diff --git a/DEPS b/DEPS
index ba9c181f..0925519d 100644
--- a/DEPS
+++ b/DEPS
@@ -36,7 +36,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '643ede69216c073c2dd497c382577dc9fde36b3e',
+  'skia_revision': 'fc3ea41cebb8272c3f683f9cf585ff780b18f09b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -56,7 +56,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '135b99861d0d898850754a845f607ec48f0bcccc',
+  'pdfium_revision': 'b6befb2ed2485a3805cddea86dc7574510178ea9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -88,7 +88,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '267de636c5220724645172da098015957e71bd62',
+  'catapult_revision': '462e4328f255bb41efd457a8d690427f8b7ce516',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -178,7 +178,7 @@
     Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0',
 
   'src/third_party/webgl/src':
-   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'b57946dc8d26325c332f3644c646dcc795c68bdc',
+   Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '46ec84c307584e6ffebc327958d56d89c36e6c27',
 
   'src/third_party/webdriver/pylib':
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 942b0c36..df161d1d 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -352,8 +352,8 @@
     bool overridable,
     bool strict_enforcement,
     bool expired_previous_decision,
-    const base::Callback<void(bool)>& callback,
-    content::CertificateRequestResultType* result) {
+    const base::Callback<void(content::CertificateRequestResultType)>&
+        callback) {
   AwContentsClientBridgeBase* client =
       AwContentsClientBridgeBase::FromWebContents(web_contents);
   bool cancel_request = true;
@@ -364,7 +364,7 @@
                                   callback,
                                   &cancel_request);
   if (cancel_request)
-    *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
+    callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
 }
 
 void AwContentBrowserClient::SelectClientCertificate(
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index afe07ca..df59173 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -89,8 +89,8 @@
       bool overridable,
       bool strict_enforcement,
       bool expired_previous_decision,
-      const base::Callback<void(bool)>& callback,
-      content::CertificateRequestResultType* result) override;
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback) override;
   void SelectClientCertificate(
       content::WebContents* web_contents,
       net::SSLCertRequestInfo* cert_request_info,
diff --git a/android_webview/browser/aw_contents_client_bridge_base.h b/android_webview/browser/aw_contents_client_bridge_base.h
index 83fae9bf..d8d4d81 100644
--- a/android_webview/browser/aw_contents_client_bridge_base.h
+++ b/android_webview/browser/aw_contents_client_bridge_base.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/supports_user_data.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/javascript_dialog_manager.h"
 
 class GURL;
@@ -41,11 +42,13 @@
 
   virtual ~AwContentsClientBridgeBase();
 
-  virtual void AllowCertificateError(int cert_error,
-                                     net::X509Certificate* cert,
-                                     const GURL& request_url,
-                                     const base::Callback<void(bool)>& callback,
-                                     bool* cancel_request) = 0;
+  virtual void AllowCertificateError(
+      int cert_error,
+      net::X509Certificate* cert,
+      const GURL& request_url,
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback,
+      bool* cancel_request) = 0;
   virtual void SelectClientCertificate(
       net::SSLCertRequestInfo* cert_request_info,
       std::unique_ptr<content::ClientCertificateDelegate> delegate) = 0;
diff --git a/android_webview/native/aw_contents_client_bridge.cc b/android_webview/native/aw_contents_client_bridge.cc
index d05a32b..9b4e00ff 100644
--- a/android_webview/native/aw_contents_client_bridge.cc
+++ b/android_webview/native/aw_contents_client_bridge.cc
@@ -80,9 +80,8 @@
     int cert_error,
     net::X509Certificate* cert,
     const GURL& request_url,
-    const base::Callback<void(bool)>& callback,
+    const base::Callback<void(content::CertificateRequestResultType)>& callback,
     bool* cancel_request) {
-
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
 
@@ -119,7 +118,8 @@
     LOG(WARNING) << "Ignoring unexpected ssl error proceed callback";
     return;
   }
-  callback->Run(proceed);
+  callback->Run(proceed ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
+                        : content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
   pending_cert_error_callbacks_.Remove(id);
 }
 
diff --git a/android_webview/native/aw_contents_client_bridge.h b/android_webview/native/aw_contents_client_bridge.h
index 677ca5b..fc8799d 100644
--- a/android_webview/native/aw_contents_client_bridge.h
+++ b/android_webview/native/aw_contents_client_bridge.h
@@ -33,11 +33,13 @@
   ~AwContentsClientBridge() override;
 
   // AwContentsClientBridgeBase implementation
-  void AllowCertificateError(int cert_error,
-                             net::X509Certificate* cert,
-                             const GURL& request_url,
-                             const base::Callback<void(bool)>& callback,
-                             bool* cancel_request) override;
+  void AllowCertificateError(
+      int cert_error,
+      net::X509Certificate* cert,
+      const GURL& request_url,
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback,
+      bool* cancel_request) override;
   void SelectClientCertificate(
       net::SSLCertRequestInfo* cert_request_info,
       std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
@@ -80,7 +82,8 @@
 
   JavaObjectWeakGlobalRef java_ref_;
 
-  typedef const base::Callback<void(bool)> CertErrorCallback;
+  typedef const base::Callback<void(content::CertificateRequestResultType)>
+      CertErrorCallback;
   IDMap<CertErrorCallback, IDMapOwnPointer> pending_cert_error_callbacks_;
   IDMap<content::JavaScriptDialogManager::DialogClosedCallback, IDMapOwnPointer>
       pending_js_dialog_callbacks_;
diff --git a/ash/aura/wm_shell_aura.cc b/ash/aura/wm_shell_aura.cc
index 4327934..004253b 100644
--- a/ash/aura/wm_shell_aura.cc
+++ b/ash/aura/wm_shell_aura.cc
@@ -112,6 +112,12 @@
   return delegate()->IsForceMaximizeOnFirstRun();
 }
 
+void WmShellAura::SetDisplayWorkAreaInsets(WmWindow* window,
+                                           const gfx::Insets& insets) {
+  aura::Window* aura_window = WmWindowAura::GetAuraWindow(window);
+  Shell::GetInstance()->SetDisplayWorkAreaInsets(aura_window, insets);
+}
+
 bool WmShellAura::IsPinned() {
   return Shell::GetInstance()->screen_pinning_controller()->IsPinned();
 }
diff --git a/ash/aura/wm_shell_aura.h b/ash/aura/wm_shell_aura.h
index 78f34c6b..341a824 100644
--- a/ash/aura/wm_shell_aura.h
+++ b/ash/aura/wm_shell_aura.h
@@ -38,6 +38,8 @@
   display::Display GetFirstDisplay() const override;
   bool IsInUnifiedMode() const override;
   bool IsForceMaximizeOnFirstRun() override;
+  void SetDisplayWorkAreaInsets(WmWindow* window,
+                                const gfx::Insets& insets) override;
   bool IsPinned() override;
   void SetPinnedWindow(WmWindow* window) override;
   bool CanShowWindowForUser(WmWindow* window) override;
diff --git a/ash/common/wm_shell.h b/ash/common/wm_shell.h
index 790809a..02dbdfc 100644
--- a/ash/common/wm_shell.h
+++ b/ash/common/wm_shell.h
@@ -23,6 +23,7 @@
 }
 
 namespace gfx {
+class Insets;
 class Point;
 }
 
@@ -188,6 +189,10 @@
   // the window size.
   virtual bool IsForceMaximizeOnFirstRun() = 0;
 
+  // Sets work area insets of the display containing |window|, pings observers.
+  virtual void SetDisplayWorkAreaInsets(WmWindow* window,
+                                        const gfx::Insets& insets) = 0;
+
   // Returns true if a system-modal dialog window is currently open.
   bool IsSystemModalWindowOpen();
 
diff --git a/ash/mus/bridge/wm_shell_mus.cc b/ash/mus/bridge/wm_shell_mus.cc
index 7215b94..254b52b 100644
--- a/ash/mus/bridge/wm_shell_mus.cc
+++ b/ash/mus/bridge/wm_shell_mus.cc
@@ -240,6 +240,11 @@
   return false;
 }
 
+void WmShellMus::SetDisplayWorkAreaInsets(WmWindow* window,
+                                          const gfx::Insets& insets) {
+  NOTIMPLEMENTED();
+}
+
 bool WmShellMus::IsPinned() {
   NOTIMPLEMENTED();
   return false;
diff --git a/ash/mus/bridge/wm_shell_mus.h b/ash/mus/bridge/wm_shell_mus.h
index 0387f00..ae1b3890 100644
--- a/ash/mus/bridge/wm_shell_mus.h
+++ b/ash/mus/bridge/wm_shell_mus.h
@@ -66,6 +66,8 @@
   display::Display GetFirstDisplay() const override;
   bool IsInUnifiedMode() const override;
   bool IsForceMaximizeOnFirstRun() override;
+  void SetDisplayWorkAreaInsets(WmWindow* window,
+                                const gfx::Insets& insets) override;
   bool IsPinned() override;
   void SetPinnedWindow(WmWindow* window) override;
   bool CanShowWindowForUser(WmWindow* window) override;
diff --git a/ash/mus/window_manager_application.cc b/ash/mus/window_manager_application.cc
index 031eced..9acd365 100644
--- a/ash/mus/window_manager_application.cc
+++ b/ash/mus/window_manager_application.cc
@@ -111,12 +111,13 @@
   InitWindowManager(window_tree_client);
 }
 
-bool WindowManagerApplication::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::ShelfLayout>(this);
-  connection->AddInterface<mojom::UserWindowController>(this);
-  connection->AddInterface<ui::mojom::AcceleratorRegistrar>(this);
-  if (connection->GetRemoteIdentity().name() == "mojo:mash_session") {
-    connector()->ConnectToInterface(connection->GetRemoteIdentity(), &session_);
+bool WindowManagerApplication::OnConnect(const shell::Identity& remote_identity,
+                                         shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::ShelfLayout>(this);
+  registry->AddInterface<mojom::UserWindowController>(this);
+  registry->AddInterface<ui::mojom::AcceleratorRegistrar>(this);
+  if (remote_identity.name() == "mojo:mash_session") {
+    connector()->ConnectToInterface(remote_identity, &session_);
     session_->AddScreenlockStateListener(
         screenlock_state_listener_binding_.CreateInterfacePtrAndBind());
   }
diff --git a/ash/mus/window_manager_application.h b/ash/mus/window_manager_application.h
index 15b6d88..b7946277 100644
--- a/ash/mus/window_manager_application.h
+++ b/ash/mus/window_manager_application.h
@@ -66,7 +66,8 @@
 
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // shell::InterfaceFactory<mojom::ShelfLayout>:
   void Create(const shell::Identity& remote_identity,
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index 2dedc94..61f1c45 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -193,8 +193,7 @@
 // ShelfLayoutManager ----------------------------------------------------------
 
 ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf_widget)
-    : root_window_(shelf_widget->GetNativeView()->GetRootWindow()),
-      updating_bounds_(false),
+    : updating_bounds_(false),
       shelf_widget_(shelf_widget),
       workspace_controller_(NULL),
       window_overlaps_shelf_(false),
@@ -481,7 +480,8 @@
   // window.
   if (WmShell::Get()->GetSessionStateDelegate()->IsUserSessionBlocked() &&
       keyboard_is_about_to_hide) {
-    Shell::GetInstance()->SetDisplayWorkAreaInsets(root_window_, gfx::Insets());
+    WmWindow* window = WmLookup::Get()->GetWindowForWidget(shelf_widget_);
+    WmShell::Get()->SetDisplayWorkAreaInsets(window, gfx::Insets());
   }
 }
 
@@ -693,7 +693,8 @@
       // if keyboard is not shown.
       if (!state_.is_adding_user_screen || !keyboard_bounds_.IsEmpty())
         insets = target_bounds.work_area_insets;
-      Shell::GetInstance()->SetDisplayWorkAreaInsets(root_window_, insets);
+      WmWindow* window = WmLookup::Get()->GetWindowForWidget(shelf_widget_);
+      WmShell::Get()->SetDisplayWorkAreaInsets(window, insets);
     }
   }
 
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h
index ab237b2..dfde44a 100644
--- a/ash/shelf/shelf_layout_manager.h
+++ b/ash/shelf/shelf_layout_manager.h
@@ -301,11 +301,6 @@
   void CompleteGestureDrag(const ui::GestureEvent& gesture);
   void CancelGestureDrag();
 
-  // The RootWindow is cached so that we don't invoke Shell::GetInstance() from
-  // our destructor. We avoid that as at the time we're deleted Shell is being
-  // deleted too.
-  aura::Window* root_window_;
-
   // True when inside UpdateBoundsAndOpacity() method. Used to prevent calling
   // UpdateBoundsAndOpacity() again from SetChildBounds().
   bool updating_bounds_;
diff --git a/ash/shell.h b/ash/shell.h
index 542d5725..d86fd28 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -216,10 +216,7 @@
   views::NonClientFrameView* CreateDefaultNonClientFrameView(
       views::Widget* widget);
 
-  // Sets the work area insets of the display that contains |window|,
-  // this notifies observers too.
-  // TODO(sky): this no longer really replicates what happens and is unreliable.
-  // Remove this.
+  // Sets work area insets of the display containing |window|, pings observers.
   void SetDisplayWorkAreaInsets(aura::Window* window,
                                 const gfx::Insets& insets);
 
diff --git a/ash/sysui/sysui_application.cc b/ash/sysui/sysui_application.cc
index c0043eb..cad9326 100644
--- a/ash/sysui/sysui_application.cc
+++ b/ash/sysui/sysui_application.cc
@@ -322,9 +322,10 @@
   input_device_client_.Connect(std::move(server));
 }
 
-bool SysUIApplication::OnConnect(::shell::Connection* connection) {
-  connection->AddInterface<mash::shelf::mojom::ShelfController>(this);
-  connection->AddInterface<mojom::WallpaperController>(this);
+bool SysUIApplication::OnConnect(const ::shell::Identity& remote_identity,
+                                 ::shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mash::shelf::mojom::ShelfController>(this);
+  registry->AddInterface<mojom::WallpaperController>(this);
   return true;
 }
 
diff --git a/ash/sysui/sysui_application.h b/ash/sysui/sysui_application.h
index 797a304..8d6d61c 100644
--- a/ash/sysui/sysui_application.h
+++ b/ash/sysui/sysui_application.h
@@ -31,7 +31,8 @@
  private:
   // shell::Service:
   void OnStart(const ::shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const ::shell::Identity& remote_identity,
+                 ::shell::InterfaceRegistry* registry) override;
 
   // InterfaceFactory<mash::shelf::mojom::ShelfController>:
   void Create(const shell::Identity& remote_identity,
diff --git a/ash/touch_hud/mus/touch_hud_application.cc b/ash/touch_hud/mus/touch_hud_application.cc
index fd87faf..7e9eb06 100644
--- a/ash/touch_hud/mus/touch_hud_application.cc
+++ b/ash/touch_hud/mus/touch_hud_application.cc
@@ -66,8 +66,9 @@
       views::WindowManagerConnection::Create(connector(), identity);
 }
 
-bool TouchHudApplication::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mash::mojom::Launchable>(this);
+bool TouchHudApplication::OnConnect(const shell::Identity& remote_identity,
+                                    shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mash::mojom::Launchable>(this);
   return true;
 }
 
diff --git a/ash/touch_hud/mus/touch_hud_application.h b/ash/touch_hud/mus/touch_hud_application.h
index c23e857..0d9144e 100644
--- a/ash/touch_hud/mus/touch_hud_application.h
+++ b/ash/touch_hud/mus/touch_hud_application.h
@@ -32,7 +32,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mojom::Launchable:
   void Launch(uint32_t what, mash::mojom::LaunchMode how) override;
diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc
index 3a58f358..72712ed0 100644
--- a/ash/wm/drag_window_resizer_unittest.cc
+++ b/ash/wm/drag_window_resizer_unittest.cc
@@ -78,7 +78,6 @@
     gfx::Rect root_bounds(root->bounds());
     EXPECT_EQ(kRootHeight, root_bounds.height());
     EXPECT_EQ(800, root_bounds.width());
-    Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
     window_.reset(new aura::Window(&delegate_));
     window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
     window_->Init(ui::LAYER_NOT_DRAWN);
diff --git a/base/feature_list.cc b/base/feature_list.cc
index 435165e1..89b105d 100644
--- a/base/feature_list.cc
+++ b/base/feature_list.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -197,10 +198,19 @@
 }
 
 // static
-void FeatureList::ClearInstanceForTesting() {
-  delete g_instance;
+std::unique_ptr<FeatureList> FeatureList::ClearInstanceForTesting() {
+  FeatureList* old_instance = g_instance;
   g_instance = nullptr;
   g_initialized_from_accessor = false;
+  return base::WrapUnique(old_instance);
+}
+
+// static
+void FeatureList::RestoreInstanceForTesting(
+    std::unique_ptr<FeatureList> instance) {
+  DCHECK(!g_instance);
+  // Note: Intentional leak of global singleton.
+  g_instance = instance.release();
 }
 
 void FeatureList::FinalizeInitialization() {
diff --git a/base/feature_list.h b/base/feature_list.h
index e9ed00a..698ecd5 100644
--- a/base/feature_list.h
+++ b/base/feature_list.h
@@ -165,8 +165,16 @@
   // process. This should only be called once and |instance| must not be null.
   static void SetInstance(std::unique_ptr<FeatureList> instance);
 
-  // Clears the previously-registered singleton instance for tests.
-  static void ClearInstanceForTesting();
+  // Clears the previously-registered singleton instance for tests and returns
+  // the old instance.
+  // Note: Most tests should never call this directly. Instead consider using
+  // base::test::ScopedFeatureList.
+  static std::unique_ptr<FeatureList> ClearInstanceForTesting();
+
+  // Sets a given (initialized) |instance| to be the singleton feature list,
+  // for testing. Existing instance must be null. This is primarily intended
+  // to support base::test::ScopedFeatureList helper class.
+  static void RestoreInstanceForTesting(std::unique_ptr<FeatureList> instance);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(FeatureListTest, CheckFeatureIdentity);
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 51863a2a..bc89f8dd 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -64,6 +64,8 @@
     "power_monitor_test_base.h",
     "scoped_command_line.cc",
     "scoped_command_line.h",
+    "scoped_feature_list.cc",
+    "scoped_feature_list.h",
     "scoped_locale.cc",
     "scoped_locale.h",
     "scoped_path_override.cc",
diff --git a/base/test/scoped_feature_list.cc b/base/test/scoped_feature_list.cc
new file mode 100644
index 0000000..f5fb7816
--- /dev/null
+++ b/base/test/scoped_feature_list.cc
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/scoped_feature_list.h"
+
+namespace base {
+namespace test {
+
+ScopedFeatureList::ScopedFeatureList() {}
+
+ScopedFeatureList::~ScopedFeatureList() {
+  if (original_feature_list_) {
+    base::FeatureList::ClearInstanceForTesting();
+    base::FeatureList::RestoreInstanceForTesting(
+        std::move(original_feature_list_));
+  }
+}
+
+void ScopedFeatureList::Init() {
+  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+  feature_list->InitializeFromCommandLine(std::string(), std::string());
+  InitWithFeatureList(std::move(feature_list));
+}
+
+void ScopedFeatureList::InitWithFeatureList(
+    std::unique_ptr<FeatureList> feature_list) {
+  DCHECK(!original_feature_list_);
+  original_feature_list_ = base::FeatureList::ClearInstanceForTesting();
+  base::FeatureList::SetInstance(std::move(feature_list));
+}
+
+void ScopedFeatureList::InitFromCommandLine(
+    const std::string& enable_features,
+    const std::string& disable_features) {
+  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+  feature_list->InitializeFromCommandLine(enable_features, disable_features);
+  InitWithFeatureList(std::move(feature_list));
+}
+
+void ScopedFeatureList::InitAndEnableFeature(const base::Feature& feature) {
+  InitFromCommandLine(feature.name, std::string());
+}
+
+void ScopedFeatureList::InitAndDisableFeature(const base::Feature& feature) {
+  InitFromCommandLine(std::string(), feature.name);
+}
+
+}  // namespace test
+}  // namespace base
diff --git a/base/test/scoped_feature_list.h b/base/test/scoped_feature_list.h
new file mode 100644
index 0000000..02603e1
--- /dev/null
+++ b/base/test/scoped_feature_list.h
@@ -0,0 +1,51 @@
+// 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 BASE_TEST_SCOPED_FEATURE_LIST_H_
+#define BASE_TEST_SCOPED_FEATURE_LIST_H_
+
+#include "base/feature_list.h"
+
+namespace base {
+namespace test {
+
+// ScopedFeatureList resets the global FeatureList instance to a new empty
+// instance and restores the original instance upon destruction.
+// Note: Re-using the same object is not allowed. To reset the feature
+// list and initialize it anew, destroy an existing scoped list and init
+// a new one.
+class ScopedFeatureList final {
+ public:
+  ScopedFeatureList();
+  ~ScopedFeatureList();
+
+  // Initializes and registers a FeatureList instance with no overrides.
+  void Init();
+
+  // Initializes and registers the given FeatureList instance.
+  void InitWithFeatureList(std::unique_ptr<FeatureList> feature_list);
+
+  // Initializes and registers a FeatureList instance with the given
+  // enabled and disabled features (comma-separated names).
+  void InitFromCommandLine(const std::string& enable_features,
+                           const std::string& disable_features);
+
+  // Initializes and registers a FeatureList instance enabling a single
+  // feature.
+  void InitAndEnableFeature(const base::Feature& feature);
+
+  // Initializes and registers a FeatureList instance disabling a single
+  // feature.
+  void InitAndDisableFeature(const base::Feature& feature);
+
+ private:
+  std::unique_ptr<FeatureList> original_feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedFeatureList);
+};
+
+}  // namespace test
+}  // namespace base
+
+#endif  // BASE_TEST_SCOPED_FEATURE_LIST_H_
diff --git a/blimp/client/core/BUILD.gn b/blimp/client/core/BUILD.gn
index 6cfad7d..94a51ae 100644
--- a/blimp/client/core/BUILD.gn
+++ b/blimp/client/core/BUILD.gn
@@ -7,12 +7,7 @@
   import("//build/config/android/rules.gni")
 }
 
-declare_args() {
-  # Enables the blimp client. This is required to get the actual implementation
-  # of blimp.
-  # By default, only a dummy-implementation is provided.
-  enable_blimp_client = false
-}
+import("//blimp/client/core/config.gni")
 
 # This target is here to let //chrome depend on //blimp/client/public
 # and automatically get the correct implementation of //blimp/client/core
diff --git a/blimp/client/core/config.gni b/blimp/client/core/config.gni
new file mode 100644
index 0000000..53e5d804
--- /dev/null
+++ b/blimp/client/core/config.gni
@@ -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.
+
+declare_args() {
+  # Enables the blimp client. This is required to get the actual implementation
+  # of blimp.
+  # By default, only a dummy-implementation is provided.
+  enable_blimp_client = false
+}
diff --git a/build/args/bots/official.desktop/blimp-engine.gn b/build/args/bots/official.android/blimp-engine.gn
similarity index 100%
rename from build/args/bots/official.desktop/blimp-engine.gn
rename to build/args/bots/official.android/blimp-engine.gn
diff --git a/build/config/ios/BUILD.gn b/build/config/ios/BUILD.gn
index ac709ae..0dda3e5 100644
--- a/build/config/ios/BUILD.gn
+++ b/build/config/ios/BUILD.gn
@@ -60,3 +60,7 @@
     "XCTest.framework",
   ]
 }
+
+group("xctest") {
+  public_configs = [ ":xctest_config" ]
+}
diff --git a/build/config/ios/codesign.py b/build/config/ios/codesign.py
index b7fc8bef..364640e 100644
--- a/build/config/ios/codesign.py
+++ b/build/config/ios/codesign.py
@@ -13,13 +13,6 @@
 import tempfile
 
 
-class InstallationError(Exception):
-  """Signals a local installation error that prevents code signing."""
-
-  def __init__(self, fmt, *args):
-    super(Exception, self).__init__(fmt % args)
-
-
 def GetProvisioningProfilesDir():
   """Returns the location of the installed mobile provisioning profiles.
 
@@ -151,36 +144,18 @@
     plistlib.writePlist(self._data, target_path)
 
 
-def FindProvisioningProfile(bundle_identifier, provisioning_profile_short_name):
+def FindProvisioningProfile(bundle_identifier, required):
   """Finds mobile provisioning profile to use to sign bundle.
 
   Args:
     bundle_identifier: the identifier of the bundle to sign.
-    provisioning_profile_short_path: optional short name of the mobile
-        provisioning profile file to use to sign (will still be checked
-        to see if it can sign bundle).
 
   Returns:
     The ProvisioningProfile object that can be used to sign the Bundle
     object or None if no matching provisioning profile was found.
   """
-  provisioning_profiles_dir = GetProvisioningProfilesDir()
-
-  # First check if there is a mobile provisioning profile installed with
-  # the requested short name. If this is the case, restrict the search to
-  # that mobile provisioning profile, otherwise consider all the installed
-  # mobile provisioning profiles.
-  provisioning_profile_paths = []
-  if provisioning_profile_short_name:
-    provisioning_profile_path = os.path.join(
-        provisioning_profiles_dir,
-        provisioning_profile_short_name + '.mobileprovision')
-    if os.path.isfile(provisioning_profile_path):
-      provisioning_profile_paths.append(provisioning_profile_path)
-
-  if not provisioning_profile_paths:
-    provisioning_profile_paths = glob.glob(
-        os.path.join(provisioning_profiles_dir, '*.mobileprovision'))
+  provisioning_profile_paths = glob.glob(
+      os.path.join(GetProvisioningProfilesDir(), '*.mobileprovision'))
 
   # Iterate over all installed mobile provisioning profiles and filter those
   # that can be used to sign the bundle.
@@ -191,6 +166,11 @@
       valid_provisioning_profiles.append(provisioning_profile)
 
   if not valid_provisioning_profiles:
+    if required:
+      sys.stderr.write(
+          'No mobile provisioning profile found for "%s".\n' %
+          bundle_identifier)
+      sys.exit(1)
     return None
 
   # Select the most specific mobile provisioning profile, i.e. the one with
@@ -200,18 +180,34 @@
       key=lambda p: len(p.application_identifier_pattern))
 
 
-def InstallFramework(framework_path, bundle, args):
+def CodeSignBundle(bundle_path, identity, extra_args):
+  process = subprocess.Popen(['xcrun', 'codesign', '--force', '--sign',
+      identity, '--timestamp=none'] + list(extra_args) + [bundle_path],
+      stderr=subprocess.PIPE)
+  _, stderr = process.communicate()
+  if process.returncode:
+    sys.stderr.write(stderr)
+    sys.exit(process.returncode)
+  for line in stderr.splitlines():
+    if line.endswith(': replacing existing signature'):
+      # Ignore warning about replacing existing signature as this should only
+      # happen when re-signing system frameworks (and then it is expected).
+      continue
+    sys.stderr.write(line)
+    sys.stderr.write('\n')
+
+
+def InstallSystemFramework(framework_path, bundle_path, args):
   """Install framework from |framework_path| to |bundle| and code-re-sign it."""
   installed_framework_path = os.path.join(
-      bundle.path, 'Frameworks', os.path.basename(framework_path))
+      bundle_path, 'Frameworks', os.path.basename(framework_path))
 
   if os.path.exists(installed_framework_path):
     shutil.rmtree(installed_framework_path)
 
   shutil.copytree(framework_path, installed_framework_path)
-
-  framework_bundle = Bundle(installed_framework_path)
-  CodeSignBundle(framework_bundle.binary_path, framework_bundle, args, True)
+  CodeSignBundle(installed_framework_path, args.identity,
+      ['--deep', '--preserve-metadata=identifier,entitlements'])
 
 
 def GenerateEntitlements(path, provisioning_profile, bundle_identifier):
@@ -235,121 +231,127 @@
   return entitlements
 
 
-def CodeSignBundle(binary, bundle, args, preserve=False):
-  """Cryptographically signs bundle.
+class Action(object):
 
-  Args:
-    bundle: the Bundle object to sign.
-    args: a dictionary with configuration settings for the code signature,
-        need to define 'entitlements_path', 'provisioning_profile_short_name',
-        'deep_signature' and 'identify' keys.
-  """
-  provisioning_profile = FindProvisioningProfile(
-      bundle.identifier, args.provisioning_profile_short_name)
-  if provisioning_profile:
-    provisioning_profile.Install(bundle)
-  else:
-    sys.stderr.write(
-        'Warning: no mobile provisioning profile found for "%s", some features '
-        'may not be functioning properly.\n' % bundle.identifier)
+  """Class implementing one action supported by the script."""
 
-  if preserve:
-    process = subprocess.Popen([
-        'xcrun', 'codesign', '--force',
-        '--sign', args.identity if args.identity else '-',
-        '--deep', '--preserve-metadata=identifier,entitlements',
-        '--timestamp=none', bundle.path], stderr=subprocess.PIPE)
-    _, stderr = process.communicate()
-    if process.returncode:
-      sys.stderr.write(stderr)
-      sys.exit(process.returncode)
-    for line in stderr.splitlines():
-      # Ignore expected warning as we are replacing the signature on purpose.
-      if not line.endswith(': replacing existing signature'):
-        sys.stderr.write(line + '\n')
-  else:
-    signature_file = os.path.join(
-        bundle.path, '_CodeSignature', 'CodeResources')
+  @classmethod
+  def Register(cls, subparsers):
+    parser = subparsers.add_parser(cls.name, help=cls.help)
+    parser.set_defaults(func=cls._Execute)
+    cls._Register(parser)
+
+
+class CodeSignBundleAction(Action):
+
+  """Class implementing the code-sign-bundle action."""
+
+  name = 'code-sign-bundle'
+  help = 'perform code signature for a bundle'
+
+  @staticmethod
+  def _Register(parser):
+    parser.add_argument(
+        '--entitlements', '-e', dest='entitlements_path',
+        help='path to the entitlements file to use')
+    parser.add_argument(
+        'path', help='path to the iOS bundle to codesign')
+    parser.add_argument(
+        '--identity', '-i', required=True,
+        help='identity to use to codesign')
+    parser.add_argument(
+        '--binary', '-b', required=True,
+        help='path to the iOS bundle binary')
+    parser.add_argument(
+        '--framework', '-F', action='append', default=[], dest='frameworks',
+        help='install and resign system framework')
+    parser.add_argument(
+        '--disable-code-signature', action='store_false', dest='sign',
+        help='disable code signature')
+    parser.set_defaults(sign=True)
+
+  @staticmethod
+  def _Execute(args):
+    if not args.identity:
+      args.identity = '-'
+
+    bundle = Bundle(args.path)
+
+    # Find mobile provisioning profile and embeds it into the bundle (if a code
+    # signing identify has been provided, fails if no valid mobile provisioning
+    # is found).
+    provisioning_profile_required = args.identity != '-'
+    provisioning_profile = FindProvisioningProfile(
+        bundle.identifier, provisioning_profile_required)
+    if provisioning_profile:
+      provisioning_profile.Install(bundle)
+
+    # Delete existing code signature.
+    signature_file = os.path.join(args.path, '_CodeSignature', 'CodeResources')
     if os.path.isfile(signature_file):
       os.unlink(signature_file)
 
+    # Install system frameworks if requested.
+    for framework_path in args.frameworks:
+      InstallSystemFramework(framework_path, args.path, args)
+
+    # Copy main binary into bundle.
     if os.path.isfile(bundle.binary_path):
       os.unlink(bundle.binary_path)
-    shutil.copy(binary, bundle.binary_path)
+    shutil.copy(args.binary, bundle.binary_path)
 
-    codesign_command = [
-        'xcrun', 'codesign', '--force', '--sign',
-        args.identity if args.identity else '-',
-        '--timestamp=none', bundle.path,
-    ]
+    if not args.sign:
+      return
 
-    with tempfile.NamedTemporaryFile(suffix='.xcent') as temporary_file_path:
-      if provisioning_profile and args.identity:
-        entitlements = GenerateEntitlements(
-            args.entitlements_path, provisioning_profile, bundle.identifier)
-        entitlements.WriteTo(temporary_file_path.name)
-        codesign_command.extend(['--entitlements', temporary_file_path.name])
-      subprocess.check_call(codesign_command)
+    # Embeds entitlements into the code signature (if code signing identify has
+    # been provided).
+    codesign_extra_args = []
+    if provisioning_profile:
+      temporary_entitlements_file = tempfile.NamedTemporaryFile(suffix='.xcent')
+      codesign_extra_args.extend(
+          ['--entitlements', temporary_entitlements_file.name])
+
+      entitlements = GenerateEntitlements(
+          args.entitlements_path, provisioning_profile, bundle.identifier)
+      entitlements.WriteTo(temporary_entitlements_file.name)
+
+    CodeSignBundle(bundle.path, args.identity, codesign_extra_args)
 
 
-def MainCodeSignBundle(args):
-  """Adapter to call CodeSignBundle from Main."""
-  bundle = Bundle(args.path)
-  for framework in args.frameworks:
-    InstallFramework(framework, bundle, args)
-  CodeSignBundle(args.binary, bundle, args)
+class GenerateEntitlementsAction(Action):
 
+  """Class implementing the generate-entitlements action."""
 
-def MainGenerateEntitlements(args):
-  """Adapter to call GenerateEntitlements from Main."""
-  info_plist = LoadPlistFile(args.info_plist)
-  bundle_identifier = info_plist['CFBundleIdentifier']
-  provisioning_profile = FindProvisioningProfile(
-      bundle_identifier, args.provisioning_profile_short_name)
+  name = 'generate-entitlements'
+  help = 'generate entitlements file'
 
-  entitlements = GenerateEntitlements(
-      args.entitlements_path, provisioning_profile, bundle_identifier)
-  entitlements.WriteTo(args.path)
+  @staticmethod
+  def _Register(parser):
+    parser.add_argument(
+        '--entitlements', '-e', dest='entitlements_path',
+        help='path to the entitlements file to use')
+    parser.add_argument(
+        'path', help='path to the entitlements file to generate')
+    parser.add_argument(
+        '--info-plist', '-p', required=True,
+        help='path to the bundle Info.plist')
+
+  @staticmethod
+  def _Execute(args):
+    info_plist = LoadPlistFile(args.info_plist)
+    bundle_identifier = info_plist['CFBundleIdentifier']
+    provisioning_profile = FindProvisioningProfile(bundle_identifier, False)
+    entitlements = GenerateEntitlements(
+        args.entitlements_path, provisioning_profile, bundle_identifier)
+    entitlements.WriteTo(args.path)
 
 
 def Main():
   parser = argparse.ArgumentParser('codesign iOS bundles')
-  parser.add_argument(
-      '--provisioning-profile', '-p', dest='provisioning_profile_short_name',
-      help='short name of the mobile provisioning profile to use ('
-           'if undefined, will autodetect the mobile provisioning '
-           'to use)')
-  parser.add_argument(
-      '--entitlements', '-e', dest='entitlements_path',
-      help='path to the entitlements file to use')
   subparsers = parser.add_subparsers()
 
-  code_sign_bundle_parser = subparsers.add_parser(
-      'code-sign-bundle',
-      help='code sign a bundle')
-  code_sign_bundle_parser.add_argument(
-      'path', help='path to the iOS bundle to codesign')
-  code_sign_bundle_parser.add_argument(
-      '--identity', '-i', required=True,
-      help='identity to use to codesign')
-  code_sign_bundle_parser.add_argument(
-      '--binary', '-b', required=True,
-      help='path to the iOS bundle binary')
-  code_sign_bundle_parser.add_argument(
-      '--framework', '-F', action='append', default=[], dest="frameworks",
-      help='install and resign system framework')
-  code_sign_bundle_parser.set_defaults(func=MainCodeSignBundle)
-
-  generate_entitlements_parser = subparsers.add_parser(
-      'generate-entitlements',
-      help='generate entitlements file')
-  generate_entitlements_parser.add_argument(
-      'path', help='path to the entitlements file to generate')
-  generate_entitlements_parser.add_argument(
-      '--info-plist', '-p', required=True,
-      help='path to the bundle Info.plist')
-  generate_entitlements_parser.set_defaults(
-      func=MainGenerateEntitlements)
+  for action in [ CodeSignBundleAction, GenerateEntitlementsAction ]:
+    action.Register(subparsers)
 
   args = parser.parse_args()
   args.func(args)
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index 73fc8be..c670170 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -6,12 +6,11 @@
 import("//build/config/mac/base_rules.gni")
 import("//build/config/mac/symbols.gni")
 
-_toolchain_suffix = ""
-_is_fat_build = additional_toolchains != []
-if (_is_fat_build) {
-  _toolchain_suffix = "($default_toolchain)"
-  _is_fat_build_main_target = current_toolchain == default_toolchain
-}
+_is_secondary_build =
+    additional_toolchains != [] && current_toolchain != default_toolchain
+
+_code_signing_script_path = "//build/config/ios/codesign.py"
+_default_entitlements_path = "//build/config/ios/entitlements.plist"
 
 # Generates Info.plist files for Mac apps and frameworks.
 #
@@ -160,12 +159,10 @@
   # Embeds the entitlements file if building for simulator. This is optional
   # with Xcode 7 or older but required with Xcode 8. This is not necessary for
   # device build as the entitlement is embedded via the codesigning step.
-  #
-  # As the generation of the entitlement depends on the
   if (use_ios_simulator) {
     _generate_entitlements_target = _target_name + "_gen_entitlements"
     _generate_entitlements_target_with_toolchain_suffix =
-        "$_generate_entitlements_target$_toolchain_suffix"
+        "$_generate_entitlements_target($default_toolchain)"
 
     _generate_entitlements_output =
         get_label_info(_generate_entitlements_target_with_toolchain_suffix,
@@ -186,7 +183,7 @@
     ]
   }
 
-  if (_is_fat_build && !_is_fat_build_main_target) {
+  if (_is_secondary_build) {
     # For the non-default toolchain of a fat-build, the template expands to a
     # single "executable" target that creates "$root_out_dir/$_output_name".
     executable(_target_name) {
@@ -237,11 +234,9 @@
     _generate_info_plist = target_name + "_generate_info_plist"
     _bundle_data_info_plist = target_name + "_bundle_data_info_plist"
 
-    if (use_ios_simulator || ios_enable_code_signing) {
-      _entitlements_path = "//build/config/ios/entitlements.plist"
-      if (defined(invoker.entitlements_path)) {
-        _entitlements_path = invoker.entitlements_path
-      }
+    _entitlements_path = _default_entitlements_path
+    if (defined(invoker.entitlements_path)) {
+      _entitlements_path = invoker.entitlements_path
     }
 
     ios_info_plist(_generate_info_plist) {
@@ -276,7 +271,7 @@
         _gen_info_plist_outputs = get_target_outputs(_gen_info_plist_target)
         _info_plist_path = _gen_info_plist_outputs[0]
 
-        script = "//build/config/ios/codesign.py"
+        script = _code_signing_script_path
         deps = [
           _gen_info_plist_target,
         ]
@@ -288,34 +283,18 @@
           _generate_entitlements_output,
         ]
         args = [
-                 "-e=" + rebase_path(_entitlements_path, root_build_dir),
                  "generate-entitlements",
+                 "-e=" + rebase_path(_entitlements_path, root_build_dir),
                  "-p=" + rebase_path(_info_plist_path, root_build_dir),
                ] + rebase_path(outputs, root_build_dir)
       }
     }
 
-    _link_executable = _target_name + "_executable"
+    _link_executable = _target_name + "_arch_executable"
+    _lipo_executable = _target_name + "_executable"
 
-    if (ios_enable_code_signing) {
-      _link_executable_visibility = [ ":$_target_name" ]
-    } else {
-      _bundle_data_executable = target_name + "_bundle_data_executable"
-      _link_executable_visibility = [ ":$_bundle_data_executable" ]
-    }
-
-    # For a fat-build, the different "executable" outputs will be used to
-    # create the final binary using "lipo". As the corresponding target has
-    # the same role as the "executable" target in a thin build, copy the
-    # visibility and redefine some variables.
-    if (_is_fat_build) {
-      _lipo_executable = _link_executable
-      _lipo_executable_visibility = _link_executable_visibility
-
-      _link_executable_visibility = []
-      _link_executable_visibility = [ ":$_lipo_executable" ]
-      _link_executable = _target_name + "_arch_executable"
-    }
+    _link_executable_visibility = [ ":$_lipo_executable" ]
+    _lipo_executable_visibility = [ ":$_target_name" ]
 
     executable(_link_executable) {
       forward_variables_from(invoker,
@@ -339,11 +318,7 @@
 
       output_name = _output_name
       output_prefix_override = true
-      if (_is_fat_build) {
-        output_dir = "$target_out_dir/$current_cpu"
-      } else {
-        output_dir = target_out_dir
-      }
+      output_dir = "$target_out_dir/$current_cpu"
 
       if (!defined(deps)) {
         deps = []
@@ -366,112 +341,74 @@
       libs += [ "UIKit.framework" ]
     }
 
-    if (_is_fat_build) {
-      # Create the multi-architecture binary from all the single architecture
-      # binaries using "lipo". This target exists for the default toolchain
-      # of a fat-build only and depends on the expansion of "ios_app_bundle"
-      # for the other toolchains (i.e. a single "executable" target).
-      #
-      # This action only happens once per "ios_app_bundle" template (for the
-      # main toolchain).
-      action(_lipo_executable) {
-        forward_variables_from(invoker, [ "testonly" ])
-        visibility = _lipo_executable_visibility
-        script = "//build/toolchain/mac/linker_driver.py"
-        outputs = [
-          "$target_out_dir/$_output_name",
+    # Create the multi-architecture binary from all the single architecture
+    # binaries using "lipo". This target exists for the default toolchain
+    # of a fat-build only and depends on the expansion of "ios_app_bundle"
+    # for the other toolchains (i.e. a single "executable" target).
+    #
+    # This action only happens once per "ios_app_bundle" template (for the
+    # main toolchain).
+    action(_lipo_executable) {
+      forward_variables_from(invoker, [ "testonly" ])
+      visibility = _lipo_executable_visibility
+      script = "//build/toolchain/mac/linker_driver.py"
+      outputs = [
+        "$target_out_dir/$_output_name",
+      ]
+      inputs = [
+        "$target_out_dir/$current_cpu/$_output_name",
+      ]
+      deps = [
+        ":$_link_executable",
+      ]
+      foreach(_additional_toolchain, additional_toolchains) {
+        _additional_toolchain_target = "$_target_name($_additional_toolchain)"
+        deps += [ ":$_additional_toolchain_target" ]
+        inputs += [ get_label_info(_additional_toolchain_target,
+                                   "root_out_dir") + "/$_output_name" ]
+      }
+      args = [
+               "xcrun",
+               "lipo",
+               "-create",
+               "-output",
+               rebase_path(outputs[0], root_build_dir),
+             ] + rebase_path(inputs, root_build_dir)
+
+      if (enable_dsyms) {
+        _dsyms_dir = "$root_out_dir/$_output_name.dSYM/"
+        outputs += [
+          "$_dsyms_dir/",
+          "$_dsyms_dir/Contents/Info.plist",
+          "$_dsyms_dir/Contents/Resources/DWARF/$_output_name",
         ]
-        inputs = [
-          "$target_out_dir/$current_cpu/$_output_name",
-        ]
-        deps = [
-          ":$_link_executable",
-        ]
-        foreach(_additional_toolchain, additional_toolchains) {
-          _additional_toolchain_target = "$_target_name($_additional_toolchain)"
-          deps += [ ":$_additional_toolchain_target" ]
-          inputs += [ get_label_info(_additional_toolchain_target,
-                                     "root_out_dir") + "/$_output_name" ]
-        }
-        args = [
-                 "xcrun",
-                 "lipo",
-                 "-create",
-                 "-output",
-                 rebase_path(outputs[0], root_build_dir),
-               ] + rebase_path(inputs, root_build_dir)
+        args +=
+            [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
+      }
 
-        if (enable_dsyms) {
-          _dsyms_dir = "$root_out_dir/$_output_name.dSYM/"
-          outputs += [
-            "$_dsyms_dir/",
-            "$_dsyms_dir/Contents/Info.plist",
-            "$_dsyms_dir/Contents/Resources/DWARF/$_output_name",
-          ]
-          args +=
-              [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
-        }
-
-        if (enable_stripping) {
-          # Check whether //build/config/mac:strip_all has been removed from
-          # the configs variable (as this is how stripping is disabled for a
-          # single target).
-          _strip_all_in_config = false
-          if (defined(invoker.configs)) {
-            foreach(_config, invoker.configs) {
-              if (_config == "//build/config/mac:strip_all") {
-                _strip_all_in_config = true
-              }
-            }
-          }
-
-          if (_strip_all_in_config) {
-            args += [ "-Wcrl,strip,-x,-S" ]
-
-            if (save_unstripped_output) {
-              outputs += [ outputs[0] + ".unstripped" ]
-              args += [ "-Wcrl,unstripped," +
-                        rebase_path(get_path_info(outputs[0], "dir"),
-                                    root_build_dir) ]
+      if (enable_stripping) {
+        # Check whether //build/config/mac:strip_all has been removed from
+        # the configs variable (as this is how stripping is disabled for a
+        # single target).
+        _strip_all_in_config = false
+        if (defined(invoker.configs)) {
+          foreach(_config, invoker.configs) {
+            if (_config == "//build/config/mac:strip_all") {
+              _strip_all_in_config = true
             }
           }
         }
-      }
-    }
 
-    if (!ios_enable_code_signing) {
-      # If codesigning is enabled, the binary will be copied into the bundle
-      # by the codesigning script (as the binary is updated by the signature).
-      # Otherwise, this "bundle_data" declares the location of the binary in
-      # the .app bundle.
-      bundle_data(_bundle_data_executable) {
-        forward_variables_from(invoker, [ "testonly" ])
-        visibility = [ ":$_target_name" ]
-        outputs = [
-          "{{bundle_executable_dir}}/$_output_name",
-        ]
-        if (_is_fat_build) {
-          public_deps = [
-            ":$_lipo_executable",
-          ]
-        } else {
-          public_deps = [
-            ":$_link_executable",
-          ]
+        if (_strip_all_in_config) {
+          args += [ "-Wcrl,strip,-x,-S" ]
+
+          if (save_unstripped_output) {
+            outputs += [ outputs[0] + ".unstripped" ]
+            args += [ "-Wcrl,unstripped," +
+                      rebase_path(get_path_info(outputs[0], "dir"),
+                                  root_build_dir) ]
+          }
         }
-        sources = [
-          "$target_out_dir/$_output_name",
-        ]
-      }
-    }
-
-    if (!ios_enable_code_signing && defined(invoker.extra_system_frameworks)) {
-      bundle_data(_target_name + "_extra_system_frameworks") {
-        visibility = [ ":$_target_name" ]
-        sources = invoker.extra_system_frameworks
-        outputs = [
-          "{{bundle_resources_dir}}/Frameworks/{{source_file_part}}",
-        ]
       }
     }
 
@@ -493,18 +430,7 @@
       if (!defined(public_deps)) {
         public_deps = []
       }
-      if (ios_enable_code_signing) {
-        if (_is_fat_build) {
-          public_deps += [ ":$_lipo_executable" ]
-        } else {
-          public_deps += [ ":$_link_executable" ]
-        }
-      } else {
-        public_deps += [ ":$_bundle_data_executable" ]
-        if (defined(invoker.extra_system_frameworks)) {
-          deps += [ ":${_target_name}_extra_system_frameworks" ]
-        }
-      }
+      public_deps += [ ":$_lipo_executable" ]
       if (defined(invoker.bundle_deps)) {
         deps += invoker.bundle_deps
       }
@@ -533,39 +459,43 @@
       bundle_executable_dir = bundle_root_dir
       bundle_plugins_dir = "$bundle_root_dir/PlugIns"
 
+      code_signing_script = _code_signing_script_path
+      code_signing_sources = [
+        _entitlements_path,
+        "$target_out_dir/$_output_name",
+      ]
+      code_signing_outputs = [ "$bundle_root_dir/$_output_name" ]
       if (ios_enable_code_signing) {
-        code_signing_script = "//build/config/ios/codesign.py"
-        code_signing_sources = [
-          _entitlements_path,
-          "$target_out_dir/$_output_name",
-        ]
-        code_signing_outputs = [
-          "$bundle_root_dir/$_output_name",
-          "$bundle_root_dir/_CodeSignature/CodeResources",
-          "$bundle_root_dir/embedded.mobileprovision",
-        ]
-        if (defined(invoker.extra_system_frameworks)) {
-          foreach(_framework, invoker.extra_system_frameworks) {
-            code_signing_outputs += [ "$bundle_root_dir/Frameworks/" +
-                                      get_path_info(_framework, "file") ]
-          }
+        code_signing_outputs +=
+            [ "$bundle_root_dir/_CodeSignature/CodeResources" ]
+      }
+      if (ios_code_signing_identity != "") {
+        code_signing_outputs += [ "$bundle_root_dir/embedded.mobileprovision" ]
+      }
+      if (defined(invoker.extra_system_frameworks)) {
+        foreach(_framework, invoker.extra_system_frameworks) {
+          code_signing_outputs += [ "$bundle_root_dir/Frameworks/" +
+                                    get_path_info(_framework, "file") ]
         }
-        code_signing_args = [
-          "-e=" + rebase_path(_entitlements_path, root_build_dir),
-          "code-sign-bundle",
-          "-i=" + ios_code_signing_identity,
-          "-b=" + rebase_path("$target_out_dir/$_output_name", root_build_dir),
-          rebase_path(bundle_root_dir, root_build_dir),
-        ]
-        if (defined(invoker.extra_system_frameworks)) {
-          # All framework in extra_system_frameworks are expected to be
-          # system framework and the path to be already system absolute
-          # so do not use rebase_path here.
-          foreach(_framework, invoker.extra_system_frameworks) {
-            code_signing_args += [ "-F=" + _framework ]
-          }
+      }
+      code_signing_args = [
+        "code-sign-bundle",
+        "-i=" + ios_code_signing_identity,
+        "-e=" + rebase_path(_entitlements_path, root_build_dir),
+        "-b=" + rebase_path("$target_out_dir/$_output_name", root_build_dir),
+        rebase_path(bundle_root_dir, root_build_dir),
+      ]
+      if (defined(invoker.extra_system_frameworks)) {
+        # All framework in extra_system_frameworks are expected to be
+        # system framework and the path to be already system absolute
+        # so do not use rebase_path here.
+        foreach(_framework, invoker.extra_system_frameworks) {
+          code_signing_args += [ "-F=" + _framework ]
         }
       }
+      if (!ios_enable_code_signing) {
+        code_signing_args += [ "--disable-code-signature" ]
+      }
     }
   }
 
@@ -897,14 +827,13 @@
   # that defines the real framework bundle (it will support the current cpu
   # as it is a fat framework).
 
-  if (_is_fat_build && !_is_fat_build_main_target) {
+  if (_is_secondary_build) {
     shared_library(_target_name) {
       forward_variables_from(invoker,
                              "*",
                              [
                                "assert_no_deps",
                                "bundle_deps",
-                               "code_signing_enabled",
                                "data_deps",
                                "info_plist",
                                "info_plist_target",
@@ -920,14 +849,14 @@
 
       if (_has_public_headers) {
         configs += [
-          ":$_framework_headers_config$_toolchain_suffix",
-          ":$_headers_map_config$_toolchain_suffix",
+          ":$_framework_headers_config($default_toolchain)",
+          ":$_headers_map_config($default_toolchain)",
         ]
 
         if (!defined(deps)) {
           deps = []
         }
-        deps += [ ":$_framework_headers_target$_toolchain_suffix" ]
+        deps += [ ":$_framework_headers_target($default_toolchain)" ]
       }
     }
 
@@ -1026,12 +955,6 @@
       }
     }
 
-    _code_signing_enabled = ios_enable_code_signing
-    if (defined(invoker.code_signing_enabled)) {
-      _code_signing_enabled =
-          invoker.code_signing_enabled && _code_signing_enabled
-    }
-
     # If the framework is unversioned, the final _target_name will be the
     # create_bundle(_framework_target), otherwise an action with the name
     # _target_name will depends on the the create_bundle() in order to prepare
@@ -1045,27 +968,14 @@
       _framework_target = _target_name + "_create_bundle"
     }
 
-    _link_shared_library_target = target_name + "_shared_library"
-    _shared_library_dir = "$target_out_dir/$_link_shared_library_target"
+    _link_shared_library_target = target_name + "_arch_shared_library"
+    _lipo_shared_library_target = target_name + "_shared_library"
 
-    if (_code_signing_enabled) {
-      _link_shared_library_visibility = [ ":$_framework_target" ]
-    } else {
-      _shared_library_bundle_data = target_name + "_shared_library_bundle_data"
-      _link_shared_library_visibility = [ ":$_shared_library_bundle_data" ]
-    }
+    _lipo_shared_library_visibility = [ ":$_framework_target" ]
+    _link_shared_library_visibility = [ ":$_lipo_shared_library_target" ]
 
-    if (_is_fat_build) {
-      _lipo_shared_library_target = _link_shared_library_target
-      _lipo_shared_library_visibility = _link_shared_library_visibility
-
-      _link_shared_library_visibility = []
-      _link_shared_library_visibility = [ ":$_lipo_shared_library_target" ]
-      _link_shared_library_target = target_name + "_arch_shared_library"
-
-      _arch_shared_library_dir = "$target_out_dir/$_link_shared_library_target"
-      _shared_library_dir = "$target_out_dir/$_lipo_shared_library_target"
-    }
+    _arch_shared_library_dir = "$target_out_dir/$_link_shared_library_target"
+    _shared_library_dir = "$target_out_dir/$_lipo_shared_library_target"
 
     shared_library(_link_shared_library_target) {
       forward_variables_from(invoker,
@@ -1073,7 +983,6 @@
                              [
                                "assert_no_deps",
                                "bundle_deps",
-                               "code_signing_enabled",
                                "data_deps",
                                "info_plist",
                                "info_plist_target",
@@ -1084,107 +993,78 @@
       output_name = _output_name
       output_prefix_override = true
       output_extension = ""
-
-      if (!_is_fat_build) {
-        output_dir = _shared_library_dir
-      } else {
-        output_dir = _arch_shared_library_dir
-      }
+      output_dir = _arch_shared_library_dir
 
       if (_has_public_headers) {
-        configs += [ ":$_headers_map_config$_toolchain_suffix" ]
+        configs += [ ":$_headers_map_config($default_toolchain)" ]
 
         if (!defined(deps)) {
           deps = []
         }
-        deps += [ ":$_framework_headers_target$_toolchain_suffix" ]
+        deps += [ ":$_framework_headers_target($default_toolchain)" ]
       }
     }
 
-    if (_is_fat_build) {
-      action(_lipo_shared_library_target) {
-        forward_variables_from(invoker, [ "testonly" ])
-        visibility = _lipo_shared_library_visibility
-        script = "//build/toolchain/mac/linker_driver.py"
-        outputs = [
-          "$_shared_library_dir/$_output_name",
-        ]
-        inputs = [
-          "$_arch_shared_library_dir/$_output_name",
-        ]
-        deps = [
-          ":$_link_shared_library_target",
-        ]
-        foreach(_additional_toolchain, additional_toolchains) {
-          _additional_toolchain_target = "$_target_name($_additional_toolchain)"
-          deps += [ ":$_additional_toolchain_target" ]
-          inputs += [ get_label_info(_additional_toolchain_target,
-                                     "target_out_dir") + "/$_output_name" ]
-        }
-        args = [
-                 "xcrun",
-                 "lipo",
-                 "-create",
-                 "-output",
-                 rebase_path(outputs[0], root_build_dir),
-               ] + rebase_path(inputs, root_build_dir)
-
-        if (enable_dsyms) {
-          _dsyms_dir = "$root_out_dir/$_output_name.dSYM/"
-          outputs += [
-            "$_dsyms_dir/",
-            "$_dsyms_dir/Contents/Info.plist",
-            "$_dsyms_dir/Contents/Resources/DWARF/$_output_name",
-          ]
-          args +=
-              [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
-        }
-
-        if (enable_stripping) {
-          # Check whether //build/config/mac:strip_all has been removed from
-          # the configs variable (as this is how stripping is disabled for a
-          # single target).
-          _strip_all_in_config = false
-          if (defined(invoker.configs)) {
-            foreach(_config, invoker.configs) {
-              if (_config == "//build/config/mac:strip_all") {
-                _strip_all_in_config = true
-              }
-            }
-          }
-
-          if (_strip_all_in_config) {
-            args += [ "-Wcrl,strip,-x,-S" ]
-
-            if (save_unstripped_output) {
-              outputs += [ outputs[0] + ".unstripped" ]
-              args += [ "-Wcrl,unstripped," +
-                        rebase_path(get_path_info(outputs[0], "dir"),
-                                    root_build_dir) ]
-            }
-          }
-        }
+    action(_lipo_shared_library_target) {
+      forward_variables_from(invoker, [ "testonly" ])
+      visibility = _lipo_shared_library_visibility
+      script = "//build/toolchain/mac/linker_driver.py"
+      outputs = [
+        "$_shared_library_dir/$_output_name",
+      ]
+      inputs = [
+        "$_arch_shared_library_dir/$_output_name",
+      ]
+      deps = [
+        ":$_link_shared_library_target",
+      ]
+      foreach(_additional_toolchain, additional_toolchains) {
+        _additional_toolchain_target = "$_target_name($_additional_toolchain)"
+        deps += [ ":$_additional_toolchain_target" ]
+        inputs += [ get_label_info(_additional_toolchain_target,
+                                   "target_out_dir") + "/$_output_name" ]
       }
-    }
+      args = [
+               "xcrun",
+               "lipo",
+               "-create",
+               "-output",
+               rebase_path(outputs[0], root_build_dir),
+             ] + rebase_path(inputs, root_build_dir)
 
-    if (!_code_signing_enabled) {
-      bundle_data(_shared_library_bundle_data) {
-        visibility = [ ":$_framework_target" ]
-        forward_variables_from(invoker, [ "testonly" ])
-        sources = [
-          "$_shared_library_dir/$_output_name",
+      if (enable_dsyms) {
+        _dsyms_dir = "$root_out_dir/$_output_name.dSYM/"
+        outputs += [
+          "$_dsyms_dir/",
+          "$_dsyms_dir/Contents/Info.plist",
+          "$_dsyms_dir/Contents/Resources/DWARF/$_output_name",
         ]
-        outputs = [
-          "{{bundle_executable_dir}}/$_output_name",
-        ]
-        if (_is_fat_build) {
-          public_deps = [
-            ":$_lipo_shared_library_target",
-          ]
-        } else {
-          public_deps = [
-            ":$_link_shared_library_target",
-          ]
+        args +=
+            [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
+      }
+
+      if (enable_stripping) {
+        # Check whether //build/config/mac:strip_all has been removed from
+        # the configs variable (as this is how stripping is disabled for a
+        # single target).
+        _strip_all_in_config = false
+        if (defined(invoker.configs)) {
+          foreach(_config, invoker.configs) {
+            if (_config == "//build/config/mac:strip_all") {
+              _strip_all_in_config = true
+            }
+          }
+        }
+
+        if (_strip_all_in_config) {
+          args += [ "-Wcrl,strip,-x,-S" ]
+
+          if (save_unstripped_output) {
+            outputs += [ outputs[0] + ".unstripped" ]
+            args += [ "-Wcrl,unstripped," +
+                      rebase_path(get_path_info(outputs[0], "dir"),
+                                  root_build_dir) ]
+          }
         }
       }
     }
@@ -1258,51 +1138,43 @@
         deps += invoker.bundle_deps
       }
 
-      if (!_code_signing_enabled) {
-        if (!defined(public_deps)) {
-          public_deps = []
-        }
-        public_deps += [ ":$_shared_library_bundle_data" ]
-      }
-
       bundle_root_dir = _framework_root_dir
       bundle_resources_dir = "$bundle_root_dir/Resources"
       bundle_executable_dir = "$bundle_root_dir"
 
-      if (_code_signing_enabled) {
-        if (!defined(deps)) {
-          deps = []
-        }
+      if (!defined(deps)) {
+        deps = []
+      }
+      deps += [ ":$_lipo_shared_library_target" ]
 
-        if (_is_fat_build) {
-          deps += [ ":$_lipo_shared_library_target" ]
-        } else {
-          deps += [ ":$_link_shared_library_target" ]
-        }
+      _entitlements_path = _default_entitlements_path
+      if (defined(invoker.entitlements_path)) {
+        _entitlements_path = invoker.entitlements_path
+      }
 
-        _entitlements_path = "//build/config/ios/entitlements.plist"
-        if (defined(invoker.entitlements_path)) {
-          _entitlements_path = invoker.entitlements_path
-        }
-
-        code_signing_script = "//build/config/ios/codesign.py"
-        code_signing_sources = [
-          _entitlements_path,
-          "$_shared_library_dir/$_output_name",
-        ]
-        code_signing_outputs = [
-          "$bundle_root_dir/$_output_name",
-          "$bundle_root_dir/_CodeSignature/CodeResources",
-          "$bundle_root_dir/embedded.mobileprovision",
-        ]
-        code_signing_args = [
-          "-e=" + rebase_path(_entitlements_path, root_build_dir),
-          "code-sign-bundle",
-          "-i=" + ios_code_signing_identity,
-          "-b=" +
-              rebase_path("$_shared_library_dir/$_output_name", root_build_dir),
-          rebase_path(bundle_root_dir, root_build_dir),
-        ]
+      code_signing_script = _code_signing_script_path
+      code_signing_sources = [
+        _entitlements_path,
+        "$_shared_library_dir/$_output_name",
+      ]
+      code_signing_outputs = [ "$bundle_root_dir/$_output_name" ]
+      if (ios_enable_code_signing) {
+        code_signing_outputs +=
+            [ "$bundle_root_dir/_CodeSignature/CodeResources" ]
+      }
+      if (ios_code_signing_identity != "") {
+        code_signing_outputs += [ "$bundle_root_dir/embedded.mobileprovision" ]
+      }
+      code_signing_args = [
+        "code-sign-bundle",
+        "-i=" + ios_code_signing_identity,
+        "-e=" + rebase_path(_entitlements_path, root_build_dir),
+        "-b=" +
+            rebase_path("$_shared_library_dir/$_output_name", root_build_dir),
+        rebase_path(bundle_root_dir, root_build_dir),
+      ]
+      if (!ios_enable_code_signing) {
+        code_signing_args += [ "--disable-code-signature" ]
       }
     }
 
@@ -1391,7 +1263,7 @@
   _host_target = _target_name + "_host"
   _host_output = _output_name + "_host"
 
-  if (_is_fat_build && !_is_fat_build_main_target) {
+  if (_is_secondary_build) {
     loadable_module(_xctest_target) {
       visibility = [ ":${_xctest_target}_loadable_module($default_toolchain)" ]
       sources = [
@@ -1422,27 +1294,12 @@
       ]
     }
 
-    _xctest_loadable_module_target = _xctest_target + "_loadable_module"
+    _xctest_loadable_module_target = _xctest_target + "_arch_loadable_module"
+    _xctest_lipo_loadable_module_target = _xctest_target + "_loadable_module"
 
-    if (!ios_enable_code_signing) {
-      _xctest_loadable_module_bundle =
-          _xctest_target + "_loadable_module_bundle"
-      _xctest_loadable_module_visibility =
-          [ ":$_xctest_loadable_module_bundle" ]
-    } else {
-      _xctest_loadable_module_visibility = [ ":$_xctest_target" ]
-    }
-
-    if (_is_fat_build) {
-      _xctest_lipo_loadable_module_target = _xctest_loadable_module_target
-      _xctest_lipo_loadable_module_visibility =
-          _xctest_loadable_module_visibility
-
-      _xctest_loadable_module_visibility = []
-      _xctest_loadable_module_visibility =
-          [ ":$_xctest_lipo_loadable_module_target" ]
-      _xctest_loadable_module_target = _xctest_target + "_arch_loadable_module"
-    }
+    _xctest_loadable_module_visibility =
+        [ ":$_xctest_lipo_loadable_module_target" ]
+    _xctest_lipo_loadable_module_visibility = [ ":$_xctest_target" ]
 
     loadable_module(_xctest_loadable_module_target) {
       visibility = _xctest_loadable_module_visibility
@@ -1451,100 +1308,72 @@
       ]
       configs += [ "//build/config/ios:xctest_config" ]
 
-      if (_is_fat_build) {
-        output_dir = "$target_out_dir/$current_cpu"
-      } else {
-        output_dir = target_out_dir
-      }
-
+      output_dir = "$target_out_dir/$current_cpu"
       output_name = _xctest_output
       output_prefix_override = true
       output_extension = ""
     }
 
-    if (_is_fat_build) {
-      action(_xctest_lipo_loadable_module_target) {
-        visibility = _xctest_lipo_loadable_module_visibility
-        script = "//build/toolchain/mac/linker_driver.py"
-        outputs = [
-          "$target_out_dir/$_xctest_output",
-        ]
-        inputs = [
-          "$target_out_dir/$current_cpu/$_xctest_output",
-        ]
-        deps = [
-          ":$_xctest_loadable_module_target",
-        ]
-        foreach(_additional_toolchain, additional_toolchains) {
-          _additional_toolchain_target = "$_target_name($_additional_toolchain)"
-          deps += [ ":$_additional_toolchain_target" ]
-          inputs += [ get_label_info(_additional_toolchain_target,
-                                     "root_out_dir") + "/$_xctest_output" ]
-        }
-        args = [
-                 "xcrun",
-                 "lipo",
-                 "-create",
-                 "-output",
-                 rebase_path(outputs[0], root_build_dir),
-               ] + rebase_path(inputs, root_build_dir)
-
-        if (enable_dsyms) {
-          _dsyms_dir = "$root_out_dir/$_output_name.dSYM/"
-          outputs += [
-            "$_dsyms_dir/",
-            "$_dsyms_dir/Contents/Info.plist",
-            "$_dsyms_dir/Contents/Resources/DWARF/$_output_name",
-          ]
-          args +=
-              [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
-        }
-
-        if (enable_stripping) {
-          # Check whether //build/config/mac:strip_all has been removed from
-          # the configs variable (as this is how stripping is disabled for a
-          # single target).
-          _strip_all_in_config = false
-          if (defined(invoker.configs)) {
-            foreach(_config, invoker.configs) {
-              if (_config == "//build/config/mac:strip_all") {
-                _strip_all_in_config = true
-              }
-            }
-          }
-
-          if (_strip_all_in_config) {
-            args += [ "-Wcrl,strip,-x,-S" ]
-
-            if (save_unstripped_output) {
-              outputs += [ outputs[0] + ".unstripped" ]
-              args += [ "-Wcrl,unstripped," +
-                        rebase_path(get_path_info(outputs[0], "dir"),
-                                    root_build_dir) ]
-            }
-          }
-        }
+    action(_xctest_lipo_loadable_module_target) {
+      visibility = _xctest_lipo_loadable_module_visibility
+      script = "//build/toolchain/mac/linker_driver.py"
+      outputs = [
+        "$target_out_dir/$_xctest_output",
+      ]
+      inputs = [
+        "$target_out_dir/$current_cpu/$_xctest_output",
+      ]
+      deps = [
+        ":$_xctest_loadable_module_target",
+      ]
+      foreach(_additional_toolchain, additional_toolchains) {
+        _additional_toolchain_target = "$_target_name($_additional_toolchain)"
+        deps += [ ":$_additional_toolchain_target" ]
+        inputs += [ get_label_info(_additional_toolchain_target,
+                                   "root_out_dir") + "/$_xctest_output" ]
       }
-    }
+      args = [
+               "xcrun",
+               "lipo",
+               "-create",
+               "-output",
+               rebase_path(outputs[0], root_build_dir),
+             ] + rebase_path(inputs, root_build_dir)
 
-    if (!ios_enable_code_signing) {
-      bundle_data(_xctest_loadable_module_bundle) {
-        visibility = [ ":$_xctest_target" ]
-        if (_is_fat_build) {
-          public_deps = [
-            ":$_xctest_lipo_loadable_module_target",
-          ]
-        } else {
-          public_deps = [
-            ":$_xctest_loadable_module_target",
-          ]
+      if (enable_dsyms) {
+        _dsyms_dir = "$root_out_dir/$_output_name.dSYM/"
+        outputs += [
+          "$_dsyms_dir/",
+          "$_dsyms_dir/Contents/Info.plist",
+          "$_dsyms_dir/Contents/Resources/DWARF/$_output_name",
+        ]
+        args +=
+            [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ]
+      }
+
+      if (enable_stripping) {
+        # Check whether //build/config/mac:strip_all has been removed from
+        # the configs variable (as this is how stripping is disabled for a
+        # single target).
+        _strip_all_in_config = false
+        if (defined(invoker.configs)) {
+          foreach(_config, invoker.configs) {
+            if (_config == "//build/config/mac:strip_all") {
+              _strip_all_in_config = true
+            }
+          }
         }
-        sources = [
-          "$target_out_dir/$_xctest_output",
-        ]
-        outputs = [
-          "{{bundle_root_dir}}/$_xctest_output",
-        ]
+
+        if (_strip_all_in_config) {
+          args += [ "-Wcrl,strip,-x,-S" ]
+
+          if (save_unstripped_output) {
+            outputs += [ outputs[0] + ".unstripped" ]
+            args += [ "-Wcrl,unstripped," +
+                      rebase_path(get_path_info(outputs[0], "dir"),
+                                  root_build_dir) ]
+          }
+        }
       }
     }
 
@@ -1555,41 +1384,37 @@
       product_type = "com.apple.product-type.bundle.unit-test"
       deps = [
         ":$_xctest_info_plist_bundle",
+        ":$_xctest_lipo_loadable_module_target",
       ]
       bundle_root_dir = "$root_out_dir/$_xctest_output.xctest"
 
+      _entitlements_path = _default_entitlements_path
+      if (defined(invoker.entitlements_path)) {
+        _entitlements_path = invoker.entitlements_path
+      }
+
+      code_signing_script = _code_signing_script_path
+      code_signing_sources = [
+        _entitlements_path,
+        "$target_out_dir/$_xctest_output",
+      ]
+      code_signing_outputs = [ "$bundle_root_dir/$_xctest_output" ]
+      if (ios_enable_code_signing) {
+        code_signing_outputs +=
+            [ "$bundle_root_dir/_CodeSignature/CodeResources" ]
+      }
+      if (ios_code_signing_identity != "") {
+        code_signing_outputs += [ "$bundle_root_dir/embedded.mobileprovision" ]
+      }
+      code_signing_args = [
+        "code-sign-bundle",
+        "-i=" + ios_code_signing_identity,
+        "-e=" + rebase_path(_entitlements_path, root_build_dir),
+        "-b=" + rebase_path("$target_out_dir/$_xctest_output", root_build_dir),
+        rebase_path(bundle_root_dir, root_build_dir),
+      ]
       if (!ios_enable_code_signing) {
-        deps += [ ":$_xctest_loadable_module_bundle" ]
-      } else {
-        if (_is_fat_build) {
-          deps += [ ":$_xctest_lipo_loadable_module_target" ]
-        } else {
-          deps += [ ":$_xctest_loadable_module_target" ]
-        }
-
-        _entitlements_path = "//build/config/ios/entitlements.plist"
-        if (defined(invoker.entitlements_path)) {
-          _entitlements_path = invoker.entitlements_path
-        }
-
-        code_signing_script = "//build/config/ios/codesign.py"
-        code_signing_sources = [
-          _entitlements_path,
-          "$target_out_dir/$_xctest_output",
-        ]
-        code_signing_outputs = [
-          "$bundle_root_dir/$_xctest_output",
-          "$bundle_root_dir/_CodeSignature/CodeResources",
-          "$bundle_root_dir/embedded.mobileprovision",
-        ]
-        code_signing_args = [
-          "-e=" + rebase_path(_entitlements_path, root_build_dir),
-          "code-sign-bundle",
-          "-i=" + ios_code_signing_identity,
-          "-b=" +
-              rebase_path("$target_out_dir/$_xctest_output", root_build_dir),
-          rebase_path(bundle_root_dir, root_build_dir),
-        ]
+        code_signing_args += [ "--disable-code-signature" ]
       }
     }
 
@@ -1626,7 +1451,7 @@
       "$_ios_platform_library/PrivateFrameworks/IDEBundleInjection.framework",
     ]
 
-    if (!_is_fat_build || _is_fat_build_main_target) {
+    if (!_is_secondary_build) {
       if (!defined(bundle_deps)) {
         bundle_deps = []
       }
diff --git a/build/config/mac/BUILD.gn b/build/config/mac/BUILD.gn
index 1e60f22..ec66a15 100644
--- a/build/config/mac/BUILD.gn
+++ b/build/config/mac/BUILD.gn
@@ -119,16 +119,10 @@
 # from a binary, but some targets may wish to specify a saves file to preserve
 # specific symbols.
 config("strip_all") {
-  if (is_ios && additional_toolchains != []) {
-    # For fat build, the generation of the dSYM happens after the fat binary has
-    # been created with "lipo" thus the stripping cannot happen at link time but
-    # after running "lipo" too.
-    _enable_stripping = false
-  } else {
-    _enable_stripping = enable_stripping
-  }
-
-  if (_enable_stripping) {
+  # On iOS, the final applications are assembled using lipo (to support fat
+  # builds). This configuration is thus always empty and the correct flags
+  # are passed to the linker_driver.py script directly during the lipo call.
+  if (enable_stripping && !is_ios) {
     ldflags = [ "-Wcrl,strip,-x,-S" ]
   }
 }
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py
index 618c0f57..f06fd15c 100755
--- a/build/mac/find_sdk.py
+++ b/build/mac/find_sdk.py
@@ -75,7 +75,7 @@
     print >> sys.stderr, ''
     print >> sys.stderr, '                                           ^^^^^^^'
     print >> sys.stderr, ''
-    return min_sdk_version
+    sys.exit(1)
 
   if options.print_sdk_path:
     print subprocess.check_output(
diff --git a/build/toolchain/mac/BUILD.gn b/build/toolchain/mac/BUILD.gn
index d3b0eeb..348c3b36 100644
--- a/build/toolchain/mac/BUILD.gn
+++ b/build/toolchain/mac/BUILD.gn
@@ -91,15 +91,15 @@
         "TOOL_VERSION=${tool_versions.linker_driver} " +
         rebase_path("//build/toolchain/mac/linker_driver.py", root_build_dir)
 
-    if (invoker.toolchain_os == "ios" && additional_toolchains != []) {
-      # For a fat build, the generation of dSYM needs to be performed after the
-      # generation of the fat binaries using "lipo". So disable the generation
-      # of the dSYM for intermediate architecture specific binaries.
-      _enable_dsyms = false
-      _save_unstripped_output = false
-    } else {
+    # On iOS, the final applications are assembled using lipo (to support fat
+    # builds). The correct flags are passed to the linker_driver.py script
+    # directly during the lipo call.
+    if (invoker.toolchain_os != "ios") {
       _enable_dsyms = enable_dsyms
       _save_unstripped_output = save_unstripped_output
+    } else {
+      _enable_dsyms = false
+      _save_unstripped_output = false
     }
 
     # Make these apply to all tools below.
diff --git a/cc/animation/timing_function.cc b/cc/animation/timing_function.cc
index 094f9e9..b7308bb 100644
--- a/cc/animation/timing_function.cc
+++ b/cc/animation/timing_function.cc
@@ -16,8 +16,8 @@
 
 TimingFunction::~TimingFunction() {}
 
-std::unique_ptr<TimingFunction> CubicBezierTimingFunction::CreatePreset(
-    EaseType ease_type) {
+std::unique_ptr<CubicBezierTimingFunction>
+CubicBezierTimingFunction::CreatePreset(EaseType ease_type) {
   // These numbers come from
   // http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag.
   switch (ease_type) {
@@ -74,7 +74,6 @@
   return base::WrapUnique(new CubicBezierTimingFunction(*this));
 }
 
-
 std::unique_ptr<StepsTimingFunction> StepsTimingFunction::Create(
     int steps,
     StepPosition step_position) {
@@ -82,19 +81,7 @@
 }
 
 StepsTimingFunction::StepsTimingFunction(int steps, StepPosition step_position)
-    : steps_(steps) {
-  switch (step_position) {
-    case StepPosition::START:
-      steps_start_offset_ = 1;
-      break;
-    case StepPosition::MIDDLE:
-      steps_start_offset_ = 0.5;
-      break;
-    case StepPosition::END:
-      steps_start_offset_ = 0;
-      break;
-  }
-}
+    : steps_(steps), step_position_(step_position) {}
 
 StepsTimingFunction::~StepsTimingFunction() {
 }
@@ -104,10 +91,7 @@
 }
 
 float StepsTimingFunction::GetValue(double t) const {
-  const double steps = static_cast<double>(steps_);
-  const double value = MathUtil::ClampToRange(
-      std::floor((steps * t) + steps_start_offset_) / steps, 0.0, 1.0);
-  return static_cast<float>(value);
+  return static_cast<float>(GetPreciseValue(t));
 }
 
 std::unique_ptr<TimingFunction> StepsTimingFunction::Clone() const {
@@ -123,4 +107,24 @@
   return 0.0f;
 }
 
+double StepsTimingFunction::GetPreciseValue(double t) const {
+  const double steps = static_cast<double>(steps_);
+  return MathUtil::ClampToRange(
+      std::floor((steps * t) + GetStepsStartOffset()) / steps, 0.0, 1.0);
+}
+
+float StepsTimingFunction::GetStepsStartOffset() const {
+  switch (step_position_) {
+    case StepPosition::START:
+      return 1;
+    case StepPosition::MIDDLE:
+      return 0.5;
+    case StepPosition::END:
+      return 0;
+    default:
+      NOTREACHED();
+      return 1;
+  }
+}
+
 }  // namespace cc
diff --git a/cc/animation/timing_function.h b/cc/animation/timing_function.h
index 85fe9209..bcd8304 100644
--- a/cc/animation/timing_function.h
+++ b/cc/animation/timing_function.h
@@ -31,7 +31,6 @@
  protected:
   TimingFunction();
 
- private:
   DISALLOW_ASSIGN(TimingFunction);
 };
 
@@ -39,7 +38,8 @@
  public:
   enum class EaseType { EASE, EASE_IN, EASE_OUT, EASE_IN_OUT, CUSTOM };
 
-  static std::unique_ptr<TimingFunction> CreatePreset(EaseType ease_type);
+  static std::unique_ptr<CubicBezierTimingFunction> CreatePreset(
+      EaseType ease_type);
   static std::unique_ptr<CubicBezierTimingFunction> Create(double x1,
                                                            double y1,
                                                            double x2,
@@ -54,8 +54,9 @@
   std::unique_ptr<TimingFunction> Clone() const override;
 
   EaseType ease_type() const { return ease_type_; }
+  const gfx::CubicBezier& bezier() const { return bezier_; }
 
- protected:
+ private:
   CubicBezierTimingFunction(EaseType ease_type,
                             double x1,
                             double y1,
@@ -65,7 +66,6 @@
   gfx::CubicBezier bezier_;
   EaseType ease_type_;
 
- private:
   DISALLOW_ASSIGN(CubicBezierTimingFunction);
 };
 
@@ -86,12 +86,17 @@
   void Range(float* min, float* max) const override;
   float Velocity(double time) const override;
 
- protected:
-  StepsTimingFunction(int steps, StepPosition step_position);
+  int steps() const { return steps_; }
+  StepPosition step_position() const { return step_position_; }
+  double GetPreciseValue(double t) const;
 
  private:
+  StepsTimingFunction(int steps, StepPosition step_position);
+
+  float GetStepsStartOffset() const;
+
   int steps_;
-  float steps_start_offset_;
+  StepPosition step_position_;
 
   DISALLOW_ASSIGN(StepsTimingFunction);
 };
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 5f64fc2c..8947789 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -146,8 +146,10 @@
     test_hooks_->DidFinishImplFrameOnThread(this);
   }
 
-  void BeginMainFrameAborted(CommitEarlyOutReason reason) override {
-    LayerTreeHostImpl::BeginMainFrameAborted(reason);
+  void BeginMainFrameAborted(
+      CommitEarlyOutReason reason,
+      std::vector<std::unique_ptr<SwapPromise>> swap_promises) override {
+    LayerTreeHostImpl::BeginMainFrameAborted(reason, std::move(swap_promises));
     test_hooks_->BeginMainFrameAbortedOnThread(this, reason);
   }
 
@@ -206,7 +208,10 @@
         << "Not supported for single-threaded mode.";
     block_notify_ready_to_activate_for_testing_ = block;
     if (!block && notify_ready_to_activate_was_blocked_) {
-      NotifyReadyToActivate();
+      task_runner_provider_->ImplThreadTaskRunner()->PostTask(
+          FROM_HERE,
+          base::Bind(&LayerTreeHostImplForTesting::NotifyReadyToActivate,
+                     base::Unretained(this)));
       notify_ready_to_activate_was_blocked_ = false;
     }
   }
@@ -278,9 +283,7 @@
     test_hooks_->BeginMainFrame(args);
   }
 
-  void UpdateLayerTreeHost() override {
-    test_hooks_->UpdateLayerTreeHost();
-  }
+  void UpdateLayerTreeHost() override { test_hooks_->UpdateLayerTreeHost(); }
 
   void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
                            const gfx::Vector2dF& outer_delta,
@@ -510,8 +513,7 @@
 
 void LayerTreeTest::EndTestAfterDelayMs(int delay_milliseconds) {
   main_task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::Bind(&LayerTreeTest::EndTest, main_thread_weak_ptr_),
+      FROM_HERE, base::Bind(&LayerTreeTest::EndTest, main_thread_weak_ptr_),
       base::TimeDelta::FromMilliseconds(delay_milliseconds));
 }
 
@@ -544,9 +546,8 @@
 
 void LayerTreeTest::PostSetDeferCommitsToMainThread(bool defer_commits) {
   main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LayerTreeTest::DispatchSetDeferCommits,
-                 main_thread_weak_ptr_, defer_commits));
+      FROM_HERE, base::Bind(&LayerTreeTest::DispatchSetDeferCommits,
+                            main_thread_weak_ptr_, defer_commits));
 }
 
 void LayerTreeTest::PostSetNeedsCommitToMainThread() {
@@ -557,9 +558,8 @@
 
 void LayerTreeTest::PostSetNeedsUpdateLayersToMainThread() {
   main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LayerTreeTest::DispatchSetNeedsUpdateLayers,
-                 main_thread_weak_ptr_));
+      FROM_HERE, base::Bind(&LayerTreeTest::DispatchSetNeedsUpdateLayers,
+                            main_thread_weak_ptr_));
 }
 
 void LayerTreeTest::PostSetNeedsRedrawToMainThread() {
@@ -571,31 +571,26 @@
 void LayerTreeTest::PostSetNeedsRedrawRectToMainThread(
     const gfx::Rect& damage_rect) {
   main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LayerTreeTest::DispatchSetNeedsRedrawRect,
-                 main_thread_weak_ptr_,
-                 damage_rect));
+      FROM_HERE, base::Bind(&LayerTreeTest::DispatchSetNeedsRedrawRect,
+                            main_thread_weak_ptr_, damage_rect));
 }
 
 void LayerTreeTest::PostSetVisibleToMainThread(bool visible) {
-  main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(
-          &LayerTreeTest::DispatchSetVisible, main_thread_weak_ptr_, visible));
+  main_task_runner_->PostTask(FROM_HERE,
+                              base::Bind(&LayerTreeTest::DispatchSetVisible,
+                                         main_thread_weak_ptr_, visible));
 }
 
 void LayerTreeTest::PostSetNextCommitForcesRedrawToMainThread() {
   main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LayerTreeTest::DispatchSetNextCommitForcesRedraw,
-                 main_thread_weak_ptr_));
+      FROM_HERE, base::Bind(&LayerTreeTest::DispatchSetNextCommitForcesRedraw,
+                            main_thread_weak_ptr_));
 }
 
 void LayerTreeTest::PostCompositeImmediatelyToMainThread() {
   main_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LayerTreeTest::DispatchCompositeImmediately,
-                 main_thread_weak_ptr_));
+      FROM_HERE, base::Bind(&LayerTreeTest::DispatchCompositeImmediately,
+                            main_thread_weak_ptr_));
 }
 
 void LayerTreeTest::PostNextCommitWaitsForActivationToMainThread() {
diff --git a/cc/trees/channel_main.h b/cc/trees/channel_main.h
index 1e279e9e..c5dc59f 100644
--- a/cc/trees/channel_main.h
+++ b/cc/trees/channel_main.h
@@ -51,7 +51,8 @@
   virtual void SetNeedsCommitOnImpl() = 0;
   virtual void BeginMainFrameAbortedOnImpl(
       CommitEarlyOutReason reason,
-      base::TimeTicks main_thread_start_time) = 0;
+      base::TimeTicks main_thread_start_time,
+      std::vector<std::unique_ptr<SwapPromise>> swap_promises) = 0;
   virtual void NotifyReadyToCommitOnImpl(CompletionEvent* completion,
                                          LayerTreeHost* layer_tree_host,
                                          base::TimeTicks main_thread_start_time,
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 2ec4696..315c5b8a 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -511,7 +511,7 @@
   if (sync_tree->IsActiveTree())
     sync_tree->elastic_overscroll()->PushPendingToActive();
 
-  sync_tree->PassSwapPromises(&swap_promise_list_);
+  sync_tree->PassSwapPromises(std::move(swap_promise_list_));
 
   sync_tree->set_top_controls_shrink_blink_size(
       top_controls_shrink_blink_size_);
@@ -1290,6 +1290,12 @@
   swap_promise_list_.clear();
 }
 
+std::vector<std::unique_ptr<SwapPromise>> LayerTreeHost::TakeSwapPromises() {
+  std::vector<std::unique_ptr<SwapPromise>> to_return;
+  to_return.swap(swap_promise_list_);
+  return to_return;
+}
+
 void LayerTreeHost::OnCommitForSwapPromises() {
   for (const auto& swap_promise : swap_promise_list_)
     swap_promise->OnCommit();
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 5ca13ec..54445df 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -335,8 +335,8 @@
   // Call this function when you expect there to be a swap buffer.
   // See swap_promise.h for how to use SwapPromise.
   void QueueSwapPromise(std::unique_ptr<SwapPromise> swap_promise);
-
   void BreakSwapPromises(SwapPromise::DidNotSwapReason reason);
+  std::vector<std::unique_ptr<SwapPromise>> TakeSwapPromises();
 
   size_t num_queued_swap_promises() const { return swap_promise_list_.size(); }
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 243e81da..149b7e2 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -101,8 +101,7 @@
 class ViewportAnchor {
  public:
   ViewportAnchor(LayerImpl* inner_scroll, LayerImpl* outer_scroll)
-  : inner_(inner_scroll),
-    outer_(outer_scroll) {
+      : inner_(inner_scroll), outer_(outer_scroll) {
     viewport_in_content_coordinates_ = inner_->CurrentScrollOffset();
 
     if (outer_)
@@ -262,20 +261,19 @@
 
   viewport_ = Viewport::Create(this);
 
-  TRACE_EVENT_OBJECT_CREATED_WITH_ID(
-      TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", id_);
+  TRACE_EVENT_OBJECT_CREATED_WITH_ID(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+                                     "cc::LayerTreeHostImpl", id_);
 
   top_controls_manager_ =
-      TopControlsManager::Create(this,
-                                 settings.top_controls_show_threshold,
+      TopControlsManager::Create(this, settings.top_controls_show_threshold,
                                  settings.top_controls_hide_threshold);
 }
 
 LayerTreeHostImpl::~LayerTreeHostImpl() {
   DCHECK(task_runner_provider_->IsImplThread());
   TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
-  TRACE_EVENT_OBJECT_DELETED_WITH_ID(
-      TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", id_);
+  TRACE_EVENT_OBJECT_DELETED_WITH_ID(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
+                                     "cc::LayerTreeHostImpl", id_);
 
   // It is released before shutdown.
   DCHECK(!output_surface_);
@@ -310,12 +308,21 @@
   animation_host_->SetMutatorHostClient(nullptr);
 }
 
-void LayerTreeHostImpl::BeginMainFrameAborted(CommitEarlyOutReason reason) {
+void LayerTreeHostImpl::BeginMainFrameAborted(
+    CommitEarlyOutReason reason,
+    std::vector<std::unique_ptr<SwapPromise>> swap_promises) {
   // If the begin frame data was handled, then scroll and scale set was applied
   // by the main thread, so the active tree needs to be updated as if these sent
   // values were applied and committed.
-  if (CommitEarlyOutHandledCommit(reason))
+  if (CommitEarlyOutHandledCommit(reason)) {
     active_tree_->ApplySentScrollAndScaleDeltasFromAbortedCommit();
+    if (pending_tree_) {
+      pending_tree_->AppendSwapPromises(std::move(swap_promises));
+    } else {
+      for (const auto& swap_promise : swap_promises)
+        swap_promise->DidNotSwap(SwapPromise::COMMIT_NO_UPDATE);
+    }
+  }
 }
 
 void LayerTreeHostImpl::BeginCommit() {
@@ -526,13 +533,11 @@
 
   if (anchor_point) {
     gfx::Vector2dF anchor(target_offset);
-    page_scale_animation_->ZoomWithAnchor(anchor,
-                                          page_scale,
+    page_scale_animation_->ZoomWithAnchor(anchor, page_scale,
                                           duration.InSecondsF());
   } else {
     gfx::Vector2dF scaled_target_offset = target_offset;
-    page_scale_animation_->ZoomTo(scaled_target_offset,
-                                  page_scale,
+    page_scale_animation_->ZoomTo(scaled_target_offset, page_scale,
                                   duration.InSecondsF());
   }
 
@@ -746,14 +751,9 @@
   int sorting_context_id = 0;
   SharedQuadState* shared_quad_state =
       target_render_pass->CreateAndAppendSharedQuadState();
-  shared_quad_state->SetAll(gfx::Transform(),
-                            root_target_rect.size(),
-                            root_target_rect,
-                            root_target_rect,
-                            false,
-                            opacity,
-                            SkXfermode::kSrcOver_Mode,
-                            sorting_context_id);
+  shared_quad_state->SetAll(gfx::Transform(), root_target_rect.size(),
+                            root_target_rect, root_target_rect, false, opacity,
+                            SkXfermode::kSrcOver_Mode, sorting_context_id);
 
   for (Region::Iterator fill_rects(fill_region); fill_rects.has_rect();
        fill_rects.next()) {
@@ -763,11 +763,8 @@
     // occlusion checks.
     SolidColorDrawQuad* quad =
         target_render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
-    quad->SetNew(shared_quad_state,
-                 screen_space_rect,
-                 visible_screen_space_rect,
-                 screen_background_color,
-                 false);
+    quad->SetNew(shared_quad_state, screen_space_rect,
+                 visible_screen_space_rect, screen_background_color, false);
   }
 }
 
@@ -779,8 +776,7 @@
   return it == list.end() ? nullptr : it->get();
 }
 
-DrawResult LayerTreeHostImpl::CalculateRenderPasses(
-    FrameData* frame) {
+DrawResult LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) {
   DCHECK(frame->render_passes.empty());
   DCHECK(CanDraw());
   DCHECK(!active_tree_->LayerListIsEmpty());
@@ -903,8 +899,7 @@
           it->render_surface()->GetRenderPassId();
       RenderPass* contributing_render_pass =
           FindRenderPassById(frame->render_passes, contributing_render_pass_id);
-      AppendQuadsForRenderSurfaceLayer(target_render_pass,
-                                       *it,
+      AppendQuadsForRenderSurfaceLayer(target_render_pass, *it,
                                        contributing_render_pass,
                                        &append_quads_data);
     } else if (it.represents_itself() && !it->visible_layer_rect().IsEmpty()) {
@@ -1066,9 +1061,7 @@
 }
 
 DrawResult LayerTreeHostImpl::PrepareToDraw(FrameData* frame) {
-  TRACE_EVENT1("cc",
-               "LayerTreeHostImpl::PrepareToDraw",
-               "SourceFrameNumber",
+  TRACE_EVENT1("cc", "LayerTreeHostImpl::PrepareToDraw", "SourceFrameNumber",
                active_tree_->source_frame_number());
   if (input_handler_client_)
     input_handler_client_->ReconcileElasticOverscrollAndRootScroll();
@@ -1247,9 +1240,8 @@
   }
   global_tile_state_.memory_limit_policy =
       ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy(
-          visible_ ?
-          policy.priority_cutoff_when_visible :
-          gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
+          visible_ ? policy.priority_cutoff_when_visible
+                   : gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
   global_tile_state_.num_resources_limit = policy.num_resources_limit;
 
   if (global_tile_state_.hard_memory_limit_in_bytes > 0) {
@@ -1611,8 +1603,8 @@
       !InnerViewportScrollLayer()->user_scrollable_vertical();
 
   // TODO(miletus) : Change the metadata to hold ScrollOffset.
-  metadata.root_scroll_offset = gfx::ScrollOffsetToVector2dF(
-      active_tree_->TotalScrollOffset());
+  metadata.root_scroll_offset =
+      gfx::ScrollOffsetToVector2dF(active_tree_->TotalScrollOffset());
 
   return metadata;
 }
@@ -1683,8 +1675,10 @@
   // TODO(boliu): If we did a temporary software renderer frame, propogate the
   // damage forward to the next frame.
   for (size_t i = 0; i < frame->render_surface_layer_list->size(); i++) {
-    (*frame->render_surface_layer_list)[i]->render_surface()->damage_tracker()->
-        DidDrawDamagedArea();
+    (*frame->render_surface_layer_list)[i]
+        ->render_surface()
+        ->damage_tracker()
+        ->DidDrawDamagedArea();
   }
   active_tree_->ResetAllChangeTracking();
 
@@ -1808,8 +1802,8 @@
   tree_resources_for_gpu_rasterization_dirty_ = false;
 }
 
-const RendererCapabilitiesImpl&
-LayerTreeHostImpl::GetRendererCapabilities() const {
+const RendererCapabilitiesImpl& LayerTreeHostImpl::GetRendererCapabilities()
+    const {
   CHECK(renderer_);
   return renderer_->Capabilities();
 }
@@ -1824,15 +1818,14 @@
   metadata.may_contain_video = frame.may_contain_video;
   active_tree()->FinishSwapPromises(&metadata);
   for (auto& latency : metadata.latency_info) {
-    TRACE_EVENT_WITH_FLOW1("input,benchmark",
-                           "LatencyInfo.Flow",
+    TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
                            TRACE_ID_DONT_MANGLE(latency.trace_id()),
                            TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
                            "step", "SwapBuffers");
     // Only add the latency component once for renderer swap, not the browser
     // swap.
-    if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
-                             0, nullptr)) {
+    if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0,
+                             nullptr)) {
       latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
                                0, 0);
     }
@@ -1868,8 +1861,7 @@
   if (!inner_container)
     return;
 
-  ViewportAnchor anchor(InnerViewportScrollLayer(),
-                        OuterViewportScrollLayer());
+  ViewportAnchor anchor(InnerViewportScrollLayer(), OuterViewportScrollLayer());
 
   float top_controls_layout_height =
       active_tree_->top_controls_shrink_blink_size()
@@ -1881,9 +1873,7 @@
   // Adjust the viewport layers by shrinking/expanding the container to account
   // for changes in the size (e.g. top controls) since the last resize from
   // Blink.
-  gfx::Vector2dF amount_to_expand(
-      0.f,
-      delta_from_top_controls);
+  gfx::Vector2dF amount_to_expand(0.f, delta_from_top_controls);
   inner_container->SetBoundsDelta(amount_to_expand);
 
   if (outer_container && !outer_container->BoundsForScrolling().IsEmpty()) {
@@ -2028,11 +2018,10 @@
   std::unique_ptr<PendingPageScaleAnimation> pending_page_scale_animation =
       active_tree_->TakePendingPageScaleAnimation();
   if (pending_page_scale_animation) {
-    StartPageScaleAnimation(
-        pending_page_scale_animation->target_offset,
-        pending_page_scale_animation->use_anchor,
-        pending_page_scale_animation->scale,
-        pending_page_scale_animation->duration);
+    StartPageScaleAnimation(pending_page_scale_animation->target_offset,
+                            pending_page_scale_animation->use_anchor,
+                            pending_page_scale_animation->scale,
+                            pending_page_scale_animation->duration);
   }
   // Activation can change the root scroll offset, so inform the synchronous
   // input handler.
@@ -2893,14 +2882,10 @@
   // the scroll delta in layer coordinates.
   bool start_clipped, end_clipped;
   gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta;
-  gfx::PointF local_start_point =
-      MathUtil::ProjectPoint(inverse_screen_space_transform,
-                             screen_space_point,
-                             &start_clipped);
-  gfx::PointF local_end_point =
-      MathUtil::ProjectPoint(inverse_screen_space_transform,
-                             screen_space_end_point,
-                             &end_clipped);
+  gfx::PointF local_start_point = MathUtil::ProjectPoint(
+      inverse_screen_space_transform, screen_space_point, &start_clipped);
+  gfx::PointF local_end_point = MathUtil::ProjectPoint(
+      inverse_screen_space_transform, screen_space_end_point, &end_clipped);
 
   // In general scroll point coordinates should not get clipped.
   DCHECK(!start_clipped);
@@ -2928,9 +2913,8 @@
   DCHECK(!end_clipped);
   if (end_clipped)
     return gfx::Vector2dF();
-  gfx::PointF actual_viewport_end_point =
-      gfx::ScalePoint(actual_screen_space_end_point,
-                      1.f / scale_from_viewport_to_screen_space);
+  gfx::PointF actual_viewport_end_point = gfx::ScalePoint(
+      actual_screen_space_end_point, 1.f / scale_from_viewport_to_screen_space);
   return actual_viewport_end_point - viewport_point;
 }
 
@@ -3722,8 +3706,7 @@
 
 void LayerTreeHostImpl::ClearUIResources() {
   for (UIResourceMap::const_iterator iter = ui_resource_map_.begin();
-      iter != ui_resource_map_.end();
-      ++iter) {
+       iter != ui_resource_map_.end(); ++iter) {
     evicted_ui_resources_.insert(iter->first);
     resource_provider_->DeleteResource(iter->second.resource_id);
   }
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 07162c06..7f13dce 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -236,7 +236,9 @@
     DISALLOW_COPY_AND_ASSIGN(FrameData);
   };
 
-  virtual void BeginMainFrameAborted(CommitEarlyOutReason reason);
+  virtual void BeginMainFrameAborted(
+      CommitEarlyOutReason reason,
+      std::vector<std::unique_ptr<SwapPromise>> swap_promises);
   virtual void ReadyToCommit() {}  // For tests.
   virtual void BeginCommit();
   virtual void CommitComplete();
@@ -489,18 +491,10 @@
     max_memory_needed_bytes_ = bytes;
   }
 
-  FrameRateCounter* fps_counter() {
-    return fps_counter_.get();
-  }
-  MemoryHistory* memory_history() {
-    return memory_history_.get();
-  }
-  DebugRectHistory* debug_rect_history() {
-    return debug_rect_history_.get();
-  }
-  ResourceProvider* resource_provider() {
-    return resource_provider_.get();
-  }
+  FrameRateCounter* fps_counter() { return fps_counter_.get(); }
+  MemoryHistory* memory_history() { return memory_history_.get(); }
+  DebugRectHistory* debug_rect_history() { return debug_rect_history_.get(); }
+  ResourceProvider* resource_provider() { return resource_provider_.get(); }
   TopControlsManager* top_controls_manager() {
     return top_controls_manager_.get();
   }
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 27f4ab21..b0e4cfe 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1581,8 +1581,7 @@
     }
   }
 
-  void AfterTest() override {
-  }
+  void AfterTest() override {}
 
  private:
   FakeContentLayerClient client_;
@@ -2132,8 +2131,7 @@
                            float scale,
                            float) override {
     gfx::ScrollOffset offset = scroll_layer_->scroll_offset();
-    scroll_layer_->SetScrollOffset(ScrollOffsetWithDelta(offset,
-                                                         scroll_delta));
+    scroll_layer_->SetScrollOffset(ScrollOffsetWithDelta(offset, scroll_delta));
     layer_tree_host()->SetPageScaleFactorAndLimits(scale, 0.5f, 2.f);
   }
 
@@ -2162,8 +2160,8 @@
   void DidCommitAndDrawFrame() override {
     switch (layer_tree_host()->source_frame_number()) {
       case 1:
-        layer_tree_host()->StartPageScaleAnimation(
-            gfx::Vector2d(), false, 1.25f, base::TimeDelta());
+        layer_tree_host()->StartPageScaleAnimation(gfx::Vector2d(), false,
+                                                   1.25f, base::TimeDelta());
         break;
     }
   }
@@ -2359,8 +2357,7 @@
 class LayerTreeHostTestDeferCommits : public LayerTreeHostTest {
  public:
   LayerTreeHostTestDeferCommits()
-      : num_will_begin_impl_frame_(0),
-        num_send_begin_main_frame_(0) {}
+      : num_will_begin_impl_frame_(0), num_send_begin_main_frame_(0) {}
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
@@ -2855,9 +2852,7 @@
     return std::move(output_surface);
   }
 
-  void BeginTest() override {
-    PostSetNeedsCommitToMainThread();
-  }
+  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
   void CallOnDraw() {
     if (!TestEnded()) {
@@ -3026,8 +3021,8 @@
     LayerImpl::PushPropertiesTo(layer);
     push_properties_count_++;
     // Push state to the active tree because we can only access it from there.
-    static_cast<PushPropertiesCountingLayerImpl*>(
-        layer)->push_properties_count_ = push_properties_count_;
+    static_cast<PushPropertiesCountingLayerImpl*>(layer)
+        ->push_properties_count_ = push_properties_count_;
   }
 
   std::unique_ptr<LayerImpl> CreateLayerImpl(
@@ -3042,8 +3037,7 @@
   size_t push_properties_count_;
 
   PushPropertiesCountingLayerImpl(LayerTreeImpl* tree_impl, int id)
-      : LayerImpl(tree_impl, id),
-        push_properties_count_(0) {
+      : LayerImpl(tree_impl, id), push_properties_count_(0) {
     SetBounds(gfx::Size(1, 1));
   }
 };
@@ -4061,9 +4055,7 @@
   LayerTreeHostTestTreeActivationCallback()
       : num_commits_(0), callback_count_(0) {}
 
-  void BeginTest() override {
-    PostSetNeedsCommitToMainThread();
-  }
+  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
   DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
                                    LayerTreeHostImpl::FrameData* frame_data,
@@ -4092,8 +4084,8 @@
         EndTest();
         break;
     }
-    return LayerTreeHostTest::PrepareToDrawOnThread(
-        host_impl, frame_data, draw_result);
+    return LayerTreeHostTest::PrepareToDrawOnThread(host_impl, frame_data,
+                                                    draw_result);
   }
 
   void AfterTest() override { EXPECT_EQ(3, num_commits_); }
@@ -4741,6 +4733,120 @@
 
 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestKeepSwapPromise);
 
+class LayerTreeHostTestKeepSwapPromiseMFBA : public LayerTreeHostTest {
+ public:
+  LayerTreeHostTestKeepSwapPromiseMFBA() {}
+
+  void InitializeSettings(LayerTreeSettings* settings) override {
+    settings->main_frame_before_activation_enabled = true;
+  }
+
+  void BeginTest() override {
+    layer_ = SolidColorLayer::Create();
+    layer_->SetIsDrawable(true);
+    layer_->SetBounds(gfx::Size(10, 10));
+    layer_tree_host()->SetRootLayer(layer_);
+    gfx::Size bounds(100, 100);
+    layer_tree_host()->SetViewportSize(bounds);
+    PostSetNeedsCommitToMainThread();
+  }
+
+  void BeginCommitOnThread(LayerTreeHostImpl* host_impl) override {
+    // Safe to check frame number here because main thread is blocked.
+    if (layer_tree_host()->source_frame_number() == 0) {
+      host_impl->BlockNotifyReadyToActivateForTesting(true);
+    } else {
+      NOTREACHED();
+    }
+  }
+
+  void DidCommit() override {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::Bind(&LayerTreeHostTestKeepSwapPromiseMFBA::ChangeFrame,
+                   base::Unretained(this)));
+  }
+
+  void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
+                                     CommitEarlyOutReason reason) override {
+    base::AutoLock lock(swap_promise_result_.lock);
+    EXPECT_FALSE(swap_promise_result_.did_not_swap_called);
+    EXPECT_FALSE(swap_promise_result_.did_activate_called);
+    EXPECT_FALSE(swap_promise_result_.did_swap_called);
+    host_impl->BlockNotifyReadyToActivateForTesting(false);
+  }
+
+  void ChangeFrame() {
+    switch (layer_tree_host()->source_frame_number()) {
+      case 1:
+        // Make no changes so that we abort the next commit caused by queuing
+        // the swap promise.
+        layer_tree_host()->QueueSwapPromise(
+            base::WrapUnique(new TestSwapPromise(&swap_promise_result_)));
+        layer_tree_host()->SetNeedsUpdateLayers();
+        break;
+      case 2:
+        break;
+      default:
+        NOTREACHED();
+        break;
+    }
+  }
+
+  void WillActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+    if (host_impl->pending_tree()) {
+      if (host_impl->pending_tree()->source_frame_number() == 1) {
+        base::AutoLock lock(swap_promise_result_.lock);
+        EXPECT_FALSE(swap_promise_result_.did_activate_called);
+        EXPECT_FALSE(swap_promise_result_.did_swap_called);
+        SetCallback(host_impl, true);
+      } else {
+        SetCallback(host_impl, false);
+      }
+    }
+  }
+
+  void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
+    if (host_impl->active_tree()->source_frame_number() == 1) {
+      base::AutoLock lock(swap_promise_result_.lock);
+      EXPECT_TRUE(swap_promise_result_.did_activate_called);
+      EXPECT_FALSE(swap_promise_result_.did_swap_called);
+    }
+  }
+
+  void ActivationCallback() {
+    // DidActivate needs to happen before the tree activation callback.
+    base::AutoLock lock(swap_promise_result_.lock);
+    EXPECT_TRUE(swap_promise_result_.did_activate_called);
+  }
+
+  void SetCallback(LayerTreeHostImpl* host_impl, bool enable) {
+    host_impl->SetTreeActivationCallback(
+        enable ? base::Bind(
+                     &LayerTreeHostTestKeepSwapPromiseMFBA::ActivationCallback,
+                     base::Unretained(this))
+               : base::Closure());
+  }
+
+  void DisplayDidDrawAndSwapOnThread() override {
+    num_swaps_++;
+    base::AutoLock lock(swap_promise_result_.lock);
+    EXPECT_TRUE(swap_promise_result_.did_swap_called);
+    EXPECT_FALSE(swap_promise_result_.did_not_swap_called);
+    EXPECT_TRUE(swap_promise_result_.dtor_called);
+    EndTest();
+  }
+
+  void AfterTest() override { EXPECT_EQ(1, num_swaps_); }
+
+ private:
+  int num_swaps_ = 0;
+  scoped_refptr<Layer> layer_;
+  TestSwapPromiseResult swap_promise_result_;
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestKeepSwapPromiseMFBA);
+
 class LayerTreeHostTestBreakSwapPromiseForVisibility
     : public LayerTreeHostTest {
  protected:
@@ -4756,10 +4862,9 @@
   void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
                                   const BeginFrameArgs& args) override {
     MainThreadTaskRunner()->PostTask(
-        FROM_HERE,
-        base::Bind(&LayerTreeHostTestBreakSwapPromiseForVisibility
-                       ::SetVisibleFalseAndQueueSwapPromise,
-            base::Unretained(this)));
+        FROM_HERE, base::Bind(&LayerTreeHostTestBreakSwapPromiseForVisibility::
+                                  SetVisibleFalseAndQueueSwapPromise,
+                              base::Unretained(this)));
   }
 
   void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
@@ -4786,8 +4891,7 @@
 class LayerTreeHostTestBreakSwapPromiseForContext : public LayerTreeHostTest {
  protected:
   LayerTreeHostTestBreakSwapPromiseForContext()
-      : output_surface_lost_triggered_(false) {
-  }
+      : output_surface_lost_triggered_(false) {}
 
   void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
@@ -4805,10 +4909,9 @@
     output_surface_lost_triggered_ = true;
 
     MainThreadTaskRunner()->PostTask(
-        FROM_HERE,
-        base::Bind(&LayerTreeHostTestBreakSwapPromiseForContext
-                       ::LoseOutputSurfaceAndQueueSwapPromise,
-                   base::Unretained(this)));
+        FROM_HERE, base::Bind(&LayerTreeHostTestBreakSwapPromiseForContext::
+                                  LoseOutputSurfaceAndQueueSwapPromise,
+                              base::Unretained(this)));
   }
 
   void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
@@ -4833,8 +4936,7 @@
   TestSwapPromiseResult swap_promise_result_;
 };
 
-SINGLE_AND_MULTI_THREAD_TEST_F(
-    LayerTreeHostTestBreakSwapPromiseForContext);
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestBreakSwapPromiseForContext);
 
 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
  public:
@@ -5297,9 +5399,7 @@
   LayerTreeHostTestWillBeginImplFrameHasDidFinishImplFrame()
       : will_begin_impl_frame_count_(0), did_finish_impl_frame_count_(0) {}
 
-  void BeginTest() override {
-    PostSetNeedsCommitToMainThread();
-  }
+  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
 
   void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
                                   const BeginFrameArgs& args) override {
@@ -5603,9 +5703,7 @@
     deltas_sent_to_client_ = true;
   }
 
-  void AfterTest() override {
-    EXPECT_TRUE(deltas_sent_to_client_);
-  }
+  void AfterTest() override { EXPECT_TRUE(deltas_sent_to_client_); }
 
   ScrollAndScaleSet info_;
   bool deltas_sent_to_client_;
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index ff5da70..975e82e 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <algorithm>
+#include <iterator>
 #include <limits>
 #include <set>
 
@@ -424,7 +425,7 @@
     next_activation_forces_redraw_ = false;
   }
 
-  target_tree->PassSwapPromises(&swap_promise_list_);
+  target_tree->PassSwapPromises(std::move(swap_promise_list_));
 
   target_tree->set_top_controls_shrink_blink_size(
       top_controls_shrink_blink_size_);
@@ -1483,11 +1484,18 @@
 }
 
 void LayerTreeImpl::PassSwapPromises(
-    std::vector<std::unique_ptr<SwapPromise>>* new_swap_promise) {
+    std::vector<std::unique_ptr<SwapPromise>> new_swap_promises) {
   for (const auto& swap_promise : swap_promise_list_)
     swap_promise->DidNotSwap(SwapPromise::SWAP_FAILS);
   swap_promise_list_.clear();
-  swap_promise_list_.swap(*new_swap_promise);
+  swap_promise_list_.swap(new_swap_promises);
+}
+
+void LayerTreeImpl::AppendSwapPromises(
+    std::vector<std::unique_ptr<SwapPromise>> new_swap_promises) {
+  std::move(new_swap_promises.begin(), new_swap_promises.end(),
+            std::back_inserter(swap_promise_list_));
+  new_swap_promises.clear();
 }
 
 void LayerTreeImpl::FinishSwapPromises(CompositorFrameMetadata* metadata) {
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 3d032fc..0f629ba9 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -358,9 +358,12 @@
   // on the active tree if a new tree is activated.
   void QueuePinnedSwapPromise(std::unique_ptr<SwapPromise> swap_promise);
 
-  // Take the |new_swap_promise| and append it to |swap_promise_list_|.
+  // Takes ownership of |new_swap_promises|. Existing swap promises in
+  // |swap_promise_list_| are cancelled (SWAP_FAILS).
   void PassSwapPromises(
-      std::vector<std::unique_ptr<SwapPromise>>* new_swap_promise);
+      std::vector<std::unique_ptr<SwapPromise>> new_swap_promises);
+  void AppendSwapPromises(
+      std::vector<std::unique_ptr<SwapPromise>> new_swap_promises);
   void FinishSwapPromises(CompositorFrameMetadata* metadata);
   void BreakSwapPromises(SwapPromise::DidNotSwapReason reason);
 
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index 8e651144..4852da2a 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -188,7 +188,8 @@
 
 void ProxyImpl::BeginMainFrameAbortedOnImpl(
     CommitEarlyOutReason reason,
-    base::TimeTicks main_thread_start_time) {
+    base::TimeTicks main_thread_start_time,
+    std::vector<std::unique_ptr<SwapPromise>> swap_promises) {
   TRACE_EVENT1("cc", "ProxyImpl::BeginMainFrameAbortedOnImplThread", "reason",
                CommitEarlyOutReasonToString(reason));
   DCHECK(IsImplThread());
@@ -197,7 +198,8 @@
   if (CommitEarlyOutHandledCommit(reason)) {
     SetInputThrottledUntilCommitOnImpl(false);
   }
-  layer_tree_host_impl_->BeginMainFrameAborted(reason);
+  layer_tree_host_impl_->BeginMainFrameAborted(reason,
+                                               std::move(swap_promises));
   scheduler_->NotifyBeginMainFrameStarted(main_thread_start_time);
   scheduler_->BeginMainFrameAborted(reason);
 }
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index a58a190..507ae33 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -40,8 +40,10 @@
   void SetDeferCommitsOnImpl(bool defer_commits) const;
   void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect);
   void SetNeedsCommitOnImpl();
-  void BeginMainFrameAbortedOnImpl(CommitEarlyOutReason reason,
-                                   base::TimeTicks main_thread_start_time);
+  void BeginMainFrameAbortedOnImpl(
+      CommitEarlyOutReason reason,
+      base::TimeTicks main_thread_start_time,
+      std::vector<std::unique_ptr<SwapPromise>> swap_promises);
   void FinishAllRenderingOnImpl(CompletionEvent* completion);
   void SetVisibleOnImpl(bool visible);
   void ReleaseOutputSurfaceOnImpl(CompletionEvent* completion);
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 6e1de7f..2b78994 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -145,9 +145,10 @@
   if (defer_commits_) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
                          TRACE_EVENT_SCOPE_THREAD);
+    std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
     channel_main_->BeginMainFrameAbortedOnImpl(
         CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT,
-        begin_main_frame_start_time);
+        begin_main_frame_start_time, std::move(empty_swap_promises));
     return;
   }
 
@@ -161,17 +162,20 @@
 
   if (!layer_tree_host_->visible()) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
+    std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
     channel_main_->BeginMainFrameAbortedOnImpl(
-        CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time);
+        CommitEarlyOutReason::ABORTED_NOT_VISIBLE, begin_main_frame_start_time,
+        std::move(empty_swap_promises));
     return;
   }
 
   if (layer_tree_host_->output_surface_lost()) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_OutputSurfaceLost",
                          TRACE_EVENT_SCOPE_THREAD);
+    std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
     channel_main_->BeginMainFrameAbortedOnImpl(
         CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST,
-        begin_main_frame_start_time);
+        begin_main_frame_start_time, std::move(empty_swap_promises));
     return;
   }
 
@@ -215,7 +219,8 @@
   if (!updated && can_cancel_this_commit) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
     channel_main_->BeginMainFrameAbortedOnImpl(
-        CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time);
+        CommitEarlyOutReason::FINISHED_NO_UPDATES, begin_main_frame_start_time,
+        layer_tree_host_->TakeSwapPromises());
 
     // Although the commit is internally aborted, this is because it has been
     // detected to be a no-op.  From the perspective of an embedder, this commit
@@ -223,7 +228,6 @@
     current_pipeline_stage_ = NO_PIPELINE_STAGE;
     layer_tree_host_->CommitComplete();
     layer_tree_host_->DidBeginMainFrame();
-    layer_tree_host_->BreakSwapPromises(SwapPromise::COMMIT_NO_UPDATE);
     return;
   }
 
diff --git a/cc/trees/remote_channel_impl.cc b/cc/trees/remote_channel_impl.cc
index 2e8d745..0ffaecf 100644
--- a/cc/trees/remote_channel_impl.cc
+++ b/cc/trees/remote_channel_impl.cc
@@ -130,12 +130,14 @@
           proto.begin_main_frame_aborted_message();
       CommitEarlyOutReason reason = CommitEarlyOutReasonFromProtobuf(
           begin_main_frame_aborted_message.reason());
+      std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
       VLOG(1) << "Received BeginMainFrameAborted from the engine with reason: "
               << CommitEarlyOutReasonToString(reason);
       ImplThreadTaskRunner()->PostTask(
           FROM_HERE,
           base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl,
-                     proxy_impl_weak_ptr_, reason, main_thread_start_time));
+                     proxy_impl_weak_ptr_, reason, main_thread_start_time,
+                     base::Passed(&empty_swap_promises)));
     } break;
     case proto::CompositorMessageToImpl::SET_NEEDS_REDRAW: {
       VLOG(1) << "Received redraw request from the engine.";
diff --git a/cc/trees/remote_channel_main.cc b/cc/trees/remote_channel_main.cc
index 540acf6..b9db7fa 100644
--- a/cc/trees/remote_channel_main.cc
+++ b/cc/trees/remote_channel_main.cc
@@ -155,7 +155,8 @@
 
 void RemoteChannelMain::BeginMainFrameAbortedOnImpl(
     CommitEarlyOutReason reason,
-    base::TimeTicks main_thread_start_time) {
+    base::TimeTicks main_thread_start_time,
+    std::vector<std::unique_ptr<SwapPromise>> swap_promises) {
   TRACE_EVENT1("cc.remote", "RemoteChannelMain::BeginMainFrameAbortedOnImpl",
                "reason", CommitEarlyOutReasonToString(reason));
   proto::CompositorMessage proto;
@@ -170,6 +171,12 @@
   VLOG(1) << "Sending BeginMainFrameAborted message to client with reason: "
           << CommitEarlyOutReasonToString(reason);
   SendMessageProto(proto);
+
+  // Notify swap promises that commit had no updates. In the local compositor
+  // case this goes to the impl thread to be queued up in case we have an
+  // activation pending but that never happens for remote compositor.
+  for (const auto& swap_promise : swap_promises)
+    swap_promise->DidNotSwap(SwapPromise::COMMIT_NO_UPDATE);
 }
 
 void RemoteChannelMain::NotifyReadyToCommitOnImpl(
diff --git a/cc/trees/remote_channel_main.h b/cc/trees/remote_channel_main.h
index e162d32..50845de0 100644
--- a/cc/trees/remote_channel_main.h
+++ b/cc/trees/remote_channel_main.h
@@ -49,7 +49,8 @@
   void SetNeedsCommitOnImpl() override;
   void BeginMainFrameAbortedOnImpl(
       CommitEarlyOutReason reason,
-      base::TimeTicks main_thread_start_time) override;
+      base::TimeTicks main_thread_start_time,
+      std::vector<std::unique_ptr<SwapPromise>> swap_promises) override;
   void NotifyReadyToCommitOnImpl(CompletionEvent* completion,
                                  LayerTreeHost* layer_tree_host,
                                  base::TimeTicks main_thread_start_time,
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 5b0fb57..b0c1abb 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -378,8 +378,8 @@
 }
 
 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
-  TRACE_EVENT1(
-      "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
+  TRACE_EVENT1("cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw",
+               can_draw);
   DCHECK(task_runner_provider_->IsImplThread());
   if (scheduler_on_impl_thread_)
     scheduler_on_impl_thread_->SetCanDraw(can_draw);
@@ -448,7 +448,9 @@
   layer_tree_host_->SetAnimationEvents(std::move(events));
 }
 
-bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
+bool SingleThreadProxy::IsInsideDraw() {
+  return inside_draw_;
+}
 
 void SingleThreadProxy::DidActivateSyncTree() {
   // Synchronously call to CommitComplete. Resetting
@@ -594,8 +596,7 @@
 
 bool SingleThreadProxy::ShouldComposite() const {
   DCHECK(task_runner_provider_->IsImplThread());
-  return layer_tree_host_impl_->visible() &&
-         layer_tree_host_impl_->CanDraw();
+  return layer_tree_host_impl_->visible() && layer_tree_host_impl_->CanDraw();
 }
 
 void SingleThreadProxy::ScheduleRequestNewOutputSurface() {
@@ -735,6 +736,7 @@
 void SingleThreadProxy::ScheduledActionSendBeginMainFrame(
     const BeginFrameArgs& begin_frame_args) {
   TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
+#if DCHECK_IS_ON()
   // Although this proxy is single-threaded, it's problematic to synchronously
   // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame.  This
   // could cause a commit to occur in between a series of SetNeedsCommit calls
@@ -742,7 +744,6 @@
   // fall on the next.  Doing it asynchronously instead matches the semantics of
   // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
   // synchronous commit.
-#if DCHECK_IS_ON()
   DCHECK(inside_impl_frame_)
       << "BeginMainFrame should only be sent inside a BeginImplFrame";
 #endif
@@ -785,8 +786,8 @@
   }
 
   if (layer_tree_host_->output_surface_lost()) {
-    TRACE_EVENT_INSTANT0(
-        "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
+    TRACE_EVENT_INSTANT0("cc", "EarlyOut_OutputSurfaceLost",
+                         TRACE_EVENT_SCOPE_THREAD);
     BeginMainFrameAbortedOnImplThread(
         CommitEarlyOutReason::ABORTED_OUTPUT_SURFACE_LOST);
     return;
@@ -825,7 +826,9 @@
   DCHECK(scheduler_on_impl_thread_->CommitPending());
   DCHECK(!layer_tree_host_impl_->pending_tree());
 
-  layer_tree_host_impl_->BeginMainFrameAborted(reason);
+  std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
+  layer_tree_host_impl_->BeginMainFrameAborted(reason,
+                                               std::move(empty_swap_promises));
   scheduler_on_impl_thread_->BeginMainFrameAborted(reason);
 }
 
diff --git a/cc/trees/threaded_channel.cc b/cc/trees/threaded_channel.cc
index ab0fa28..67902ae 100644
--- a/cc/trees/threaded_channel.cc
+++ b/cc/trees/threaded_channel.cc
@@ -5,6 +5,7 @@
 #include "cc/trees/threaded_channel.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
@@ -26,8 +27,7 @@
     : task_runner_provider_(task_runner_provider),
       main_thread_only_vars_unsafe_(proxy_main),
       compositor_thread_vars_unsafe_(
-          main()
-              .proxy_main_weak_factory.GetWeakPtr()) {
+          main().proxy_main_weak_factory.GetWeakPtr()) {
   DCHECK(IsMainThread());
 }
 
@@ -93,12 +93,13 @@
 
 void ThreadedChannel::BeginMainFrameAbortedOnImpl(
     CommitEarlyOutReason reason,
-    base::TimeTicks main_thread_start_time) {
+    base::TimeTicks main_thread_start_time,
+    std::vector<std::unique_ptr<SwapPromise>> swap_promises) {
   DCHECK(IsMainThread());
   ImplThreadTaskRunner()->PostTask(
       FROM_HERE,
       base::Bind(&ProxyImpl::BeginMainFrameAbortedOnImpl, proxy_impl_weak_ptr_,
-                 reason, main_thread_start_time));
+                 reason, main_thread_start_time, base::Passed(&swap_promises)));
 }
 
 void ThreadedChannel::SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) {
diff --git a/cc/trees/threaded_channel.h b/cc/trees/threaded_channel.h
index 1ae1ef1d..2333e33 100644
--- a/cc/trees/threaded_channel.h
+++ b/cc/trees/threaded_channel.h
@@ -96,7 +96,8 @@
   void SetNeedsCommitOnImpl() override;
   void BeginMainFrameAbortedOnImpl(
       CommitEarlyOutReason reason,
-      base::TimeTicks main_thread_start_time) override;
+      base::TimeTicks main_thread_start_time,
+      std::vector<std::unique_ptr<SwapPromise>> swap_promises) override;
   void SetNeedsRedrawOnImpl(const gfx::Rect& damage_rect) override;
   void SetVisibleOnImpl(bool visible) override;
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 3d45c4ef..9980cb68 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=54
 MINOR=0
-BUILD=2824
+BUILD=2825
 PATCH=0
diff --git a/chrome/android/java/res/drawable-hdpi/bookmark_back_normal.png b/chrome/android/java/res/drawable-hdpi/back_normal.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/bookmark_back_normal.png
rename to chrome/android/java/res/drawable-hdpi/back_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/bookmark_delete_white.png b/chrome/android/java/res/drawable-hdpi/bookmark_delete_white.png
deleted file mode 100644
index f7cfa84..0000000
--- a/chrome/android/java/res/drawable-hdpi/bookmark_delete_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/bookmark_cancel_active.png b/chrome/android/java/res/drawable-hdpi/btn_close_white.png
similarity index 100%
rename from chrome/android/java/res/drawable-hdpi/bookmark_cancel_active.png
rename to chrome/android/java/res/drawable-hdpi/btn_close_white.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/ic_share_white_24dp.png b/chrome/android/java/res/drawable-hdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000..7ec2855
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_share_white_24dp.png b/chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_share_white_24dp.png
new file mode 100644
index 0000000..50bf8d3
--- /dev/null
+++ b/chrome/android/java/res/drawable-ldrtl-hdpi-v17/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_share_white_24dp.png b/chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_share_white_24dp.png
new file mode 100644
index 0000000..b34c663
--- /dev/null
+++ b/chrome/android/java/res/drawable-ldrtl-mdpi-v17/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_share_white_24dp.png b/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_share_white_24dp.png
new file mode 100644
index 0000000..a97dec2
--- /dev/null
+++ b/chrome/android/java/res/drawable-ldrtl-xhdpi-v17/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_share_white_24dp.png b/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_share_white_24dp.png
new file mode 100644
index 0000000..6dfd3ba7
--- /dev/null
+++ b/chrome/android/java/res/drawable-ldrtl-xxhdpi-v17/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_share_white_24dp.png b/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_share_white_24dp.png
new file mode 100644
index 0000000..5ea7a0d
--- /dev/null
+++ b/chrome/android/java/res/drawable-ldrtl-xxxhdpi-v17/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bookmark_back_normal.png b/chrome/android/java/res/drawable-mdpi/back_normal.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/bookmark_back_normal.png
rename to chrome/android/java/res/drawable-mdpi/back_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bookmark_delete_white.png b/chrome/android/java/res/drawable-mdpi/bookmark_delete_white.png
deleted file mode 100644
index 06dc931..0000000
--- a/chrome/android/java/res/drawable-mdpi/bookmark_delete_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/bookmark_cancel_active.png b/chrome/android/java/res/drawable-mdpi/btn_close_white.png
similarity index 100%
rename from chrome/android/java/res/drawable-mdpi/bookmark_cancel_active.png
rename to chrome/android/java/res/drawable-mdpi/btn_close_white.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/ic_share_white_24dp.png b/chrome/android/java/res/drawable-mdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000..b8b8065
--- /dev/null
+++ b/chrome/android/java/res/drawable-mdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bookmark_back_normal.png b/chrome/android/java/res/drawable-xhdpi/back_normal.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/bookmark_back_normal.png
rename to chrome/android/java/res/drawable-xhdpi/back_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bookmark_delete_white.png b/chrome/android/java/res/drawable-xhdpi/bookmark_delete_white.png
deleted file mode 100644
index b6c902cb..0000000
--- a/chrome/android/java/res/drawable-xhdpi/bookmark_delete_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/bookmark_cancel_active.png b/chrome/android/java/res/drawable-xhdpi/btn_close_white.png
similarity index 100%
rename from chrome/android/java/res/drawable-xhdpi/bookmark_cancel_active.png
rename to chrome/android/java/res/drawable-xhdpi/btn_close_white.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/ic_share_white_24dp.png b/chrome/android/java/res/drawable-xhdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000..d195507
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bookmark_back_normal.png b/chrome/android/java/res/drawable-xxhdpi/back_normal.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/bookmark_back_normal.png
rename to chrome/android/java/res/drawable-xxhdpi/back_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bookmark_delete_white.png b/chrome/android/java/res/drawable-xxhdpi/bookmark_delete_white.png
deleted file mode 100644
index f966b74..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/bookmark_delete_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/bookmark_cancel_active.png b/chrome/android/java/res/drawable-xxhdpi/btn_close_white.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxhdpi/bookmark_cancel_active.png
rename to chrome/android/java/res/drawable-xxhdpi/btn_close_white.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/ic_share_white_24dp.png b/chrome/android/java/res/drawable-xxhdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000..5aee46d0
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxhdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bookmark_back_normal.png b/chrome/android/java/res/drawable-xxxhdpi/back_normal.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/bookmark_back_normal.png
rename to chrome/android/java/res/drawable-xxxhdpi/back_normal.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bookmark_delete_white.png b/chrome/android/java/res/drawable-xxxhdpi/bookmark_delete_white.png
deleted file mode 100644
index f324c3d4..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/bookmark_delete_white.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/bookmark_cancel_active.png b/chrome/android/java/res/drawable-xxxhdpi/btn_close_white.png
similarity index 100%
rename from chrome/android/java/res/drawable-xxxhdpi/bookmark_cancel_active.png
rename to chrome/android/java/res/drawable-xxxhdpi/btn_close_white.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/ic_share_white_24dp.png b/chrome/android/java/res/drawable-xxxhdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000..6742e90
--- /dev/null
+++ b/chrome/android/java/res/drawable-xxxhdpi/ic_share_white_24dp.png
Binary files differ
diff --git a/chrome/android/java/res/drawable/bookmark_item_highlight.xml b/chrome/android/java/res/drawable/selectable_item_highlight.xml
similarity index 66%
rename from chrome/android/java/res/drawable/bookmark_item_highlight.xml
rename to chrome/android/java/res/drawable/selectable_item_highlight.xml
index ba9f547..0ba396f 100644
--- a/chrome/android/java/res/drawable/bookmark_item_highlight.xml
+++ b/chrome/android/java/res/drawable/selectable_item_highlight.xml
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2015 The Chromium Authors. All rights reserved.
+<!-- 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. -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_checked="true"
-        android:drawable="@color/bookmark_list_item_highlight_color" />
+        android:drawable="@color/selectable_list_item_highlight_color" />
 </selector>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/bookmark_main_content.xml b/chrome/android/java/res/layout/bookmark_main_content.xml
index 1bac801..5cbaa5b2 100644
--- a/chrome/android/java/res/layout/bookmark_main_content.xml
+++ b/chrome/android/java/res/layout/bookmark_main_content.xml
@@ -49,30 +49,8 @@
         android:layout_alignParentTop="true"
         android:background="@color/appbar_background" >
 
-        <org.chromium.chrome.browser.widget.NumberRollView
-            android:id="@+id/selection_mode_number"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:visibility="gone" >
+        <include layout="@layout/number_roll_view" />
 
-            <TextView
-                android:id="@+id/up"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:singleLine="true"
-                android:textColor="@android:color/white"
-                android:textSize="20sp" />
-
-            <TextView
-                android:id="@+id/down"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_vertical"
-                android:singleLine="true"
-                android:textColor="@android:color/white"
-                android:textSize="20sp" />
-        </org.chromium.chrome.browser.widget.NumberRollView>
     </org.chromium.chrome.browser.bookmarks.BookmarkActionBar>
 
     <org.chromium.chrome.browser.widget.FadingShadowView
diff --git a/chrome/android/java/res/layout/bookmark_row_content.xml b/chrome/android/java/res/layout/bookmark_row_content.xml
index 8f195f5..f176914 100644
--- a/chrome/android/java/res/layout/bookmark_row_content.xml
+++ b/chrome/android/java/res/layout/bookmark_row_content.xml
@@ -47,9 +47,4 @@
             chrome:tint="@color/dark_mode_tint" />
     </LinearLayout>
 
-    <org.chromium.chrome.browser.bookmarks.BookmarkItemHighlightView
-        android:id="@+id/highlight"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
 </merge>
diff --git a/chrome/android/java/res/layout/download_item_view.xml b/chrome/android/java/res/layout/download_item_view.xml
index d4edf86a..088dbe0 100644
--- a/chrome/android/java/res/layout/download_item_view.xml
+++ b/chrome/android/java/res/layout/download_item_view.xml
@@ -4,61 +4,67 @@
      found in the LICENSE file. -->
 
 <!-- Represents a single item in the DownloadHistoryAdapterView. --> 
-<RelativeLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginEnd="16dp"
-        android:layout_marginTop="16dp"
-        android:layout_marginBottom="16dp" >
+<view class="org.chromium.chrome.browser.download.ui.DownloadItemView"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content" >
 
-    <ImageView
-            android:id="@+id/icon_view"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
-            android:layout_alignParentStart="true"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentBottom="true"
+    <RelativeLayout
+            android:id="@+id/content"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
             android:layout_marginEnd="16dp"
-            android:contentDescription="@null"
-            android:scaleType="centerInside"
-            android:background="@color/light_active_color" />
-    
-    <TextView
-            android:id="@+id/filename_view"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentEnd="true"
-            android:layout_toEndOf="@+id/icon_view"
-            android:singleLine="true"
-            android:textColor="@color/default_text_color"
-            android:textSize="16sp" />
-    
-    <TextView
-            android:id="@+id/hostname_view"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true"
-            android:layout_toEndOf="@+id/icon_view"
-            android:layout_toStartOf="@+id/filesize_view"
-            android:layout_below="@+id/filename_view"
-            android:layout_marginEnd="16dp"
-            android:layout_marginTop="0dp"
-            android:textAlignment="viewStart"
-            android:ellipsize="start"
-            android:singleLine="true" />
+            android:paddingTop="16dp"
+            android:paddingBottom="16dp" >
 
-    <TextView
-            android:id="@+id/filesize_view"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true"
-            android:layout_alignParentEnd="true"
-            android:layout_below="@+id/filename_view"
-            android:layout_marginTop="0dp"
-            android:textAlignment="viewEnd"
-            android:singleLine="true" />
+        <ImageView
+                android:id="@+id/icon_view"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
+                android:layout_alignParentStart="true"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentBottom="true"
+                android:layout_marginEnd="16dp"
+                android:contentDescription="@null"
+                android:scaleType="centerInside"
+                android:background="@color/light_active_color" />
 
-</RelativeLayout>
\ No newline at end of file
+        <TextView
+                android:id="@+id/filename_view"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentEnd="true"
+                android:layout_toEndOf="@+id/icon_view"
+                android:singleLine="true"
+                android:textColor="@color/default_text_color"
+                android:textSize="16sp" />
+
+        <TextView
+                android:id="@+id/hostname_view"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_alignParentBottom="true"
+                android:layout_toEndOf="@+id/icon_view"
+                android:layout_toStartOf="@+id/filesize_view"
+                android:layout_below="@+id/filename_view"
+                android:layout_marginEnd="16dp"
+                android:layout_marginTop="0dp"
+                android:textAlignment="viewStart"
+                android:ellipsize="start"
+                android:singleLine="true" />
+
+        <TextView
+                android:id="@+id/filesize_view"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentBottom="true"
+                android:layout_alignParentEnd="true"
+                android:layout_below="@+id/filename_view"
+                android:layout_marginTop="0dp"
+                android:textAlignment="viewEnd"
+                android:singleLine="true" />
+    </RelativeLayout>
+
+ </view>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/download_main.xml b/chrome/android/java/res/layout/download_main.xml
index 1320ddb..d6f8607 100644
--- a/chrome/android/java/res/layout/download_main.xml
+++ b/chrome/android/java/res/layout/download_main.xml
@@ -15,12 +15,16 @@
         android:layout_height="match_parent"
         android:background="#ffffff"
         android:orientation="vertical" >
-        
+
         <org.chromium.chrome.browser.download.ui.DownloadManagerToolbar
             android:id="@id/action_bar"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
-            android:background="@color/appbar_background" />
+            android:background="@color/appbar_background" >
+
+            <include layout="@layout/number_roll_view" />
+
+        </org.chromium.chrome.browser.download.ui.DownloadManagerToolbar>
 
         <org.chromium.chrome.browser.widget.FadingShadowView
             android:id="@+id/shadow"
diff --git a/chrome/android/java/res/layout/number_roll_view.xml b/chrome/android/java/res/layout/number_roll_view.xml
new file mode 100644
index 0000000..91069d5
--- /dev/null
+++ b/chrome/android/java/res/layout/number_roll_view.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<org.chromium.chrome.browser.widget.NumberRollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/selection_mode_number"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:visibility="gone" >
+
+    <TextView
+        android:id="@+id/up"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:singleLine="true"
+        android:textColor="@android:color/white"
+        android:textSize="20sp" />
+
+    <TextView
+        android:id="@+id/down"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:singleLine="true"
+        android:textColor="@android:color/white"
+        android:textSize="20sp" />
+</org.chromium.chrome.browser.widget.NumberRollView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/selectable_item_highlight_view.xml b/chrome/android/java/res/layout/selectable_item_highlight_view.xml
new file mode 100644
index 0000000..242c2a3
--- /dev/null
+++ b/chrome/android/java/res/layout/selectable_item_highlight_view.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<org.chromium.chrome.browser.widget.selection.SelectableItemHighlightView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/highlight"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/chrome/android/java/res/menu/bookmark_action_bar_menu.xml b/chrome/android/java/res/menu/bookmark_action_bar_menu.xml
index 9a85d9e..ac3db18 100644
--- a/chrome/android/java/res/menu/bookmark_action_bar_menu.xml
+++ b/chrome/android/java/res/menu/bookmark_action_bar_menu.xml
@@ -40,7 +40,7 @@
             chrome:showAsAction="ifRoom"/>
         <item
             android:id="@+id/selection_mode_delete_menu_id"
-            android:icon="@drawable/bookmark_delete_white"
+            android:icon="@drawable/ic_delete_white_24dp"
             android:title="@null"
             chrome:showAsAction="ifRoom"/>
         <item
diff --git a/chrome/android/java/res/menu/download_manager_menu.xml b/chrome/android/java/res/menu/download_manager_menu.xml
index bc927a5..b2cd777 100644
--- a/chrome/android/java/res/menu/download_manager_menu.xml
+++ b/chrome/android/java/res/menu/download_manager_menu.xml
@@ -6,10 +6,25 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:chrome="http://schemas.android.com/apk/res-auto" >
 
-    <item
-        android:id="@+id/close_menu_id"
-        android:icon="@drawable/btn_close"
-        android:title="@string/close"
-        chrome:showAsAction="ifRoom"/>
-
+    <group android:id="@+id/normal_menu_group" >
+        <item
+            android:id="@+id/close_menu_id"
+            android:icon="@drawable/btn_close"
+            android:title="@string/close"
+            chrome:showAsAction="ifRoom" />
+     </group>
+     <group
+        android:id="@+id/selection_mode_menu_group"
+        android:visible="false" >
+        <item
+            android:id="@+id/selection_mode_share_menu_id"
+            android:icon="@drawable/ic_share_white_24dp"
+            android:title="@string/remove"
+            chrome:showAsAction="ifRoom" />
+        <item
+            android:id="@+id/selection_mode_delete_menu_id"
+            android:icon="@drawable/ic_delete_white_24dp"
+            android:title="@string/share"
+            chrome:showAsAction="ifRoom" />
+     </group>
 </menu>
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml
index f3f3fbd7..2759cc8 100644
--- a/chrome/android/java/res/values/colors.xml
+++ b/chrome/android/java/res/values/colors.xml
@@ -165,7 +165,6 @@
     <color name="bookmark_detail_text">#212121</color>
     <color name="bookmark_detail_section">#7C7B79</color>
     <color name="bookmark_drawer_selected_background_color">#F0F0F0</color>
-    <color name="bookmark_list_item_highlight_color">#804281f4</color>
 
     <!-- Favicon colors -->
     <color name="default_favicon_background_color">#ff787878</color>
@@ -193,4 +192,7 @@
     <color name="payments_section_chevron">#b2b2b2</color>
     <color name="payments_section_separator">#e0e0e0</color>
 
+    <!-- Other colors -->
+    <color name="selectable_list_item_highlight_color">#804281f4</color>
+
 </resources>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
index 4603c88..a18d91b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
@@ -4,26 +4,21 @@
 
 package org.chromium.chrome.browser.bookmarks;
 
-import android.app.Activity;
 import android.content.Context;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.widget.Toolbar;
 import android.support.v7.widget.Toolbar.OnMenuItemClickListener;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.MenuItem;
-import android.view.View;
 import android.view.View.OnClickListener;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
-import org.chromium.chrome.browser.widget.NumberRollView;
-import org.chromium.chrome.browser.widget.TintedDrawable;
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
+import org.chromium.chrome.browser.widget.selection.SelectionToolbar;
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.bookmarks.BookmarkType;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -34,23 +29,15 @@
  * Main action bar of bookmark UI. It is responsible for displaying title and buttons
  * associated with the current context.
  */
-public class BookmarkActionBar extends Toolbar implements BookmarkUIObserver,
+public class BookmarkActionBar extends SelectionToolbar<BookmarkId> implements BookmarkUIObserver,
         OnMenuItemClickListener, OnClickListener {
-    private static final int NAVIGATION_BUTTON_NONE = 0;
-    private static final int NAVIGATION_BUTTON_MENU = 1;
-    private static final int NAVIGATION_BUTTON_BACK = 2;
-    private static final int NAVIGATION_BUTTON_SELECTION_BACK = 3;
-
-    private int mNavigationButton;
     private BookmarkItem mCurrentFolder;
     private BookmarkDelegate mDelegate;
-    private ActionBarDrawerToggle mActionBarDrawerToggle;
-    private boolean mIsSelectionEnabled;
 
     private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObserver() {
         @Override
         public void bookmarkModelChanged() {
-            onSelectionStateChange(mDelegate.getSelectedBookmarks());
+            onSelectionStateChange(mDelegate.getSelectionDelegate().getSelectedItems());
         }
     };
 
@@ -69,26 +56,13 @@
     }
 
     @Override
-    public void onClick(View view) {
-        switch (mNavigationButton) {
-            case NAVIGATION_BUTTON_NONE:
-                break;
-            case NAVIGATION_BUTTON_MENU:
-                // ActionBarDrawerToggle handles this.
-                break;
-            case NAVIGATION_BUTTON_BACK:
-                mDelegate.openFolder(mCurrentFolder.getParentId());
-                break;
-            case NAVIGATION_BUTTON_SELECTION_BACK:
-                mDelegate.clearSelection();
-                break;
-            default:
-                assert false : "Incorrect navigation button state";
-        }
+    protected void onNavigationBack() {
+        mDelegate.openFolder(mCurrentFolder.getParentId());
     }
 
     @Override
     public boolean onMenuItemClick(MenuItem menuItem) {
+        SelectionDelegate<BookmarkId> selectionDelegate = mDelegate.getSelectionDelegate();
         if (menuItem.getItemId() == R.id.edit_menu_id) {
             BookmarkAddEditFolderActivity.startEditFolderActivity(getContext(),
                     mCurrentFolder.getId());
@@ -100,7 +74,7 @@
             mDelegate.openSearchUI();
             return true;
         } else if (menuItem.getItemId() == R.id.selection_mode_edit_menu_id) {
-            List<BookmarkId> list = mDelegate.getSelectedBookmarks();
+            List<BookmarkId> list = selectionDelegate.getSelectedItems();
             assert list.size() == 1;
             BookmarkItem item = mDelegate.getModel().getBookmarkById(list.get(0));
             if (item.isFolder()) {
@@ -110,7 +84,7 @@
             }
             return true;
         } else if (menuItem.getItemId() == R.id.selection_mode_move_menu_id) {
-            List<BookmarkId> list = mDelegate.getSelectedBookmarks();
+            List<BookmarkId> list = selectionDelegate.getSelectedItems();
             if (list.size() >= 1) {
                 BookmarkFolderSelectActivity.startFolderSelectActivity(getContext(),
                         list.toArray(new BookmarkId[list.size()]));
@@ -118,17 +92,17 @@
             return true;
         } else if (menuItem.getItemId() == R.id.selection_mode_delete_menu_id) {
             mDelegate.getModel().deleteBookmarks(
-                    mDelegate.getSelectedBookmarks().toArray(new BookmarkId[0]));
+                    selectionDelegate.getSelectedItems().toArray(new BookmarkId[0]));
             return true;
         } else if (menuItem.getItemId() == R.id.selection_open_in_new_tab_id) {
-            openBookmarksInNewTabs(mDelegate.getSelectedBookmarks(), new TabDelegate(false),
+            openBookmarksInNewTabs(selectionDelegate.getSelectedItems(), new TabDelegate(false),
                     mDelegate.getModel());
-            mDelegate.clearSelection();
+            selectionDelegate.clearSelection();
             return true;
         } else if (menuItem.getItemId() == R.id.selection_open_in_incognito_tab_id) {
-            openBookmarksInNewTabs(mDelegate.getSelectedBookmarks(), new TabDelegate(true),
+            openBookmarksInNewTabs(selectionDelegate.getSelectedItems(), new TabDelegate(true),
                     mDelegate.getModel());
-            mDelegate.clearSelection();
+            selectionDelegate.clearSelection();
             return true;
         }
 
@@ -136,70 +110,6 @@
         return false;
     }
 
-    /**
-     * Update the current navigation button (the top-left icon on LTR)
-     * @param navigationButton one of NAVIGATION_BUTTON_* constants.
-     */
-    private void setNavigationButton(int navigationButton) {
-        int iconResId = 0;
-        int contentDescriptionId = 0;
-
-        if (navigationButton == NAVIGATION_BUTTON_MENU && !mDelegate.doesDrawerExist()) {
-            mNavigationButton = NAVIGATION_BUTTON_NONE;
-        } else {
-            mNavigationButton = navigationButton;
-        }
-
-        if (mNavigationButton == NAVIGATION_BUTTON_MENU) {
-            initActionBarDrawerToggle();
-            // ActionBarDrawerToggle will take care of icon and content description, so just return.
-            return;
-        }
-
-        if (mActionBarDrawerToggle != null) {
-            mActionBarDrawerToggle.setDrawerIndicatorEnabled(false);
-            mDelegate.getDrawerLayout().setDrawerListener(null);
-        }
-
-        setNavigationOnClickListener(this);
-
-        switch (mNavigationButton) {
-            case NAVIGATION_BUTTON_NONE:
-                break;
-            case NAVIGATION_BUTTON_BACK:
-                iconResId = R.drawable.bookmark_back_normal;
-                contentDescriptionId = R.string.accessibility_toolbar_btn_back;
-                break;
-            case NAVIGATION_BUTTON_SELECTION_BACK:
-                iconResId = R.drawable.bookmark_cancel_active;
-                contentDescriptionId = R.string.accessibility_bookmark_cancel_selection;
-                break;
-            default:
-                assert false : "Incorrect navigationButton argument";
-        }
-
-        if (iconResId == 0) {
-            setNavigationIcon(null);
-        } else {
-            setNavigationIcon(iconResId);
-        }
-        setNavigationContentDescription(contentDescriptionId);
-    }
-
-    /**
-     * Set up ActionBarDrawerToggle, a.k.a. hamburger button.
-     */
-    private void initActionBarDrawerToggle() {
-        // Sadly, the only way to set correct toolbar button listener for ActionBarDrawerToggle
-        // is constructing, so we will need to construct every time we re-show this button.
-        mActionBarDrawerToggle = new ActionBarDrawerToggle((Activity) getContext(),
-                mDelegate.getDrawerLayout(), this,
-                R.string.accessibility_bookmark_drawer_toggle_btn_open,
-                R.string.accessibility_bookmark_drawer_toggle_btn_close);
-        mDelegate.getDrawerLayout().setDrawerListener(mActionBarDrawerToggle);
-        mActionBarDrawerToggle.syncState();
-    }
-
     void showLoadingUi() {
         setTitle(null);
         setNavigationButton(NAVIGATION_BUTTON_NONE);
@@ -215,6 +125,12 @@
         mDelegate.addUIObserver(this);
         if (!delegate.isDialogUi()) getMenu().removeItem(R.id.close_menu_id);
         delegate.getModel().addObserver(mBookmarkModelObserver);
+
+        // This class will handle setting the title. Pass 0 to the superclass so that it doesn't
+        // try to set the title when a selection is cleared.
+        int titleResId = 0;
+        initialize(delegate.getSelectionDelegate(), titleResId, delegate.getDrawerLayout(),
+                R.id.normal_menu_group, R.id.selection_mode_menu_group);
     }
 
     @Override
@@ -256,17 +172,8 @@
 
     @Override
     public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {
-        boolean wasSelectionEnabled = mIsSelectionEnabled;
-        mIsSelectionEnabled = mDelegate.isSelectionEnabled();
-        NumberRollView numberRollView = (NumberRollView) findViewById(R.id.selection_mode_number);
+        super.onSelectionStateChange(selectedBookmarks);
         if (mIsSelectionEnabled) {
-            setOverflowIcon(TintedDrawable.constructTintedDrawable(getResources(),
-                    R.drawable.btn_menu, android.R.color.white));
-            setNavigationButton(NAVIGATION_BUTTON_SELECTION_BACK);
-            setTitle(null);
-
-            getMenu().setGroupVisible(R.id.normal_menu_group, false);
-            getMenu().setGroupVisible(R.id.selection_mode_menu_group, true);
             // Editing a bookmark action on multiple selected items doesn't make sense. So disable.
             getMenu().findItem(R.id.selection_mode_edit_menu_id).setVisible(
                     selectedBookmarks.size() == 1);
@@ -289,23 +196,7 @@
                     break;
                 }
             }
-            setBackgroundColor(
-                    ApiCompatibilityUtils.getColor(getResources(), R.color.light_active_color));
-
-            numberRollView.setVisibility(View.VISIBLE);
-            if (!wasSelectionEnabled) numberRollView.setNumber(0, false);
-            numberRollView.setNumber(selectedBookmarks.size(), true);
         } else {
-            setOverflowIcon(TintedDrawable.constructTintedDrawable(getResources(),
-                    R.drawable.btn_menu));
-            getMenu().setGroupVisible(R.id.normal_menu_group, true);
-            getMenu().setGroupVisible(R.id.selection_mode_menu_group, false);
-            setBackgroundColor(ApiCompatibilityUtils.getColor(getResources(),
-                    R.color.appbar_background));
-
-            numberRollView.setVisibility(View.GONE);
-            numberRollView.setNumber(0, false);
-
             mDelegate.notifyStateChange(this);
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkContentView.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkContentView.java
index 2e7593e9..4b64f68 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkContentView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkContentView.java
@@ -63,8 +63,8 @@
      *         method. False otherwise.
      */
     boolean onBackPressed() {
-        if (mDelegate != null && mDelegate.isSelectionEnabled()) {
-            mDelegate.clearSelection();
+        if (mDelegate != null && mDelegate.getSelectionDelegate().isSelectionEnabled()) {
+            mDelegate.getSelectionDelegate().clearSelection();
             return true;
         }
         return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkDelegate.java
index 19bab5cf..a450b01 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkDelegate.java
@@ -8,10 +8,9 @@
 
 import org.chromium.chrome.browser.favicon.LargeIconBridge;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
 import org.chromium.components.bookmarks.BookmarkId;
 
-import java.util.List;
-
 /**
  * Interface used by UI components in the main bookmarks UI to broadcast UI change notifications
  * and get bookmark data model.
@@ -49,31 +48,9 @@
     void openFolder(BookmarkId folder);
 
     /**
-     * Clear all selected items. After this call, {@link #isSelectionEnabled()} will return false.
+     * @return The SelectionDelegate responsible for tracking selected bookmarks.
      */
-    void clearSelection();
-
-    /**
-     * Toggle the selection state of a bookmark. If the given bookmark is not
-     * editable, it will take no effect.
-     * @return True if the bookmark is selected after toggling. False otherwise.
-     */
-    boolean toggleSelectionForBookmark(BookmarkId bookmark);
-
-    /**
-     * @return True if the bookmark is selected. False otherwise.
-     */
-    boolean isBookmarkSelected(BookmarkId bookmark);
-
-    /**
-     * @return Whether selection is happening.
-     */
-    boolean isSelectionEnabled();
-
-    /**
-     * @return The list of bookmarks that are currently selected by the user.
-     */
-    List<BookmarkId> getSelectedBookmarks();
+    SelectionDelegate<BookmarkId> getSelectionDelegate();
 
     /**
      * Notifies the current mode set event to the given observer. For example, if the current mode
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
index 432eda4..195c53d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -25,12 +25,9 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
 import org.chromium.components.bookmarks.BookmarkId;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
 import java.util.Stack;
 
 /**
@@ -47,13 +44,13 @@
     private BookmarkUndoController mUndoController;
     private final ObserverList<BookmarkUIObserver> mUIObservers =
             new ObserverList<BookmarkUIObserver>();
-    private Set<BookmarkId> mSelectedBookmarks = new HashSet<>();
     private BasicNativePage mNativePage;
     private BookmarkContentView mContentView;
     private BookmarkSearchView mSearchView;
     private ViewSwitcher mViewSwitcher;
     private DrawerLayout mDrawer;
     private BookmarkDrawerListView mDrawerListView;
+    private SelectionDelegate<BookmarkId> mSelectionDelegate;
     private final Stack<BookmarkUIState> mStateStack = new Stack<>();
     private LargeIconBridge mLargeIconBridge;
     private String mInitialUrl;
@@ -75,13 +72,13 @@
                     openFolder(parent.getId());
                 }
             }
-            clearSelection();
+            mSelectionDelegate.clearSelection();
         }
 
         @Override
         public void bookmarkNodeMoved(BookmarkItem oldParent, int oldIndex, BookmarkItem newParent,
                 int newIndex) {
-            clearSelection();
+            mSelectionDelegate.clearSelection();
         }
 
         @Override
@@ -91,7 +88,7 @@
             if (getCurrentState() == BookmarkUIState.STATE_FOLDER) {
                 setState(mStateStack.peek());
             }
-            clearSelection();
+            mSelectionDelegate.clearSelection();
         }
     };
 
@@ -118,6 +115,14 @@
         mActivity = activity;
         mIsDialogUi = isDialogUi;
 
+        mSelectionDelegate = new SelectionDelegate<BookmarkId>() {
+            @Override
+            public boolean toggleSelectionForItem(BookmarkId bookmark) {
+                if (!mBookmarkModel.getBookmarkById(bookmark).isEditable()) return false;
+                return super.toggleSelectionForItem(bookmark);
+            }
+        };
+
         mBookmarkModel = new BookmarkModel();
         mMainView = (ViewGroup) mActivity.getLayoutInflater().inflate(R.layout.bookmark_main, null);
         mDrawer = (DrawerLayout) mMainView.findViewById(R.id.bookmark_drawer_layout);
@@ -277,7 +282,7 @@
             }
         }
 
-        clearSelection();
+        mSelectionDelegate.clearSelection();
 
         for (BookmarkUIObserver observer : mUIObservers) {
             notifyStateChange(observer);
@@ -304,39 +309,8 @@
     }
 
     @Override
-    public void clearSelection() {
-        mSelectedBookmarks.clear();
-        for (BookmarkUIObserver observer : mUIObservers) {
-            observer.onSelectionStateChange(new ArrayList<BookmarkId>(mSelectedBookmarks));
-        }
-    }
-
-    @Override
-    public boolean toggleSelectionForBookmark(BookmarkId bookmark) {
-        if (!mBookmarkModel.getBookmarkById(bookmark).isEditable()) return false;
-
-        if (mSelectedBookmarks.contains(bookmark)) mSelectedBookmarks.remove(bookmark);
-        else mSelectedBookmarks.add(bookmark);
-        for (BookmarkUIObserver observer : mUIObservers) {
-            observer.onSelectionStateChange(new ArrayList<BookmarkId>(mSelectedBookmarks));
-        }
-
-        return isBookmarkSelected(bookmark);
-    }
-
-    @Override
-    public boolean isBookmarkSelected(BookmarkId bookmark) {
-        return mSelectedBookmarks.contains(bookmark);
-    }
-
-    @Override
-    public boolean isSelectionEnabled() {
-        return !mSelectedBookmarks.isEmpty();
-    }
-
-    @Override
-    public List<BookmarkId> getSelectedBookmarks() {
-        return new ArrayList<BookmarkId>(mSelectedBookmarks);
+    public SelectionDelegate<BookmarkId> getSelectionDelegate() {
+        return mSelectionDelegate;
     }
 
     @Override
@@ -379,7 +353,7 @@
 
     @Override
     public void openBookmark(BookmarkId bookmark, int launchLocation) {
-        clearSelection();
+        mSelectionDelegate.clearSelection();
         if (BookmarkUtils.openBookmark(
                     mBookmarkModel, mActivity, bookmark, launchLocation)) {
             BookmarkUtils.finishActivityOnPhone(mActivity);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRecyclerView.java
index 5bf0ba1..5e1f5f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRecyclerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRecyclerView.java
@@ -111,7 +111,7 @@
 
     @Override
     public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {
-        if (!mDelegate.isSelectionEnabled()) {
+        if (!mDelegate.getSelectionDelegate().isSelectionEnabled()) {
             for (int i = 0; i < getLayoutManager().getChildCount(); ++i) {
                 View child = getLayoutManager().getChildAt(i);
                 if (child instanceof Checkable) ((Checkable) child).setChecked(false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java
index b5ccc51..933eab7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java
@@ -7,14 +7,10 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
-import android.widget.Checkable;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ListPopupWindow;
 import android.widget.TextView;
@@ -22,6 +18,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
 import org.chromium.chrome.browser.widget.TintedImageButton;
+import org.chromium.chrome.browser.widget.selection.SelectableItemView;
 import org.chromium.components.bookmarks.BookmarkId;
 
 import java.util.List;
@@ -29,13 +26,11 @@
 /**
  * Common logic for bookmark and folder rows.
  */
-abstract class BookmarkRow extends FrameLayout implements BookmarkUIObserver,
-        Checkable, OnClickListener, OnLongClickListener {
+abstract class BookmarkRow extends SelectableItemView<BookmarkId> implements BookmarkUIObserver {
 
     protected ImageView mIconImageView;
     protected TextView mTitleView;
     protected TintedImageButton mMoreIcon;
-    private BookmarkItemHighlightView mHighlightView;
 
     protected BookmarkDelegate mDelegate;
     protected BookmarkId mBookmarkId;
@@ -59,19 +54,12 @@
         clearPopup();
         if (isSelectable()) {
             mMoreIcon.setVisibility(bookmarkItem.isEditable() ? VISIBLE : GONE);
-            setChecked(mDelegate.isBookmarkSelected(bookmarkId));
+            setChecked(mDelegate.getSelectionDelegate().isItemSelected(bookmarkId));
         }
+        super.setId(bookmarkId);
         return bookmarkItem;
     }
 
-    /**
-     * Same as {@link OnClickListener#onClick(View)} on this.
-     * Subclasses should override this instead of setting their own OnClickListener because this
-     * class handles onClick events in selection mode, and won't forward events to subclasses in
-     * that case.
-     */
-    protected abstract void onClick();
-
     private void initialize() {
         mDelegate.addUIObserver(this);
         updateSelectionState();
@@ -90,7 +78,8 @@
     }
 
     private void updateSelectionState() {
-        if (isSelectable()) mMoreIcon.setClickable(!mDelegate.isSelectionEnabled());
+        if (isSelectable()) mMoreIcon.setClickable(
+                !mDelegate.getSelectionDelegate().isSelectionEnabled());
     }
 
     /**
@@ -150,7 +139,8 @@
                 public void onItemClick(AdapterView<?> parent, View view, int position,
                         long id) {
                     if (position == 0) {
-                        setChecked(mDelegate.toggleSelectionForBookmark(mBookmarkId));
+                        setChecked(mDelegate.getSelectionDelegate().toggleSelectionForItem(
+                                mBookmarkId));
                     } else if (position == 1) {
                         BookmarkItem item = mDelegate.getModel().getBookmarkById(mBookmarkId);
                         if (item.isFolder()) {
@@ -187,8 +177,6 @@
         mTitleView = (TextView) findViewById(R.id.title);
 
         if (isSelectable()) {
-            mHighlightView = (BookmarkItemHighlightView) findViewById(R.id.highlight);
-
             mMoreIcon = (TintedImageButton) findViewById(R.id.more);
             mMoreIcon.setVisibility(VISIBLE);
             mMoreIcon.setOnClickListener(new OnClickListener() {
@@ -198,9 +186,6 @@
                 }
             });
         }
-
-        setOnClickListener(this);
-        setOnLongClickListener(this);
     }
 
     @Override
@@ -208,7 +193,6 @@
         super.onAttachedToWindow();
         mIsAttachedToWindow = true;
         if (mDelegate != null) {
-            setChecked(mDelegate.isBookmarkSelected(mBookmarkId));
             initialize();
         }
     }
@@ -218,38 +202,19 @@
         super.onDetachedFromWindow();
         mIsAttachedToWindow = false;
         cleanup();
-        setChecked(false);
     }
 
-    // OnClickListener implementation.
-
-    @Override
-    public final void onClick(View view) {
-        assert view == this;
-
-        if (mDelegate.isSelectionEnabled() && isSelectable()) {
-            onLongClick(view);
-        } else {
-            onClick();
-        }
-    }
-
-    // OnLongClickListener implementation.
-
+    // SelectableItem overrides.
     @Override
     public boolean onLongClick(View view) {
-        assert view == this;
         if (!isSelectable()) return false;
-        setChecked(mDelegate.toggleSelectionForBookmark(mBookmarkId));
-        return true;
+        return super.onLongClick(view);
     }
 
-    // Checkable implementations.
-
     @Override
     public boolean isChecked() {
-        if (mHighlightView == null) return false;
-        return mHighlightView.isChecked();
+        if (!isSelectable()) return false;
+        return super.isChecked();
     }
 
     @Override
@@ -260,13 +225,20 @@
     @Override
     public void setChecked(boolean checked) {
         // Unselectable rows do not have highlight view.
-        if (mHighlightView != null) mHighlightView.setChecked(checked);
+        if (isSelectable()) super.setChecked(checked);
+    }
+
+    @Override
+    public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {
+        if (isSelectable()) super.onSelectionStateChange(selectedBookmarks);
+        updateSelectionState();
     }
 
     // BookmarkUIObserver implementations.
 
     @Override
     public void onBookmarkDelegateInitialized(BookmarkDelegate delegate) {
+        super.setSelectionDelegate(delegate.getSelectionDelegate());
         mDelegate = delegate;
         if (mIsAttachedToWindow) initialize();
     }
@@ -284,8 +256,4 @@
     public void onFolderStateSet(BookmarkId folder) {
     }
 
-    @Override
-    public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {
-        updateSelectionState();
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchView.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchView.java
index f6c1a44..aa27a2e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkSearchView.java
@@ -136,7 +136,7 @@
         mHistoryResultSwitcher = (HistoryResultSwitcher) findViewById(R.id.history_result_switcher);
 
         Toolbar searchBar = (Toolbar) findViewById(R.id.search_bar);
-        searchBar.setNavigationIcon(R.drawable.bookmark_back_normal);
+        searchBar.setNavigationIcon(R.drawable.back_normal);
         searchBar.setNavigationContentDescription(R.string.accessibility_toolbar_btn_back);
         searchBar.setNavigationOnClickListener(new OnClickListener() {
             @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIObserver.java
index 5c9982bb..3bc83e1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIObserver.java
@@ -4,16 +4,15 @@
 
 package org.chromium.chrome.browser.bookmarks;
 
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
 import org.chromium.components.bookmarks.BookmarkId;
 
-import java.util.List;
-
 /**
  * Observer interface to get notification for UI mode changes, bookmark changes, and other related
  * event that affects UI. All bookmark UI components are expected to implement this and
  * update themselves correctly on each event.
  */
-interface BookmarkUIObserver {
+interface BookmarkUIObserver extends SelectionObserver<BookmarkId> {
     void onBookmarkDelegateInitialized(BookmarkDelegate delegate);
 
     /**
@@ -30,12 +29,4 @@
      * @see BookmarkDelegate#openFolder(BookmarkId)
      */
     void onFolderStateSet(BookmarkId folder);
-
-    /**
-     * Please refer to
-     * {@link BookmarkDelegate#toggleSelectionForBookmark(BookmarkId)},
-     * {@link BookmarkDelegate#clearSelection()} and
-     * {@link BookmarkDelegate#getSelectedBookmarks()}
-     */
-    void onSelectionStateChange(List<BookmarkId> selectedBookmarks);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java
index dd92ef9..9e16457 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarkswidget/BookmarkWidgetService.java
@@ -466,7 +466,7 @@
             views.setTextViewText(R.id.title, TextUtils.isEmpty(title) ? url : title);
 
             if (bookmark == mCurrentFolder.folder) {
-                views.setImageViewResource(R.id.favicon, R.drawable.bookmark_back_normal);
+                views.setImageViewResource(R.id.favicon, R.drawable.back_normal);
             } else if (bookmark.isFolder) {
                 views.setImageViewResource(R.id.favicon, R.drawable.bookmark_folder);
             } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 51ed88f..51342d04 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -104,18 +104,18 @@
     private static class PageLoadMetricsObserver implements PageLoadMetrics.Observer {
         private final CustomTabsConnection mConnection;
         private final CustomTabsSessionToken mSession;
-        private final WebContents mWebContents;
+        private final Tab mTab;
 
         public PageLoadMetricsObserver(CustomTabsConnection connection,
-                CustomTabsSessionToken session, WebContents webContents) {
+                CustomTabsSessionToken session, Tab tab) {
             mConnection = connection;
             mSession = session;
-            mWebContents = webContents;
+            mTab = tab;
         }
 
         @Override
         public void onFirstContentfulPaint(WebContents webContents, long firstContentfulPaintMs) {
-            if (webContents != mWebContents) return;
+            if (webContents != mTab.getWebContents()) return;
 
             mConnection.notifyPageLoadMetric(
                     mSession, PageLoadMetrics.FIRST_CONTENTFUL_PAINT, firstContentfulPaintMs);
@@ -430,7 +430,7 @@
                 getApplication(), mSession, mIntentDataProvider.isOpenedByChrome());
 
         mMetricsObserver = new PageLoadMetricsObserver(
-                CustomTabsConnection.getInstance(getApplication()), mSession, webContents);
+                CustomTabsConnection.getInstance(getApplication()), mSession, tab);
         tab.addObserver(mTabObserver);
         return tab;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
index 176f55c..c9629f94 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -224,7 +224,7 @@
         if (startTime > 0) builder.setWhen(startTime);
         Intent cancelIntent = buildActionIntent(
                 ACTION_DOWNLOAD_CANCEL, notificationId, downloadGuid, fileName);
-        builder.addAction(R.drawable.bookmark_cancel_active,
+        builder.addAction(R.drawable.btn_close_white,
                 mContext.getResources().getString(R.string.download_notification_cancel_button),
                 buildPendingIntent(cancelIntent, notificationId));
         Intent pauseIntent = buildActionIntent(
@@ -282,7 +282,7 @@
         Intent dismissIntent = new Intent(cancelIntent);
         dismissIntent.putExtra(EXTRA_NOTIFICATION_DISMISSED, true);
         builder.setDeleteIntent(buildPendingIntent(dismissIntent, entry.notificationId));
-        builder.addAction(R.drawable.bookmark_cancel_active,
+        builder.addAction(R.drawable.btn_close_white,
                 mContext.getResources().getString(R.string.download_notification_cancel_button),
                 buildPendingIntent(cancelIntent, entry.notificationId));
         Intent resumeIntent = buildActionIntent(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
index db81315..99d5765 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java
@@ -30,7 +30,7 @@
 
     /** Holds onto a View that displays information about a downloaded file. */
     static class ItemViewHolder extends RecyclerView.ViewHolder {
-        public View mItemView;
+        public DownloadItemView mItemView;
         public ImageView mIconView;
         public TextView mFilenameView;
         public TextView mHostnameView;
@@ -38,7 +38,10 @@
 
         public ItemViewHolder(View itemView) {
             super(itemView);
-            mItemView = itemView;
+
+            assert itemView instanceof DownloadItemView;
+            mItemView = (DownloadItemView) itemView;
+
             mIconView = (ImageView) itemView.findViewById(R.id.icon_view);
             mFilenameView = (TextView) itemView.findViewById(R.id.filename_view);
             mHostnameView = (TextView) itemView.findViewById(R.id.hostname_view);
@@ -88,6 +91,7 @@
     public ViewHolder createViewHolder(ViewGroup parent) {
         View v = LayoutInflater.from(parent.getContext()).inflate(
                 R.layout.download_item_view, parent, false);
+        ((DownloadItemView) v).setSelectionDelegate(mManager.getSelectionDelegate());
         return new ItemViewHolder(v);
     }
 
@@ -102,12 +106,7 @@
                 UrlUtilities.formatUrlForSecurityDisplay(item.getDownloadInfo().getUrl(), false));
         holder.mFilesizeView.setText(
                 Formatter.formatFileSize(context, item.getDownloadInfo().getContentLength()));
-        holder.mItemView.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                mManager.onDownloadItemClicked(item);
-            }
-        });
+        holder.mItemView.initialize(mManager, item);
 
         // Pick what icon to display for the item.
         int fileType = convertMimeTypeToFilterType(item.getDownloadInfo().getMimeType());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
new file mode 100644
index 0000000..303d202
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
@@ -0,0 +1,43 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.download.ui;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import org.chromium.chrome.browser.download.DownloadItem;
+import org.chromium.chrome.browser.widget.selection.SelectableItemView;
+
+/**
+ * The view for a downloaded item displayed in the Downloads list.
+ */
+public class DownloadItemView extends SelectableItemView<String> {
+    DownloadManagerUi mManager;
+    DownloadItem mItem;
+
+    /**
+     * Constructor for inflating from XML.
+     */
+    public DownloadItemView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Initialize the DownloadItemView. Must be called before the item can respond to click events.
+     *
+     * @param manager The DownloadManagerUi responsible for opening DownloadItems.
+     * @param item The DownloadItem represented by this DownloadItemView.
+     */
+    public void initialize(DownloadManagerUi manager, DownloadItem item) {
+        mManager = manager;
+        mItem = item;
+        setId(item.getId());
+    }
+
+    @Override
+    public void onClick() {
+        mManager.onDownloadItemClicked(mItem);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
index 4eeffec..7fc67ca5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java
@@ -5,22 +5,17 @@
 package org.chromium.chrome.browser.download.ui;
 
 import android.content.Context;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.widget.Toolbar;
 import android.util.AttributeSet;
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.download.ui.DownloadManagerUi.DownloadUiObserver;
+import org.chromium.chrome.browser.widget.selection.SelectionToolbar;
 import org.chromium.ui.base.DeviceFormFactor;
 
 /**
  * Handles toolbar functionality for the {@link DownloadManagerUi}.
  */
-public class DownloadManagerToolbar extends Toolbar implements DownloadUiObserver {
-
-    private ActionBarDrawerToggle mActionBarDrawerToggle;
-
+public class DownloadManagerToolbar extends SelectionToolbar<String> implements DownloadUiObserver {
     public DownloadManagerToolbar(Context context, AttributeSet attrs) {
         super(context, attrs);
         inflateMenu(R.menu.download_manager_menu);
@@ -28,15 +23,6 @@
 
     @Override
     public void initialize(DownloadManagerUi manager) {
-        if (manager.getView() instanceof DrawerLayout) {
-            DrawerLayout drawerLayout = (DrawerLayout) manager.getView();
-            mActionBarDrawerToggle = new ActionBarDrawerToggle(manager.getActivity(),
-                    drawerLayout, (Toolbar) manager.getView().findViewById(R.id.action_bar),
-                    R.string.accessibility_bookmark_drawer_toggle_btn_open,
-                    R.string.accessibility_bookmark_drawer_toggle_btn_close);
-            drawerLayout.addDrawerListener(mActionBarDrawerToggle);
-            mActionBarDrawerToggle.syncState();
-        }
         if (DeviceFormFactor.isTablet(getContext())) {
             getMenu().findItem(R.id.close_menu_id).setVisible(false);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
index 7ff6df5e..df1a9e5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java
@@ -30,6 +30,7 @@
 import org.chromium.chrome.browser.download.DownloadManagerService;
 import org.chromium.chrome.browser.widget.FadingShadow;
 import org.chromium.chrome.browser.widget.FadingShadowView;
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.widget.Toast;
 
@@ -78,10 +79,14 @@
 
     private BasicNativePage mNativePage;
 
+    private SelectionDelegate<String> mSelectionDelegate;
+
     public DownloadManagerUi(Activity activity) {
         mActivity = activity;
         mMainView = (ViewGroup) LayoutInflater.from(activity).inflate(R.layout.download_main, null);
 
+        mSelectionDelegate = new SelectionDelegate<String>();
+
         mHistoryAdapter = new DownloadHistoryAdapter();
         mHistoryAdapter.initialize(this);
 
@@ -91,6 +96,12 @@
         mToolbar = (DownloadManagerToolbar) mMainView.findViewById(R.id.action_bar);
         mToolbar.initialize(this);
         mToolbar.setOnMenuItemClickListener(this);
+        DrawerLayout drawerLayout = null;
+        if (!DeviceFormFactor.isLargeTablet(activity)) {
+            drawerLayout = (DrawerLayout) mMainView;
+        }
+        mToolbar.initialize(mSelectionDelegate, R.string.menu_downloads, drawerLayout,
+                R.id.normal_menu_group, R.id.selection_mode_menu_group);
 
         mSpaceDisplay = new SpaceDisplay(mMainView, mHistoryAdapter);
         mFilterView = (ListView) mMainView.findViewById(R.id.section_list);
@@ -147,6 +158,10 @@
                 return true;
             }
         }
+        if (mSelectionDelegate.isSelectionEnabled()) {
+            mSelectionDelegate.clearSelection();
+            return true;
+        }
         return false;
     }
 
@@ -158,6 +173,13 @@
     }
 
     /**
+     * @return The SelectionDelegate responsible for tracking selected download items.
+     */
+    public SelectionDelegate<String> getSelectionDelegate() {
+        return mSelectionDelegate;
+    }
+
+    /**
      * Sets the download manager to the state that the url represents.
      */
     public void updateForUrl(String url) {
@@ -171,6 +193,7 @@
             mActivity.finish();
             return true;
         }
+        // TODO(twellington): Hook up delete and share icons.
         return false;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemHighlightView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemHighlightView.java
similarity index 81%
rename from chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemHighlightView.java
rename to chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemHighlightView.java
index 19073cb..b4930df 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemHighlightView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemHighlightView.java
@@ -1,8 +1,8 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.bookmarks;
+package org.chromium.chrome.browser.widget.selection;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -15,9 +15,9 @@
 import org.chromium.chrome.R;
 
 /**
- * Highlight overlay view for items on the main grid.
+ * Highlight overlay view for selectable items.
  */
-public class BookmarkItemHighlightView extends View implements Checkable {
+public class SelectableItemHighlightView extends View implements Checkable {
     public static final int ANIMATION_DURATION_MS = 150;
     private static final int[] CHECKED_STATE_SET = {android.R.attr.state_checked};
     private boolean mIsChecked;
@@ -25,12 +25,12 @@
     /**
      * Constructor for inflating from XML.
      */
-    public BookmarkItemHighlightView(Context context, AttributeSet attrs) {
+    public SelectableItemHighlightView(Context context, AttributeSet attrs) {
         super(context, attrs);
         Drawable clickDrawable = context.obtainStyledAttributes(new int[] {
                 android.R.attr.selectableItemBackground }).getDrawable(0);
         Drawable longClickDrawable = ApiCompatibilityUtils.getDrawable(context.getResources(),
-                R.drawable.bookmark_item_highlight);
+                R.drawable.selectable_item_highlight);
         LayerDrawable ld = new LayerDrawable(new Drawable[] {clickDrawable, longClickDrawable});
         setBackground(ld);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
new file mode 100644
index 0000000..ca66a34
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
@@ -0,0 +1,146 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.widget.selection;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLongClickListener;
+import android.widget.Checkable;
+import android.widget.FrameLayout;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
+
+import java.util.List;
+
+/**
+ * An item that can be selected. When selected, the item will be highlighted. A selection is
+ * initially established via long-press. If a selection is already established, clicking on the item
+ * will toggle its selection.
+ *
+ * @param <E> The type of the unique identifier for this SelectableItem.
+ */
+public abstract class SelectableItemView<E> extends FrameLayout implements Checkable,
+        OnClickListener, OnLongClickListener, SelectionObserver<E> {
+    private SelectionDelegate<E> mSelectionDelegate;
+    private SelectableItemHighlightView mHighlightView;
+    private E mId;
+
+    /**
+     * Constructor for inflating from XML.
+     */
+    public SelectableItemView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Destroys and cleans up itself.
+     */
+    public void destroy() {
+        if (mSelectionDelegate != null) {
+            mSelectionDelegate.removeObserver(this);
+        }
+    }
+
+    /**
+     * Sets the SelectionDelegate and registers this object as an observer. The SelectionDelegate
+     * must be set before the item can respond to click events.
+     * @param delegate The SelectionDelegate that will inform this item of selection changes.
+     */
+    public void setSelectionDelegate(SelectionDelegate<E> delegate) {
+        if (mSelectionDelegate != delegate) {
+            if (mSelectionDelegate != null) mSelectionDelegate.removeObserver(this);
+            mSelectionDelegate = delegate;
+            mSelectionDelegate.addObserver(this);
+        }
+    }
+
+    /**
+     * @param id The unique identifier for this SelectableItem.
+     */
+    public void setId(E id) {
+        mId = id;
+        setChecked(mSelectionDelegate.isItemSelected(id));
+    }
+
+    // FrameLayout implementations.
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        inflate(getContext(), R.layout.selectable_item_highlight_view, this);
+        mHighlightView = (SelectableItemHighlightView) findViewById(R.id.highlight);
+
+        setOnClickListener(this);
+        setOnLongClickListener(this);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (mSelectionDelegate != null) {
+            setChecked(mSelectionDelegate.isItemSelected(mId));
+        }
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        setChecked(false);
+    }
+
+    // OnClickListener implementation.
+    @Override
+    public final void onClick(View view) {
+        assert view == this;
+
+        if (mSelectionDelegate.isSelectionEnabled()) {
+            onLongClick(view);
+        }  else {
+            onClick();
+        }
+    }
+
+    // OnLongClickListener implementation.
+    @Override
+    public boolean onLongClick(View view) {
+        assert view == this;
+        boolean checked = mSelectionDelegate.toggleSelectionForItem(mId);
+        setChecked(checked);
+        return true;
+    }
+
+    // Checkable implementations.
+    @Override
+    public boolean isChecked() {
+        return mHighlightView.isChecked();
+    }
+
+    @Override
+    public void toggle() {
+        setChecked(!isChecked());
+    }
+
+    @Override
+    public void setChecked(boolean checked) {
+        mHighlightView.setChecked(checked);
+    }
+
+    // SelectionObserver implementation.
+    @Override
+    public void onSelectionStateChange(List<E> selectedItems) {
+        setChecked(mSelectionDelegate.isItemSelected(mId));
+    }
+
+    /**
+     * Same as {@link OnClickListener#onClick(View)} on this.
+     * Subclasses should override this instead of setting their own OnClickListener because this
+     * class handles onClick events in selection mode, and won't forward events to subclasses in
+     * that case.
+     */
+    protected abstract void onClick();
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java
new file mode 100644
index 0000000..f66b43e0
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java
@@ -0,0 +1,103 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.widget.selection;
+
+import org.chromium.base.ObserverList;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A generic delegate used to keep track of selected items.
+ * @param <E> The type of the unique identifier for selectable items this delegate interacts with.
+ */
+public class SelectionDelegate<E> {
+
+    /**
+     * Observer interface to be notified of selection changes.
+     */
+    public interface SelectionObserver<E> {
+        /**
+         * Called when the set of selected items has changed.
+         * @param selectedItems The list of currently selected items. An empty list indicates there
+         *                      is no selection.
+         */
+        public void onSelectionStateChange(List<E> selectedItems);
+    }
+
+    private Set<E> mSelectedItems = new HashSet<>();
+    private ObserverList<SelectionObserver<E>> mObservers = new ObserverList<>();
+
+    /**
+     * Toggles the selected state for the given item.
+     * @param itemId The id of the item to toggle.
+     * @return Whether the item is selected.
+     */
+    public boolean toggleSelectionForItem(E itemId) {
+        if (mSelectedItems.contains(itemId)) mSelectedItems.remove(itemId);
+        else mSelectedItems.add(itemId);
+
+        notifyObservers();
+
+        return isItemSelected(itemId);
+    }
+
+    /**
+     * True if the bookmark is selected. False otherwise.
+     * @param itemId The id of the item.
+     * @return Whether the item is selected.
+     */
+    public boolean isItemSelected(E itemId) {
+        return mSelectedItems.contains(itemId);
+    }
+
+    /**
+     * @return Whether any items are selected.
+     */
+    public boolean isSelectionEnabled() {
+        return !mSelectedItems.isEmpty();
+    }
+
+   /**
+    * Clears all selected items.
+    */
+    public void clearSelection() {
+        mSelectedItems.clear();
+        notifyObservers();
+    }
+
+    /**
+     * @return The list of selected items.
+     */
+    public List<E> getSelectedItems() {
+        return new ArrayList<E>(mSelectedItems);
+    }
+
+    /**
+     * Adds a SelectionObserver to be notified of selection changes.
+     * @param observer The SelectionObserver to add.
+     */
+    public void addObserver(SelectionObserver<E> observer) {
+        mObservers.addObserver(observer);
+    }
+
+    /**
+     * Removes a SelectionObserver.
+     * @param observer The SelectionObserver to remove.
+     */
+    public void removeObserver(SelectionObserver<E> observer) {
+        mObservers.removeObserver(observer);
+    }
+
+    private void notifyObservers() {
+        List<E> selectedItems = getSelectedItems();
+        for (SelectionObserver<E> observer : mObservers) {
+            observer.onSelectionStateChange(selectedItems);
+        }
+    }
+
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionToolbar.java
new file mode 100644
index 0000000..7cdcf73
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectionToolbar.java
@@ -0,0 +1,230 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.widget.selection;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.annotation.CallSuper;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.widget.Toolbar;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import org.chromium.base.ApiCompatibilityUtils;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.NumberRollView;
+import org.chromium.chrome.browser.widget.TintedDrawable;
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * A toolbar that changes its view depending on whether a selection is established. The XML inflated
+ * for this class must include number_roll_view.xml.
+ *
+ * @param <E> The type of the unique identifier for selectable items this toolbar interacts with.
+ */
+public class SelectionToolbar<E> extends Toolbar implements SelectionObserver<E>, OnClickListener {
+    /** No navigation button is displayed. **/
+    protected static final int NAVIGATION_BUTTON_NONE = 0;
+    /** Button to open the DrawerLayout. Only valid if mDrawerLayout is set. **/
+    protected static final int NAVIGATION_BUTTON_MENU = 1;
+    /** Button to navigate back. This calls {@link #onNavigationBack()}. **/
+    protected static final int NAVIGATION_BUTTON_BACK = 2;
+    /** Button to clear the selection. **/
+    protected static final int NAVIGATION_BUTTON_SELECTION_BACK = 3;
+
+    protected boolean mIsSelectionEnabled;
+    protected SelectionDelegate<E> mSelectionDelegate;
+
+    private NumberRollView mNumberRollView;
+    private DrawerLayout mDrawerLayout;
+    private ActionBarDrawerToggle mActionBarDrawerToggle;
+    private int mNavigationButton;
+    private int mTitleResId;
+    private int mNormalGroupResId;
+    private int mSelectedGroupResId;
+
+    /**
+     * Constructor for inflating from XML.
+     */
+    public SelectionToolbar(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Destroys and cleans up itself.
+     */
+    public void destroy() {
+        if (mSelectionDelegate != null) {
+            mSelectionDelegate.removeObserver(this);
+        }
+    }
+
+    /**
+     * Initializes the SelectionToolbar.
+     *
+     * @param delegate The SelectionDelegate that will inform the toolbar of selection changes.
+     * @param titleResId The resource id of the title string. May be 0 if this class shouldn't set
+     *                   set a title when the selection is cleared.
+     * @param drawerLayout The DrawerLayout whose navigation icon is displayed in this toolbar.
+     * @param normalGroupResId The resource id of the menu group to show when a selection isn't
+     *                         established.
+     * @param selectedGroupResId The resource id of the menu item to show when a selection is
+     *                           established.
+     */
+    public void initialize(SelectionDelegate<E> delegate, int titleResId,
+            @Nullable DrawerLayout drawerLayout, int normalGroupResId, int selectedGroupResId) {
+        mTitleResId = titleResId;
+        mDrawerLayout = drawerLayout;
+        mNormalGroupResId = normalGroupResId;
+        mSelectedGroupResId = selectedGroupResId;
+
+        mSelectionDelegate = delegate;
+        mSelectionDelegate.addObserver(this);
+
+        if (mDrawerLayout != null) initActionBarDrawerToggle();
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mNumberRollView = (NumberRollView) findViewById(R.id.selection_mode_number);
+    }
+
+    @Override
+    @CallSuper
+    public void onSelectionStateChange(List<E> selectedItems) {
+        boolean wasSelectionEnabled = mIsSelectionEnabled;
+        mIsSelectionEnabled = mSelectionDelegate.isSelectionEnabled();
+
+        if (mIsSelectionEnabled) {
+            // TODO(twellington): add the concept of normal & selected tint to apply to all
+            //                    toolbar buttons.
+            setOverflowIcon(TintedDrawable.constructTintedDrawable(getResources(),
+                    R.drawable.btn_menu, android.R.color.white));
+            setNavigationButton(NAVIGATION_BUTTON_SELECTION_BACK);
+            setTitle(null);
+
+            getMenu().setGroupVisible(mNormalGroupResId, false);
+            getMenu().setGroupVisible(mSelectedGroupResId, true);
+
+            setBackgroundColor(
+                    ApiCompatibilityUtils.getColor(getResources(), R.color.light_active_color));
+
+            mNumberRollView.setVisibility(View.VISIBLE);
+            if (!wasSelectionEnabled) mNumberRollView.setNumber(0, false);
+            mNumberRollView.setNumber(selectedItems.size(), true);
+
+        } else {
+            setOverflowIcon(TintedDrawable.constructTintedDrawable(getResources(),
+                    R.drawable.btn_menu));
+            getMenu().setGroupVisible(mNormalGroupResId, true);
+            getMenu().setGroupVisible(mSelectedGroupResId, false);
+            setBackgroundColor(ApiCompatibilityUtils.getColor(getResources(),
+                    R.color.appbar_background));
+
+            if (mTitleResId != 0) setTitle(mTitleResId);
+            setNavigationButton(NAVIGATION_BUTTON_MENU);
+
+            mNumberRollView.setVisibility(View.GONE);
+            mNumberRollView.setNumber(0, false);
+        }
+    }
+
+    @Override
+    public void onClick(View view) {
+        switch (mNavigationButton) {
+            case NAVIGATION_BUTTON_NONE:
+                break;
+            case NAVIGATION_BUTTON_MENU:
+                // ActionBarDrawerToggle handles this.
+                break;
+            case NAVIGATION_BUTTON_BACK:
+                onNavigationBack();
+                break;
+            case NAVIGATION_BUTTON_SELECTION_BACK:
+                mSelectionDelegate.clearSelection();
+                break;
+            default:
+                assert false : "Incorrect navigation button state";
+        }
+    }
+
+    /**
+     * Handle a click on the navigation back button. Subclasses should override this method if
+     * navigation back is a valid toolbar action.
+     */
+    protected void onNavigationBack() {}
+
+    /**
+     * Update the current navigation button (the top-left icon on LTR)
+     * @param navigationButton one of NAVIGATION_BUTTON_* constants.
+     */
+    protected void setNavigationButton(int navigationButton) {
+        int iconResId = 0;
+        int contentDescriptionId = 0;
+
+        if (navigationButton == NAVIGATION_BUTTON_MENU && mDrawerLayout == null) {
+            mNavigationButton = NAVIGATION_BUTTON_NONE;
+        } else {
+            mNavigationButton = navigationButton;
+        }
+
+        if (mNavigationButton == NAVIGATION_BUTTON_MENU) {
+            initActionBarDrawerToggle();
+            // ActionBarDrawerToggle will take care of icon and content description, so just return.
+            return;
+        }
+
+        if (mActionBarDrawerToggle != null) {
+            mActionBarDrawerToggle.setDrawerIndicatorEnabled(false);
+            mDrawerLayout.addDrawerListener(null);
+        }
+
+        setNavigationOnClickListener(this);
+
+        switch (mNavigationButton) {
+            case NAVIGATION_BUTTON_NONE:
+                break;
+            case NAVIGATION_BUTTON_BACK:
+                // TODO(twellington): use ic_arrow_back_white_24dp and tint it.
+                iconResId = R.drawable.back_normal;
+                contentDescriptionId = R.string.accessibility_toolbar_btn_back;
+                break;
+            case NAVIGATION_BUTTON_SELECTION_BACK:
+                // TODO(twellington): use btn_close and tint it.
+                iconResId = R.drawable.btn_close_white;
+                contentDescriptionId = R.string.accessibility_cancel_selection;
+                break;
+            default:
+                assert false : "Incorrect navigationButton argument";
+        }
+
+        if (iconResId == 0) {
+            setNavigationIcon(null);
+        } else {
+            setNavigationIcon(iconResId);
+        }
+        setNavigationContentDescription(contentDescriptionId);
+    }
+
+    /**
+     * Set up ActionBarDrawerToggle, a.k.a. hamburger button.
+     */
+    private void initActionBarDrawerToggle() {
+        // Sadly, the only way to set correct toolbar button listener for ActionBarDrawerToggle
+        // is constructing, so we will need to construct every time we re-show this button.
+        mActionBarDrawerToggle = new ActionBarDrawerToggle((Activity) getContext(),
+                mDrawerLayout, this,
+                R.string.accessibility_drawer_toggle_btn_open,
+                R.string.accessibility_drawer_toggle_btn_close);
+        mDrawerLayout.addDrawerListener(mActionBarDrawerToggle);
+        mActionBarDrawerToggle.syncState();
+    }
+}
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index f814cec1..b73ba6e 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -201,6 +201,9 @@
       <message name="IDS_ADD" desc="Prompt for the user to add something, like a new address. [CHAR-LIMIT=20]">
         Add
       </message>
+      <message name="IDS_SHARE" desc="Content description for a button to share item(s). [CHAR-LIMIT=20]">
+        Share
+      </message>
 
       <!-- Main Preferences -->
       <message name="IDS_PREFERENCES" desc="Title for Chrome's Settings.">
@@ -2217,12 +2220,6 @@
       <message name="IDS_BOOKMARK_MISSING_URL" desc="Error message appearing when a user tries to create a bookmark without a url. [CHAR-LIMIT=32]">
         URL required
       </message>
-      <message name="IDS_ACCESSIBILITY_BOOKMARK_DRAWER_TOGGLE_BTN_OPEN" desc="Content description for the button to show the navigation drawer.">
-        Open navigation drawer
-      </message>
-      <message name="IDS_ACCESSIBILITY_BOOKMARK_DRAWER_TOGGLE_BTN_CLOSE" desc="Content description for the button to close the navigation drawer.">
-        Close navigation drawer
-      </message>
 
       <!-- Offline pages -->
       <message name="IDS_OFFLINE_PAGES_VIEWING_OFFLINE_PAGE" desc="Text explaining that the user is viewing an offline copy of a web page.">
@@ -2372,9 +2369,6 @@
       <message name="IDS_ACCESSIBILITY_OMNIBOX_BTN_REFINE" desc="Content description for the omnibox refine button.">
         Refine
       </message>
-      <message name="IDS_ACCESSIBILITY_BOOKMARK_CANCEL_SELECTION" desc="Content description for the cancel selection button that deselects the selected bookmarks.">
-        Cancel selection
-      </message>
       <message name="IDS_ACCESSIBILITY_BOOKMARK_MORE_INFO" desc="Content description for the button that shows option menu for a bookmark.">
         Options
       </message>
@@ -2387,6 +2381,15 @@
       <message name="IDS_ACCESSIBILITY_BOOKMARK_DETAIL_SAVE_BTN" desc="Content description for the save button that allows users to save the edited bookmark.">
         Save bookmark
       </message>
+      <message name="IDS_ACCESSIBILITY_CANCEL_SELECTION" desc="Content description for the cancel selection button that deselects the selected items in a selectable list view.">
+        Cancel selection
+      </message>
+      <message name="IDS_ACCESSIBILITY_DRAWER_TOGGLE_BTN_OPEN" desc="Content description for the button to show the navigation drawer.">
+        Open navigation drawer
+      </message>
+      <message name="IDS_ACCESSIBILITY_DRAWER_TOGGLE_BTN_CLOSE" desc="Content description for the button to close the navigation drawer.">
+        Close navigation drawer
+      </message>
 
       <message name="IDS_VIDEO_CALL_NOTIFICATION_TEXT_2" desc="Text to be shown as a notification when a WebRTC video call is in progress.">
         Accessing video input
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 9042411..523cd96 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -103,7 +103,6 @@
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java",
-  "java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemHighlightView.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemRow.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkLaunchLocation.java",
@@ -320,6 +319,7 @@
   "java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java",
   "java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java",
   "java/src/org/chromium/chrome/browser/download/ui/DownloadHistoryAdapter.java",
+  "java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java",
   "java/src/org/chromium/chrome/browser/download/ui/DownloadManagerUi.java",
   "java/src/org/chromium/chrome/browser/download/ui/DownloadManagerToolbar.java",
   "java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java",
@@ -1035,6 +1035,10 @@
   "java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java",
   "java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarTablet.java",
   "java/src/org/chromium/chrome/browser/widget/incognitotoggle/IncognitoToggleButtonTablet.java",
+  "java/src/org/chromium/chrome/browser/widget/selection/SelectableItemHighlightView.java",
+  "java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java",
+  "java/src/org/chromium/chrome/browser/widget/selection/SelectionDelegate.java",
+  "java/src/org/chromium/chrome/browser/widget/selection/SelectionToolbar.java",
   "java/src/org/chromium/chrome/browser/widget/newtab/NewTabButton.java",
 ]
 
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc
index d471c59..862e1ef 100644
--- a/chrome/app/mash/mash_runner.cc
+++ b/chrome/app/mash/mash_runner.cc
@@ -53,8 +53,9 @@
   ~DefaultService() override {}
 
   // shell::Service:
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<ServiceFactory>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<ServiceFactory>(this);
     return true;
   }
 
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 13bffe0..afe1798c 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -40,6 +40,7 @@
   "+mojo/converters",
   "+mojo/runner/child",
   "+services/shell/public/cpp",
+  "+services/ui/common", # TODO(sad): Should be removed: crbug.com/634377
   "+services/ui/public",
   "+policy",  # For generated headers and source
   "+ppapi/c",  # For various types.
diff --git a/chrome/browser/android/offline_pages/offline_page_utils.cc b/chrome/browser/android/offline_pages/offline_page_utils.cc
index 6320e52..aa787a8 100644
--- a/chrome/browser/android/offline_pages/offline_page_utils.cc
+++ b/chrome/browser/android/offline_pages/offline_page_utils.cc
@@ -73,15 +73,6 @@
   callback.Run(result_url);
 }
 
-void OnGetBestPageForOnlineURLDone(
-    const base::Callback<void(const GURL&)>& callback,
-    const OfflinePageItem* item) {
-  GURL result_url;
-  if (item)
-    result_url = item->GetOfflineURL();
-  callback.Run(result_url);
-}
-
 }  // namespace
 
 // static
@@ -94,23 +85,6 @@
 }
 
 // static
-void OfflinePageUtils::GetOfflineURLForOnlineURL(
-    content::BrowserContext* browser_context,
-    const GURL& online_url,
-    const base::Callback<void(const GURL&)>& callback) {
-  OfflinePageModel* offline_page_model =
-      OfflinePageModelFactory::GetForBrowserContext(browser_context);
-  if (!offline_page_model) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::Bind(&OnGetPageByOfflineURLDone, callback, nullptr));
-    return;
-  }
-
-  offline_page_model->GetBestPageForOnlineURL(
-      online_url, base::Bind(&OnGetBestPageForOnlineURLDone, callback));
-}
-
-// static
 GURL OfflinePageUtils::MaybeGetOnlineURLForOfflineURL(
     content::BrowserContext* browser_context,
     const GURL& offline_url) {
diff --git a/chrome/browser/android/offline_pages/offline_page_utils.h b/chrome/browser/android/offline_pages/offline_page_utils.h
index 8442472..11455ff2 100644
--- a/chrome/browser/android/offline_pages/offline_page_utils.h
+++ b/chrome/browser/android/offline_pages/offline_page_utils.h
@@ -24,12 +24,6 @@
   // Returns true if |url| might point to an offline page.
   static bool MightBeOfflineURL(const GURL& url);
 
-  // Gets an offline URL of an offline page with |online_url| if one exists.
-  static void GetOfflineURLForOnlineURL(
-      content::BrowserContext* browser_context,
-      const GURL& online_url,
-      const base::Callback<void(const GURL&)>& callback);
-
   // Gets an online URL of an offline page with |offline_url| if one exists.
   // Deprecated.  Use |GetOnlineURLForOfflineURL|.
   static GURL MaybeGetOnlineURLForOfflineURL(
diff --git a/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc b/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc
index c46dcea..64f3fe3 100644
--- a/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc
+++ b/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc
@@ -53,7 +53,6 @@
 
   void SetUp() override;
   void RunUntilIdle();
-  GURL GetOfflineURLForOnlineURL(GURL online_url);
 
   // Necessary callbacks for the offline page model.
   void OnSavePageDone(SavePageResult result, int64_t offlineId);
@@ -142,14 +141,6 @@
   url_ = url;
 }
 
-GURL OfflinePageUtilsTest::GetOfflineURLForOnlineURL(GURL online_url) {
-  OfflinePageUtils::GetOfflineURLForOnlineURL(
-      profile(), online_url,
-      base::Bind(&OfflinePageUtilsTest::OnGetURLDone, AsWeakPtr()));
-  RunUntilIdle();
-  return url_;
-}
-
 void OfflinePageUtilsTest::SetLastPathCreatedByArchiver(
     const base::FilePath& file_path) {}
 
@@ -226,17 +217,6 @@
   EXPECT_TRUE(OfflinePageUtils::MightBeOfflineURL(GURL("file:///test.mhtml")));
 }
 
-TEST_F(OfflinePageUtilsTest, GetOfflineURLForOnlineURL) {
-  EXPECT_EQ(offline_url_page_1(),
-            OfflinePageUtilsTest::GetOfflineURLForOnlineURL(kTestPage1Url));
-  EXPECT_EQ(offline_url_page_2(),
-            OfflinePageUtilsTest::GetOfflineURLForOnlineURL(kTestPage2Url));
-  EXPECT_EQ(GURL::EmptyGURL(),
-            OfflinePageUtilsTest::GetOfflineURLForOnlineURL(kTestPage3Url));
-  EXPECT_EQ(GURL::EmptyGURL(),
-            OfflinePageUtilsTest::GetOfflineURLForOnlineURL(kTestPage4Url));
-}
-
 TEST_F(OfflinePageUtilsTest, MaybeGetOnlineURLForOfflineURL) {
   EXPECT_EQ(kTestPage1Url, OfflinePageUtils::MaybeGetOnlineURLForOfflineURL(
                                profile(), offline_url_page_1()));
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 8a8a08e..43b30a4 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -244,6 +244,12 @@
 #include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views_linux.h"
 #endif
 
+#if defined(USE_AURA)
+#include "services/shell/runner/common/client_util.h"
+#include "services/ui/common/gpu_service.h"
+#include "ui/views/mus/window_manager_connection.h"
+#endif
+
 #if defined(USE_ASH)
 #include "chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h"
 #endif
@@ -741,8 +747,7 @@
 }  // namespace
 
 ChromeContentBrowserClient::ChromeContentBrowserClient()
-    :
-      weak_factory_(this) {
+    : weak_factory_(this) {
 #if defined(ENABLE_PLUGINS)
   for (size_t i = 0; i < arraysize(kPredefinedAllowedDevChannelOrigins); ++i)
     allowed_dev_channel_origins_.insert(kPredefinedAllowedDevChannelOrigins[i]);
@@ -2035,15 +2040,16 @@
     bool overridable,
     bool strict_enforcement,
     bool expired_previous_decision,
-    const base::Callback<void(bool)>& callback,
-    content::CertificateRequestResultType* result) {
+    const base::Callback<void(content::CertificateRequestResultType)>&
+        callback) {
   DCHECK(web_contents);
   if (resource_type != content::RESOURCE_TYPE_MAIN_FRAME) {
     // A sub-resource has a certificate error.  The user doesn't really
     // have a context for making the right decision, so block the
     // request hard, without an info bar to allow showing the insecure
     // content.
-    *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
+    if (!callback.is_null())
+      callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
     return;
   }
 
@@ -2052,7 +2058,9 @@
       prerender::PrerenderContents::FromWebContents(web_contents);
   if (prerender_contents) {
     prerender_contents->Destroy(prerender::FINAL_STATUS_SSL_ERROR);
-    *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
+    if (!callback.is_null()) {
+      callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
+    }
     return;
   }
 
@@ -2510,6 +2518,15 @@
   return NULL;
 }
 
+gpu::GpuChannelEstablishFactory*
+ChromeContentBrowserClient::GetGpuChannelEstablishFactory() {
+#if defined(USE_AURA)
+  if (views::WindowManagerConnection::Exists())
+    return views::WindowManagerConnection::Get()->gpu_service();
+#endif
+  return nullptr;
+}
+
 bool ChromeContentBrowserClient::AllowPepperSocketAPI(
     content::BrowserContext* browser_context,
     const GURL& url,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index ca247d88..fc5b98eb 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -177,8 +177,8 @@
       bool overridable,
       bool strict_enforcement,
       bool expired_previous_decision,
-      const base::Callback<void(bool)>& callback,
-      content::CertificateRequestResultType* request) override;
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback) override;
   void SelectClientCertificate(
       content::WebContents* web_contents,
       net::SSLCertRequestInfo* cert_request_info,
@@ -222,6 +222,7 @@
   void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) override;
   content::BrowserPpapiHost* GetExternalBrowserPpapiHost(
       int plugin_process_id) override;
+  gpu::GpuChannelEstablishFactory* GetGpuChannelEstablishFactory() override;
   bool AllowPepperSocketAPI(
       content::BrowserContext* browser_context,
       const GURL& url,
diff --git a/chrome/browser/chromeos/chrome_interface_factory.cc b/chrome/browser/chromeos/chrome_interface_factory.cc
index 3e29eec..344d404 100644
--- a/chrome/browser/chromeos/chrome_interface_factory.cc
+++ b/chrome/browser/chromeos/chrome_interface_factory.cc
@@ -22,6 +22,7 @@
 #include "mash/public/interfaces/launchable.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/shell/public/cpp/connection.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "ui/app_list/presenter/app_list_presenter.mojom.h"
 #include "ui/keyboard/keyboard.mojom.h"
 
@@ -80,9 +81,9 @@
 
   template <typename Interface>
   static void AddFactory(
-      shell::Connection* connection,
+      shell::InterfaceRegistry* registry,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
-    connection->AddInterface<Interface>(
+    registry->AddInterface<Interface>(
         base::Bind(&FactoryImpl::CallMainThreadFactory<Interface>),
         task_runner);
   }
@@ -148,16 +149,17 @@
 
 ChromeInterfaceFactory::~ChromeInterfaceFactory() {}
 
-bool ChromeInterfaceFactory::OnConnect(shell::Connection* connection,
+bool ChromeInterfaceFactory::OnConnect(const shell::Identity& remote_identity,
+                                       shell::InterfaceRegistry* registry,
                                        shell::Connector* connector) {
-  FactoryImpl::AddFactory<keyboard::mojom::Keyboard>(
-      connection, main_thread_task_runner_);
-  FactoryImpl::AddFactory<mash::mojom::Launchable>(
-      connection, main_thread_task_runner_);
+  FactoryImpl::AddFactory<keyboard::mojom::Keyboard>(registry,
+                                                     main_thread_task_runner_);
+  FactoryImpl::AddFactory<mash::mojom::Launchable>(registry,
+                                                   main_thread_task_runner_);
   FactoryImpl::AddFactory<ash::sysui::mojom::WallpaperManager>(
-      connection, main_thread_task_runner_);
+      registry, main_thread_task_runner_);
   FactoryImpl::AddFactory<app_list::mojom::AppListPresenter>(
-      connection, main_thread_task_runner_);
+      registry, main_thread_task_runner_);
   return true;
 }
 
diff --git a/chrome/browser/chromeos/chrome_interface_factory.h b/chrome/browser/chromeos/chrome_interface_factory.h
index 3538bbc0..cd3af39d 100644
--- a/chrome/browser/chromeos/chrome_interface_factory.h
+++ b/chrome/browser/chromeos/chrome_interface_factory.h
@@ -20,7 +20,8 @@
 
  private:
   // content::ConnectionFilter:
-  bool OnConnect(shell::Connection* connection,
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry,
                  shell::Connector* connector) override;
 
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc
index 01991a06..8299aeb 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -740,13 +740,17 @@
   }
   DCHECK(mtp_storage_info);
 
-  // Mtp write is enabled only when the device is writable and supports generic
-  // hierarchical file system.
+  // Mtp write is enabled only when the device is writable, supports generic
+  // hierarchical file system, and writing to external storage devices is not
+  // prohibited by the preference.
   const bool read_only =
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           chromeos::switches::kDisableMtpWriteSupport) ||
       mtp_storage_info->access_capability() != kAccessCapabilityReadWrite ||
-      mtp_storage_info->filesystem_type() != kFilesystemTypeGenericHierarchical;
+      mtp_storage_info->filesystem_type() !=
+          kFilesystemTypeGenericHierarchical ||
+      GetExternalStorageAccessMode(profile_) ==
+          chromeos::MOUNT_ACCESS_MODE_READ_ONLY;
 
   content::BrowserThread::PostTask(
       content::BrowserThread::IO, FROM_HERE,
diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
index 2d501d0..1d5965b 100644
--- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc
@@ -1448,10 +1448,6 @@
       CONTENT_SETTING_ALLOW,
       host_content_settings_map->GetContentSetting(
           http_host, http_host, CONTENT_SETTINGS_TYPE_COOKIES, std::string()));
-  EXPECT_EQ(CONTENT_SETTING_ALLOW,
-            host_content_settings_map->GetContentSetting(
-                http_host_narrower, http_host_narrower,
-                CONTENT_SETTINGS_TYPE_COOKIES, std::string()));
   host_content_settings_map->SetContentSettingCustomScope(
       ContentSettingsPattern::FromURL(https_host),
       ContentSettingsPattern::Wildcard(), CONTENT_SETTINGS_TYPE_COOKIES,
@@ -1463,6 +1459,10 @@
   // Settings also apply to subdomains.
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
             host_content_settings_map->GetContentSetting(
+                http_host_narrower, http_host_narrower,
+                CONTENT_SETTINGS_TYPE_COOKIES, std::string()));
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            host_content_settings_map->GetContentSetting(
                 https_host_narrower, https_host_narrower,
                 CONTENT_SETTINGS_TYPE_COOKIES, std::string()));
 
@@ -1503,19 +1503,19 @@
               "https://example.com:443");
   EXPECT_TRUE(settings[1].primary_pattern.ToString() == "*");
 
-  // Cookie settings didn't get migrated.
   EXPECT_EQ(
       CONTENT_SETTING_ALLOW,
       host_content_settings_map->GetContentSetting(
           http_host, http_host, CONTENT_SETTINGS_TYPE_COOKIES, std::string()));
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
             host_content_settings_map->GetContentSetting(
-                http_host_narrower, http_host_narrower,
-                CONTENT_SETTINGS_TYPE_COOKIES, std::string()));
-  EXPECT_EQ(CONTENT_SETTING_ALLOW,
-            host_content_settings_map->GetContentSetting(
                 https_host, https_host, CONTENT_SETTINGS_TYPE_COOKIES,
                 std::string()));
+  // Settings still apply to subdomains. Cookie settings didn't get migrated.
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            host_content_settings_map->GetContentSetting(
+                http_host_narrower, http_host_narrower,
+                CONTENT_SETTINGS_TYPE_COOKIES, std::string()));
   EXPECT_EQ(CONTENT_SETTING_ALLOW,
             host_content_settings_map->GetContentSetting(
                 https_host_narrower, https_host_narrower,
diff --git a/chrome/browser/metrics/metrics_service_browsertest.cc b/chrome/browser/metrics/metrics_service_browsertest.cc
index 2ba8c021..740f6ba7 100644
--- a/chrome/browser/metrics/metrics_service_browsertest.cc
+++ b/chrome/browser/metrics/metrics_service_browsertest.cc
@@ -77,7 +77,8 @@
 // Flaky on Linux. See http://crbug.com/131094
 // Child crashes fail the process on ASan (see crbug.com/411251,
 // crbug.com/368525).
-#if defined(OS_LINUX) || defined(ADDRESS_SANITIZER)
+// Flaky failing DCHECK on Windows, see crbug.com/635770
+#if defined(OS_LINUX) || defined(ADDRESS_SANITIZER) || defined(OS_WIN)
 #define MAYBE_CrashRenderers DISABLED_CrashRenderers
 #else
 #define MAYBE_CrashRenderers CrashRenderers
@@ -112,4 +113,3 @@
   // is set to true, but this preference isn't set until the browser
   // exits... it's not clear to me how to test that.
 }
-
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
index 588dc8d0..b086529 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/common/channel_info.h"
@@ -167,13 +168,9 @@
 TEST_F(ChromePasswordManagerClientTest,
        IsAutomaticPasswordSavingEnabledWhenFlagIsSetTest) {
   // Add the enable-automatic-password-saving feature.
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  std::vector<const base::Feature*> enabled_features;
-  std::vector<const base::Feature*> disabled_features;
-  enabled_features.push_back(
-      &password_manager::features::kEnableAutomaticPasswordSaving);
-  password_manager::SetFeatures(enabled_features, disabled_features,
-                                std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      password_manager::features::kEnableAutomaticPasswordSaving);
 
   if (chrome::GetChannel() == version_info::Channel::UNKNOWN)
     EXPECT_TRUE(GetClient()->IsAutomaticPasswordSavingEnabled());
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index dca4eb54..74d1061f 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -464,6 +464,18 @@
                            true);
 }
 
+// This test ensures that PDF can be loaded from local file
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, EnsurePDFFromLocalFileLoads) {
+  base::FilePath test_data_dir;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
+  test_data_dir = test_data_dir.Append(FILE_PATH_LITERAL("pdf"));
+  base::FilePath test_data_file = test_data_dir.AppendASCII("test.pdf");
+  ASSERT_TRUE(PathExists(test_data_file));
+  GURL test_pdf_url("file://" + test_data_file.MaybeAsASCII());
+  content::WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url);
+  ASSERT_TRUE(guest_contents);
+}
+
 // This test ensures that link permissions are enforced properly in PDFs.
 IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkPermissions) {
   GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test.pdf"));
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html
index 4de7620..ffc5a62 100644
--- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html
+++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.html
@@ -2,11 +2,25 @@
                              what i18n to use for keypad, ie, does 1 ABC make
                              sense in every scenario? -->
 
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/polymer.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/paper-styles.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
+
+<iron-iconset-svg name="pin-keyboard" size="24">
+  <svg>
+    <defs>
+      <!--
+      Inlined from Polymer's iron-icons to avoid importing everything.
+      See http://goo.gl/Y1OdAq for instructions on adding additional icons.
+      -->
+      <g id="forward"><path d="M12 8V4l8 8-8 8v-4H4V8z"></path></g>
+  </defs>
+</svg>
+</iron-iconset-svg>
 
 <dom-module id="pin-keyboard">
   <template>
@@ -140,7 +154,7 @@
 
     <div id="root">
       <div id="container-constrained-width">
-        <div class="row horizontal-center">
+        <div class="row">
           <input id="pin-input" type="[[getInputType_(enablePassword)]]"
                  class$="[[getInputClass_(value)]]
                          [[getSubmitHiddenClass_(enableSubmitButton)]]"
@@ -151,7 +165,7 @@
                                 [[getSubmitHiddenClass_(enableSubmitButton)]]"
                         on-tap="firePinSubmitEvent_">
             <div class$="icon-container [[getSubmitClass_(value)]]">
-                <iron-icon class="icon" icon="icons:forward"><iron-icon>
+                <iron-icon class="icon" icon="pin-keyboard:forward"><iron-icon>
             </div>
           </paper-button>
         </div>
@@ -200,7 +214,7 @@
           </paper-button>
           <paper-button class="digit-button clear-button" on-tap="onPinClear_">
             <div class="icon-container">
-              <iron-icon class="icon" icon="icons:clear"><iron-icon>
+              <iron-icon class="icon" icon="cr:clear"><iron-icon>
             </div>
             <inner-text class="icon-subheading">
               $i18n{pinKeyboardClear}
diff --git a/chrome/browser/resources/feedback/manifest.json b/chrome/browser/resources/feedback/manifest.json
index 5371e97..bfc3f60 100644
--- a/chrome/browser/resources/feedback/manifest.json
+++ b/chrome/browser/resources/feedback/manifest.json
@@ -18,7 +18,7 @@
     "background": {
       "scripts": ["js/event_handler.js"]
     },
-    "content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem: chrome://resources; style-src 'unsafe-inline' blob: filesystem: data: *; img-src * blob: filesystem: data:; media-src 'self' blob: filesystem:"
+    "content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem: chrome://resources; style-src 'unsafe-inline' blob: file: filesystem: data: *; img-src * blob: file: filesystem: data:; media-src 'self' blob: filesystem:"
   },
   "display_in_launcher": false,
   "display_in_new_tab_page": false
diff --git a/chrome/browser/resources/md_history/browser_service.js b/chrome/browser/resources/md_history/browser_service.js
index 952a506..9052df5 100644
--- a/chrome/browser/resources/md_history/browser_service.js
+++ b/chrome/browser/resources/md_history/browser_service.js
@@ -60,7 +60,7 @@
      * @param {string} sessionTag
      * @param {number} windowId
      * @param {number} tabId
-     * @param {Event} e
+     * @param {MouseEvent} e
      */
     openForeignSessionTab: function(sessionTag, windowId, tabId, e) {
       chrome.send('openForeignSession', [
diff --git a/chrome/browser/resources/md_history/constants.js b/chrome/browser/resources/md_history/constants.js
index 99ff543..467f99b 100644
--- a/chrome/browser/resources/md_history/constants.js
+++ b/chrome/browser/resources/md_history/constants.js
@@ -47,7 +47,7 @@
 var QueryResult;
 
 /** @constructor
- *  @extends {CustomEvent} */
-var TapEvent = function() {
+ *  @extends {MouseEvent} */
+var DomRepeatClickEvent = function() {
   this.model = null;
 };
diff --git a/chrome/browser/resources/md_history/synced_device_card.html b/chrome/browser/resources/md_history/synced_device_card.html
index e6d57d7..77549703 100644
--- a/chrome/browser/resources/md_history/synced_device_card.html
+++ b/chrome/browser/resources/md_history/synced_device_card.html
@@ -94,7 +94,7 @@
             <div id="item-container">
               <div id="icon" class="website-icon"></div>
               <a href="[[tab.url]]" class="website-title" title="[[tab.title]]"
-                  on-tap="openTab_">
+                  on-click="openTab_">
                 <history-searched-label title="[[tab.title]]"
                     search-term="[[searchTerm]]"></history-searched-label>
               </a>
diff --git a/chrome/browser/resources/md_history/synced_device_card.js b/chrome/browser/resources/md_history/synced_device_card.js
index 71760a79..8090df8a 100644
--- a/chrome/browser/resources/md_history/synced_device_card.js
+++ b/chrome/browser/resources/md_history/synced_device_card.js
@@ -40,14 +40,15 @@
   },
 
   /**
-   * @param {TapEvent} e
+   * Open a single synced tab. Listens to 'click' rather than 'tap'
+   * to determine what modifier keys were pressed.
+   * @param {DomRepeatClickEvent} e
    * @private
    */
   openTab_: function(e) {
     var tab = /** @type {ForeignSessionTab} */(e.model.tab);
-    var srcEvent = /** @type {Event} */(e.detail.sourceEvent);
     md_history.BrowserService.getInstance().openForeignSessionTab(
-        this.sessionTag, tab.windowId, tab.sessionId, srcEvent);
+        this.sessionTag, tab.windowId, tab.sessionId, e);
     e.preventDefault();
   },
 
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
index 3b85a19..dc16b716 100644
--- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
+++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.css
@@ -199,8 +199,6 @@
 
 .sink-name {
   min-width: 10%;
-  overflow: hidden;
-  text-overflow: ellipsis;
 }
 
 #sink-search {
@@ -249,11 +247,11 @@
 
 .sink-text {
   -webkit-padding-end: var(--dialog-padding-end);
-  display: inline-flex;
-  flex-direction: row;
   flex-flow: row nowrap;
   line-height: normal;
+  overflow: hidden;
+  text-overflow: ellipsis;
   white-space: nowrap;
-  width: 250px;
+  width: 275px;
 }
 
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
index 429757e..de948ff6a 100644
--- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
+++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.html
@@ -89,8 +89,8 @@
             sink="[[getSinkForRoute_(currentRoute_)]]"
             is-any-sink-currently-launching=
                 "[[computeIsLaunching_(currentLaunchingSinkId_)]]"
-            on-close-route="onCloseRoute_"
-            on-replace-route-click="onReplaceRouteClick_">
+            on-change-route-source-click="onChangeRouteSourceClick_"
+            on-close-route="onCloseRoute_">
         </route-details>
       </template>
       <div id="sink-list-view"
diff --git a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
index 08a64afc..ec7e183e 100644
--- a/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
+++ b/chrome/browser/resources/media_router/elements/media_router_container/media_router_container.js
@@ -192,17 +192,6 @@
     },
 
     /**
-     * Whether the sink with a pending route creation, whose ID is given by
-     * |currentLaunchingSinkId_|, is waiting for the current route to it to be
-     * closed so a new one can be started.
-     * @private {boolean}
-     */
-    launchingSinkAwaitingRouteClose_: {
-      type: Boolean,
-      value: false,
-    },
-
-    /**
      * Whether the user's mouse is positioned over the dialog.
      * @private {boolean|undefined}
      */
@@ -1589,6 +1578,26 @@
   },
 
   /**
+   * Handles a change-route-source-click event. Sets the currently launching
+   * sink to be the current route's sink and shows the sink list.
+   *
+   * @param {!Event} event The event object.
+   * Parameters in |event|.detail:
+   *   route - route to modify.
+   *   selectedCastMode - cast mode to use for the new source.
+   * @private
+   */
+  onChangeRouteSourceClick_: function(event) {
+    /** @type {{route: !media_router.Route, selectedCastMode: number}} */
+    var detail = event.detail;
+    this.currentLaunchingSinkId_ = detail.route.sinkId;
+    var sink = this.sinkMap_[detail.route.sinkId];
+    this.showSinkList_();
+    this.maybeReportUserFirstAction(
+        media_router.MediaRouterUserAction.REPLACE_LOCAL_ROUTE);
+  },
+
+  /**
    * Handles a close-route event. Shows the sink list and starts a timer to
    * close the dialog if there is no click within three seconds.
    *
@@ -1744,28 +1753,6 @@
   },
 
   /**
-   * Handles a replace-route-click event. Closes the currently displayed local
-   * route and shows the sink list. When the current route has been successfully
-   * removed from the route map, the container will launch a new route for the
-   * same sink.
-   *
-   * @param {!Event} event The event object.
-   * Parameters in |event|.detail:
-   *   route - route to close.
-   * @private
-   */
-  onReplaceRouteClick_: function(event) {
-    /** @type {{route: !media_router.Route}} */
-    var detail = event.detail;
-    this.currentLaunchingSinkId_ = detail.route.sinkId;
-    this.launchingSinkAwaitingRouteClose_ = true;
-    this.fire('close-route', detail);
-    this.showSinkList_();
-    this.maybeReportUserFirstAction(
-        media_router.MediaRouterUserAction.REPLACE_LOCAL_ROUTE);
-  },
-
-  /**
    * Called when a sink is clicked.
    *
    * @param {!Event} event The event object.
@@ -1976,14 +1963,6 @@
 
     this.sinkToRouteMap_ = tempSinkToRouteMap;
     this.rebuildSinksToShow_();
-
-    // A sink was waiting for its route to be closed and removed from the route
-    // map so a new route to it can be started.
-    if (this.launchingSinkAwaitingRouteClose_ &&
-        !(this.currentLaunchingSinkId_ in this.sinkToRouteMap_) &&
-        this.currentLaunchingSinkId_ in this.sinkMap_) {
-      this.showOrCreateRoute_(this.sinkMap_[this.currentLaunchingSinkId_]);
-    }
   },
 
   /**
@@ -1993,7 +1972,7 @@
    * name.
    */
   rebuildSinksToShow_: function() {
-    var sinksToShow = this.allSinks.filter(function(sink) {
+    var updatedSinkList = this.allSinks.filter(function(sink) {
       return !sink.isPseudoSink;
     }, this);
     if (this.pseudoSinkSearchState_) {
@@ -2004,13 +1983,13 @@
       // list but |currentLaunchingSinkId_| is non-empty (thereby preventing any
       // other sink from launching).
       if (pendingPseudoSink.id == this.currentLaunchingSinkId_) {
-        sinksToShow.unshift(pendingPseudoSink);
+        updatedSinkList.unshift(pendingPseudoSink);
       }
     }
     if (this.userHasSelectedCastMode_) {
       // If user explicitly selected a cast mode, then we show only sinks that
       // are compatible with current cast mode or sinks that are active.
-      sinksToShow = sinksToShow.filter(function(element) {
+      updatedSinkList = updatedSinkList.filter(function(element) {
         return (element.castModes & this.shownCastModeValue_) ||
                this.sinkToRouteMap_[element.id];
       }, this);
@@ -2023,7 +2002,27 @@
       this.setShownCastMode_(this.computeCastMode_());
     }
 
-    this.sinksToShow_ = sinksToShow;
+    // When there's an updated list of sinks, append any new sinks to the end
+    // of the existing list. This prevents sinks randomly jumping around the
+    // dialog, which can surprise users / lead to inadvertently casting to the
+    // wrong sink.
+    if (this.sinksToShow_) {
+      for (var i = this.sinksToShow_.length - 1; i >= 0; i--) {
+        var index = updatedSinkList.findIndex(function(updatedSink) {
+            return this.sinksToShow_[i].id == updatedSink.id; }.bind(this));
+        if (index < 0) {
+          // Remove any sinks that are no longer discovered.
+          this.sinksToShow_.splice(i, 1);
+        } else {
+          // If the sink exists, remove it from |updatedSinkList| as it is
+          // already in |sinksToShow_|.
+          updatedSinkList.splice(index, 1);
+        }
+      }
+
+      updatedSinkList = this.sinksToShow_.concat(updatedSinkList);
+    }
+    this.sinksToShow_ = updatedSinkList;
   },
 
   /**
@@ -2203,9 +2202,7 @@
       this.fire('navigate-sink-list-to-details');
       this.maybeReportUserFirstAction(
           media_router.MediaRouterUserAction.STATUS_REMOTE);
-    } else if ((this.launchingSinkAwaitingRouteClose_ &&
-                this.currentLaunchingSinkId_ == sink.id) ||
-               this.currentLaunchingSinkId_ == '') {
+    } else if (this.currentLaunchingSinkId_ == '') {
       // Allow one launch at a time.
       var selectedCastModeValue =
           this.shownCastModeValue_ == media_router.CastModeType.AUTO ?
@@ -2232,11 +2229,7 @@
             window.performance.now() - this.populatedSinkListSeenTimeMs_;
         this.fire('report-sink-click-time', {timeMs: timeToSelectSink});
       }
-      if (!this.launchingSinkAwaitingRouteClose_) {
-        this.currentLaunchingSinkId_ = sink.id;
-      } else {
-        this.launchingSinkAwaitingRouteClose_ = false;
-      }
+      this.currentLaunchingSinkId_ = sink.id;
       if (sink.isPseudoSink) {
         this.rebuildSinksToShow_();
       }
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.html b/chrome/browser/resources/media_router/elements/route_details/route_details.html
index 703f464c..61043b44 100644
--- a/chrome/browser/resources/media_router/elements/route_details/route_details.html
+++ b/chrome/browser/resources/media_router/elements/route_details/route_details.html
@@ -14,7 +14,7 @@
     <div id="route-action-buttons" class="layout">
       <paper-button flat class="route-button button"
           id="start-casting-to-route-button"
-          hidden$="[[computeCastButtonHidden_(route, replaceRouteAvailable_)]]"
+          hidden$="[[computeCastButtonHidden_(route, changeRouteSourceAvailable_)]]"
           on-tap="startCastingToRoute_">
         <span>[[i18n('startCastingButtonText')]]</span>
       </paper-button>
diff --git a/chrome/browser/resources/media_router/elements/route_details/route_details.js b/chrome/browser/resources/media_router/elements/route_details/route_details.js
index ed64617..ae7ebcca 100644
--- a/chrome/browser/resources/media_router/elements/route_details/route_details.js
+++ b/chrome/browser/resources/media_router/elements/route_details/route_details.js
@@ -17,6 +17,17 @@
     },
 
     /**
+     * Whether the external container will accept change-route-source-click
+     * events.
+     * @private {boolean}
+     */
+    changeRouteSourceAvailable_: {
+      type: Boolean,
+      computed: 'computeChangeRouteSourceAvailable_(route, sink,' +
+                    'isAnySinkCurrentlyLaunching, shownCastModeValue)',
+    },
+
+    /**
      * Whether a sink is currently launching in the container.
      * @type {boolean}
      */
@@ -26,16 +37,6 @@
     },
 
     /**
-     * Whether the external container will accept replace-route-click events.
-     * @private {boolean}
-     */
-    replaceRouteAvailable_: {
-      type: Boolean,
-      computed: 'computeReplaceRouteAvailable_(route, sink,' +
-                    'isAnySinkCurrentlyLaunching, shownCastModeValue)',
-    },
-
-    /**
      * The route to show.
      * @type {?media_router.Route|undefined}
      */
@@ -91,12 +92,12 @@
 
   /**
    * @param {?media_router.Route|undefined} route
-   * @param {boolean} replaceRouteAvailable
+   * @param {boolean} changeRouteSourceAvailable
    * @return {boolean} Whether to show the button that allows casting to the
    *     current route or the current route's sink.
    */
-  computeCastButtonHidden_: function(route, replaceRouteAvailable) {
-    return !((route && route.canJoin) || replaceRouteAvailable);
+  computeCastButtonHidden_: function(route, changeRouteSourceAvailable) {
+    return !((route && route.canJoin) || changeRouteSourceAvailable);
   },
 
   /**
@@ -107,13 +108,14 @@
    *     now.
    * @param {number} shownCastModeValue Currently selected cast mode value or
    *     AUTO if no value has been explicitly selected.
-   * @return {boolean} Whether the replace route function should be available
-   *     when displaying |currentRoute| in the route details view. Replace route
-   *     should not be available when the source that would be cast from when
-   *     creating a new route would be the same as the route's current source.
+   * @return {boolean} Whether the change route source function should be
+   *     available when displaying |currentRoute| in the route details view.
+   *     Changing the route source should not be available when the currently
+   *     selected source that would be cast is the same as the route's current
+   *     source.
    * @private
    */
-  computeReplaceRouteAvailable_: function(
+  computeChangeRouteSourceAvailable_: function(
       route, sink, isAnySinkCurrentlyLaunching, shownCastModeValue) {
     if (isAnySinkCurrentlyLaunching || !route || !sink) {
       return false;
@@ -121,19 +123,43 @@
     if (!route.currentCastMode) {
       return true;
     }
-    var selectedCastMode = shownCastModeValue;
-    if (selectedCastMode == media_router.CastModeType.AUTO) {
-      selectedCastMode = sink.castModes & -sink.castModes;
-    }
-    return ((selectedCastMode & sink.castModes) != 0) &&
+    var selectedCastMode =
+        this.computeSelectedCastMode_(shownCastModeValue, sink);
+    return (selectedCastMode != 0) &&
         (selectedCastMode != route.currentCastMode);
   },
 
   /**
+   * @param {number} castMode User selected cast mode or AUTO.
+   * @param {?media_router.Sink} sink Sink to which we will cast.
+   * @return {number} The selected cast mode when |castMode| is selected in the
+   *     dialog and casting to |sink|.  Returning 0 means there is no cast mode
+   *     available to |sink| and therefore the start-casting-to-route button
+   *     will not be shown.
+   */
+  computeSelectedCastMode_: function(castMode, sink) {
+    // |sink| can be null when there is a local route, which is shown in the
+    // dialog, but the sink to which it is connected isn't in the current set of
+    // sinks known to the dialog.  This can happen, for example, with DIAL
+    // devices.  A route is created to a DIAL device, but opening the dialog on
+    // a tab that only supports mirroring will not show the DIAL device.  The
+    // route will be shown in route details if it is the only local route, so
+    // you arrive at this function with a null |sink|.
+    if (!sink) {
+      return 0;
+    }
+    if (castMode == media_router.CastModeType.AUTO) {
+      return sink.castModes & -sink.castModes;
+    }
+    return castMode & sink.castModes;
+  },
+
+  /**
    * Fires a join-route-click event if the current route is joinable, otherwise
-   * it fires a replace-route-click event, which stops the current route and
-   * immediately launches a new route to the same sink. This is called when the
-   * button to start casting to the current route is clicked.
+   * it fires a change-route-source-click event, which changes the source of the
+   * current route. This may cause the current route to be closed and a new
+   * route to be started. This is called when the button to start casting to the
+   * current route is clicked.
    *
    * @private
    */
@@ -141,7 +167,11 @@
     if (this.route.canJoin) {
       this.fire('join-route-click', {route: this.route});
     } else {
-      this.fire('replace-route-click', {route: this.route});
+      this.fire('change-route-source-click', {
+        route: this.route,
+        selectedCastMode:
+            this.computeSelectedCastMode_(this.shownCastModeValue, this.sink)
+      });
     }
   },
 
diff --git a/chrome/browser/resources/media_router/media_router.js b/chrome/browser/resources/media_router/media_router.js
index b0110d0c..c6e0f32e 100644
--- a/chrome/browser/resources/media_router/media_router.js
+++ b/chrome/browser/resources/media_router/media_router.js
@@ -34,6 +34,8 @@
                                onAcknowledgeFirstRunFlow);
     container.addEventListener('back-click', onNavigateToSinkList);
     container.addEventListener('cast-mode-selected', onCastModeSelected);
+    container.addEventListener('change-route-source-click',
+                               onChangeRouteSourceClick);
     container.addEventListener('close-dialog', onCloseDialog);
     container.addEventListener('close-route', onCloseRoute);
     container.addEventListener('create-route', onCreateRoute);
@@ -96,6 +98,22 @@
   }
 
   /**
+   * Reports the route for which the users wants to replace the source and the
+   * cast mode that should be used for the new source.
+   *
+   * @param {!Event} event The event object.
+   * Parameters in |event|.detail:
+   *   route - route to modify.
+   *   selectedCastMode - type of cast mode selected by the user.
+   */
+  function onChangeRouteSourceClick(event) {
+    /** @type {{route: !media_router.Route, selectedCastMode: number}} */
+    var detail = event.detail;
+    media_router.browserApi.changeRouteSource(
+        detail.route, detail.selectedCastMode);
+  }
+
+  /**
    * Updates the preference that the user has seen the first run flow.
    * Called when the user clicks on the acknowledgement button on the first run
    * flow.
diff --git a/chrome/browser/resources/media_router/media_router_ui_interface.js b/chrome/browser/resources/media_router/media_router_ui_interface.js
index abc8cbb..6232c37 100644
--- a/chrome/browser/resources/media_router/media_router_ui_interface.js
+++ b/chrome/browser/resources/media_router/media_router_ui_interface.js
@@ -203,6 +203,19 @@
   }
 
   /**
+   * Modifies |route| by changing its source to the one identified by
+   * |selectedCastMode|.
+   *
+   * @param {!media_router.Route} route The route being modified.
+   * @param {number} selectedCastMode The value of the cast mode the user
+   *   selected.
+   */
+  function changeRouteSource(route, selectedCastMode) {
+    chrome.send('requestRoute',
+                [{sinkId: route.sinkId, selectedCastMode: selectedCastMode}]);
+  }
+
+  /**
    * Closes the dialog.
    *
    * @param {boolean} pressEscToClose Whether the user pressed ESC to close the
@@ -387,6 +400,7 @@
   return {
     acknowledgeFirstRunFlow: acknowledgeFirstRunFlow,
     actOnIssue: actOnIssue,
+    changeRouteSource: changeRouteSource,
     closeDialog: closeDialog,
     closeRoute: closeRoute,
     joinRoute: joinRoute,
diff --git a/chrome/browser/resources/pdf/manifest.json b/chrome/browser/resources/pdf/manifest.json
index b153845..4e6189d 100644
--- a/chrome/browser/resources/pdf/manifest.json
+++ b/chrome/browser/resources/pdf/manifest.json
@@ -14,7 +14,7 @@
   "mime_types": [
     "application/pdf"
   ],
-  "content_security_policy": "script-src 'self' blob: filesystem: chrome://resources; object-src * blob: filesystem: data:; plugin-types application/x-google-chrome-pdf",
+  "content_security_policy": "script-src 'self' blob: filesystem: chrome://resources; object-src * blob: file: filesystem: data:; plugin-types application/x-google-chrome-pdf",
   "mime_types_handler": "index.html",
   "web_accessible_resources": [
     "*.js",
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.cc b/chrome/browser/ssl/bad_clock_blocking_page.cc
index 816f3cc..5666afcb 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.cc
+++ b/chrome/browser/ssl/bad_clock_blocking_page.cc
@@ -55,7 +55,7 @@
     const base::Time& time_triggered,
     ssl_errors::ClockState clock_state,
     std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-    const base::Callback<void(bool)>& callback)
+    const base::Callback<void(content::CertificateRequestResultType)>& callback)
     : SecurityInterstitialPage(web_contents, request_url),
       callback_(callback),
       ssl_info_(ssl_info),
@@ -160,5 +160,6 @@
   if (callback_.is_null())
     return;
 
-  base::ResetAndReturn(&callback_).Run(false);
+  base::ResetAndReturn(&callback_)
+      .Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
 }
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.h b/chrome/browser/ssl/bad_clock_blocking_page.h
index 48366d97..2c32180 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.h
+++ b/chrome/browser/ssl/bad_clock_blocking_page.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/interstitials/security_interstitial_page.h"
 #include "chrome/browser/ssl/ssl_cert_reporter.h"
 #include "components/ssl_errors/error_classification.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "net/ssl/ssl_info.h"
 
 class CertReportHelper;
@@ -42,7 +43,8 @@
                        const base::Time& time_triggered,
                        ssl_errors::ClockState clock_state,
                        std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-                       const base::Callback<void(bool)>& callback);
+                       const base::Callback<void(
+                           content::CertificateRequestResultType)>& callback);
 
   ~BadClockBlockingPage() override;
 
@@ -68,7 +70,7 @@
  private:
   void NotifyDenyCertificate();
 
-  base::Callback<void(bool)> callback_;
+  base::Callback<void(content::CertificateRequestResultType)> callback_;
   const net::SSLInfo ssl_info_;
   const base::Time time_triggered_;
   std::unique_ptr<ChromeControllerClient> controller_;
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.cc b/chrome/browser/ssl/captive_portal_blocking_page.cc
index 3b5483a0..89d46df 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page.cc
+++ b/chrome/browser/ssl/captive_portal_blocking_page.cc
@@ -55,7 +55,7 @@
     const GURL& login_url,
     std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
     const net::SSLInfo& ssl_info,
-    const base::Callback<void(bool)>& callback)
+    const base::Callback<void(content::CertificateRequestResultType)>& callback)
     : SecurityInterstitialPage(web_contents, request_url),
       login_url_(login_url),
       callback_(callback) {
@@ -220,7 +220,7 @@
   // Need to explicity deny the certificate via the callback, otherwise memory
   // is leaked.
   if (!callback_.is_null()) {
-    callback_.Run(false);
+    callback_.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
     callback_.Reset();
   }
 }
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.h b/chrome/browser/ssl/captive_portal_blocking_page.h
index ce185d9a..170b251 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page.h
+++ b/chrome/browser/ssl/captive_portal_blocking_page.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "chrome/browser/interstitials/security_interstitial_page.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "url/gurl.h"
 
 #if !defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
@@ -40,12 +41,14 @@
   // Interstitial type, for testing.
   static const void* const kTypeForTesting;
 
-  CaptivePortalBlockingPage(content::WebContents* web_contents,
-                            const GURL& request_url,
-                            const GURL& login_url,
-                            std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-                            const net::SSLInfo& ssl_info,
-                            const base::Callback<void(bool)>& callback);
+  CaptivePortalBlockingPage(
+      content::WebContents* web_contents,
+      const GURL& request_url,
+      const GURL& login_url,
+      std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
+      const net::SSLInfo& ssl_info,
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback);
   ~CaptivePortalBlockingPage() override;
 
   // InterstitialPageDelegate method:
@@ -72,7 +75,7 @@
   // URL of the login page, opened when the user clicks the "Connect" button.
   const GURL login_url_;
   std::unique_ptr<CertReportHelper> cert_report_helper_;
-  base::Callback<void(bool)> callback_;
+  base::Callback<void(content::CertificateRequestResultType)> callback_;
 
   DISALLOW_COPY_AND_ASSIGN(CaptivePortalBlockingPage);
 };
diff --git a/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
index f039c09..844e941 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
+++ b/chrome/browser/ssl/captive_portal_blocking_page_browsertest.cc
@@ -67,7 +67,8 @@
       const GURL& login_url,
       std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
       const net::SSLInfo& ssl_info,
-      const base::Callback<void(bool)>& callback,
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback,
       bool is_wifi,
       const std::string& wifi_ssid)
       : CaptivePortalBlockingPage(web_contents,
@@ -140,8 +141,9 @@
   CaptivePortalBlockingPage* blocking_page =
       new CaptivePortalBlockingPageForTesting(
           contents, GURL(kBrokenSSL), login_url, std::move(ssl_cert_reporter),
-          ssl_info, base::Callback<void(bool)>(), is_wifi_connection,
-          wifi_ssid);
+          ssl_info,
+          base::Callback<void(content::CertificateRequestResultType)>(),
+          is_wifi_connection, wifi_ssid);
   blocking_page->Show();
 
   WaitForInterstitialAttach(contents);
@@ -318,7 +320,8 @@
     CaptivePortalBlockingPage* blocking_page =
         new CaptivePortalBlockingPageForTesting(
             contents, GURL(kBrokenSSL), request_url, nullptr, empty_ssl_info,
-            base::Callback<void(bool)>(), false, "");
+            base::Callback<void(content::CertificateRequestResultType)>(),
+            false, "");
     return blocking_page;
   }
 };
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index 82bede2..c6f0890e4 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -115,7 +115,7 @@
     int options_mask,
     const base::Time& time_triggered,
     std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-    const base::Callback<void(bool)>& callback)
+    const base::Callback<void(content::CertificateRequestResultType)>& callback)
     : SecurityInterstitialPage(web_contents, request_url),
       callback_(callback),
       ssl_info_(ssl_info),
@@ -240,7 +240,7 @@
 
   // Accepting the certificate resumes the loading of the page.
   DCHECK(!callback_.is_null());
-  callback_.Run(true);
+  callback_.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE);
   callback_.Reset();
 }
 
@@ -261,7 +261,7 @@
   if (callback_.is_null())
     return;
 
-  callback_.Run(false);
+  callback_.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
   callback_.Reset();
 }
 
diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h
index f60a66f..1353e9a0 100644
--- a/chrome/browser/ssl/ssl_blocking_page.h
+++ b/chrome/browser/ssl/ssl_blocking_page.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ssl/ssl_cert_reporter.h"
 #include "components/certificate_reporting/error_report.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "net/ssl/ssl_info.h"
 #include "url/gurl.h"
 
@@ -59,7 +60,8 @@
                   int options_mask,
                   const base::Time& time_triggered,
                   std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-                  const base::Callback<void(bool)>& callback);
+                  const base::Callback<
+                      void(content::CertificateRequestResultType)>& callback);
 
   // InterstitialPageDelegate method:
   InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
@@ -91,7 +93,7 @@
  private:
   void NotifyDenyCertificate();
 
-  base::Callback<void(bool)> callback_;
+  base::Callback<void(content::CertificateRequestResultType)> callback_;
   const net::SSLInfo ssl_info_;
   const bool overridable_;  // The UI allows the user to override the error.
 
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 757bae42..456bfd37 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -736,6 +736,29 @@
                                  AuthState::DISPLAYED_INSECURE_CONTENT);
 }
 
+// Tests that the NavigationEntry gets marked as active mixed content,
+// even if there is a certificate error. Regression test for
+// https://crbug.com/593950.
+IN_PROC_BROWSER_TEST_F(SSLUITest, TestBrokenHTTPSWithActiveInsecureContent) {
+  ASSERT_TRUE(https_server_expired_.Start());
+
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(tab);
+
+  // Navigate to a page with a certificate error and click through the
+  // interstitial.
+  ui_test_utils::NavigateToURL(
+      browser(),
+      https_server_expired_.GetURL("/ssl/page_runs_insecure_content.html"));
+  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID,
+                                 AuthState::SHOWING_INTERSTITIAL);
+  ProceedThroughInterstitial(tab);
+
+  // Now check that the page is marked as having run insecure content.
+  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID,
+                                 AuthState::RAN_INSECURE_CONTENT);
+}
+
 IN_PROC_BROWSER_TEST_F(SSLUITest, TestBrokenHTTPSMetricsReporting_Proceed) {
   ASSERT_TRUE(https_server_expired_.Start());
   ASSERT_NO_FATAL_FAILURE(SetUpMockReporter());
@@ -917,8 +940,11 @@
 
   // We should see no interstitial, but we should have an error
   // (red-crossed-out-https) in the URL bar.
+  // TODO(estark): once http://crbug.com/634171 is fixed and certificate
+  // errors for subresources don't generate
+  // DISPLAYED/RAN_INSECURE_CONTENT switch this back to AuthState::NONE.
   CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
-                                 AuthState::NONE);
+                                 AuthState::RAN_INSECURE_CONTENT);
 
   // We should see that the script tag in the page loaded and ran (and
   // wasn't blocked by the certificate error).
@@ -2205,8 +2231,11 @@
   observer.Wait();
 
   // We should still be authentication broken.
-  CheckAuthenticationBrokenState(
-      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
+  // TODO(estark): once http://crbug.com/634171 is fixed and certificate
+  // errors for subresources don't generate
+  // DISPLAYED/RAN_INSECURE_CONTENT switch this back to AuthState::NONE.
+  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID,
+                                 AuthState::RAN_INSECURE_CONTENT);
 }
 
 // From an HTTP top frame, navigate to good and bad HTTPS (security state should
@@ -2361,11 +2390,12 @@
   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
       tab, "window.domAutomationController.send(IsFooSet());", &js_result));
   EXPECT_TRUE(js_result);
-  // TODO(estark): once http://crbug.com/634171 is fixed and certificate errors
-  // for subresources don't generate DISPLAYED_INSECURE_CONTENT switch this back
-  // to AuthState::NONE.
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
-                                 AuthState::DISPLAYED_INSECURE_CONTENT);
+  // TODO(estark): once http://crbug.com/634171 is fixed and certificate
+  // errors for subresources don't generate
+  // DISPLAYED/RAN_INSECURE_CONTENT switch this back to AuthState::NONE.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_COMMON_NAME_INVALID,
+      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
 }
 
 // Like the test above, but only displaying inactive content (an image).
@@ -3010,7 +3040,8 @@
         net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
     return new SSLBlockingPage(
         contents, net::ERR_CERT_CONTAINS_ERRORS, ssl_info, request_url, 0,
-        base::Time::NowFromSystemTime(), nullptr, base::Callback<void(bool)>());
+        base::Time::NowFromSystemTime(), nullptr,
+        base::Callback<void(content::CertificateRequestResultType)>());
   }
 };
 
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc
index 0efa0e99..1f22451 100644
--- a/chrome/browser/ssl/ssl_error_handler.cc
+++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -155,7 +155,8 @@
     const GURL& request_url,
     int options_mask,
     std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-    const base::Callback<void(bool)>& callback) {
+    const base::Callback<void(content::CertificateRequestResultType)>&
+        callback) {
   DCHECK(!FromWebContents(web_contents));
   SSLErrorHandler* error_handler =
       new SSLErrorHandler(web_contents, cert_error, ssl_info, request_url,
@@ -188,7 +189,7 @@
     const GURL& request_url,
     int options_mask,
     std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-    const base::Callback<void(bool)>& callback)
+    const base::Callback<void(content::CertificateRequestResultType)>& callback)
     : content::WebContentsObserver(web_contents),
       web_contents_(web_contents),
       cert_error_(cert_error),
@@ -409,7 +410,8 @@
   // Need to explicity deny the certificate via the callback, otherwise memory
   // is leaked.
   if (!callback_.is_null()) {
-    base::ResetAndReturn(&callback_).Run(false);
+    base::ResetAndReturn(&callback_)
+        .Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
   }
   if (common_name_mismatch_handler_) {
     common_name_mismatch_handler_->Cancel();
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h
index f86c487..6431dad3 100644
--- a/chrome/browser/ssl/ssl_error_handler.h
+++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -56,13 +56,15 @@
 
   // Entry point for the class. The parameters are the same as SSLBlockingPage
   // constructor.
-  static void HandleSSLError(content::WebContents* web_contents,
-                             int cert_error,
-                             const net::SSLInfo& ssl_info,
-                             const GURL& request_url,
-                             int options_mask,
-                             std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-                             const base::Callback<void(bool)>& callback);
+  static void HandleSSLError(
+      content::WebContents* web_contents,
+      int cert_error,
+      const net::SSLInfo& ssl_info,
+      const GURL& request_url,
+      int options_mask,
+      std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback);
 
   // Testing methods.
   static void SetInterstitialDelayForTest(base::TimeDelta delay);
@@ -79,7 +81,8 @@
                   const GURL& request_url,
                   int options_mask,
                   std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
-                  const base::Callback<void(bool)>& callback);
+                  const base::Callback<
+                      void(content::CertificateRequestResultType)>& callback);
 
   ~SSLErrorHandler() override;
 
@@ -132,7 +135,7 @@
   const net::SSLInfo ssl_info_;
   const GURL request_url_;
   const int options_mask_;
-  base::Callback<void(bool)> callback_;
+  base::Callback<void(content::CertificateRequestResultType)> callback_;
   Profile* const profile_;
 
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/ssl/ssl_error_handler_unittest.cc b/chrome/browser/ssl/ssl_error_handler_unittest.cc
index 0bea2056..e31b526 100644
--- a/chrome/browser/ssl/ssl_error_handler_unittest.cc
+++ b/chrome/browser/ssl/ssl_error_handler_unittest.cc
@@ -29,13 +29,14 @@
   SSLErrorHandlerForTest(Profile* profile,
                          content::WebContents* web_contents,
                          const net::SSLInfo& ssl_info)
-      : SSLErrorHandler(web_contents,
-                        net::ERR_CERT_COMMON_NAME_INVALID,
-                        ssl_info,
-                        GURL(),
-                        0,
-                        nullptr,
-                        base::Callback<void(bool)>()),
+      : SSLErrorHandler(
+            web_contents,
+            net::ERR_CERT_COMMON_NAME_INVALID,
+            ssl_info,
+            GURL(),
+            0,
+            nullptr,
+            base::Callback<void(content::CertificateRequestResultType)>()),
         profile_(profile),
         captive_portal_checked_(false),
         suggested_url_exists_(false),
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index e2b7875..5313eaa 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -213,10 +213,6 @@
     ]
   }
 
-  if (use_aura) {
-    defines += [ "MOJO_RUNNER_CLIENT" ]
-  }
-
   if (enable_basic_printing || enable_print_preview) {
     deps += [ "//printing" ]
   }
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.h b/chrome/browser/ui/toolbar/media_router_contextual_menu.h
index 234f785..1fdb949 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu.h
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.h
@@ -20,6 +20,11 @@
   ui::MenuModel* menu_model() { return &menu_model_; }
 
  private:
+#if defined(GOOGLE_CHROME_BUILD)
+  FRIEND_TEST_ALL_PREFIXES(MediaRouterContextualMenuUnitTest,
+                           ToggleCloudServicesItem);
+#endif  // GOOGLE_CHROME_BUILD
+
   // ui::SimpleMenuModel::Delegate:
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
index 062151ba4..add32614 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
@@ -89,3 +89,29 @@
     EXPECT_TRUE(model()->IsVisibleAt(i));
   }
 }
+
+#if defined(GOOGLE_CHROME_BUILD)
+// Tests whether the cloud services item is correctly toggled. This menu item
+// is only availble on official Chrome builds.
+TEST_F(MediaRouterContextualMenuUnitTest, ToggleCloudServicesItem) {
+  // The Media Router Action has a getter for the model, but not the delegate.
+  // Create the MediaRouterContextualMenu ui::SimpleMenuModel::Delegate here.
+  MediaRouterContextualMenu menu(browser());
+
+  // Set up an authenticated account such that the cloud services menu item is
+  // surfaced. Whether or not it is surfaced is tested in the "Basic" test.
+  signin_manager()->SetAuthenticatedAccountInfo("foo@bar.com", "password");
+
+  // By default, the command is not checked.
+  EXPECT_FALSE(menu.IsCommandIdChecked(
+      IDC_MEDIA_ROUTER_CLOUD_SERVICES_TOGGLE));
+
+  menu.ExecuteCommand(IDC_MEDIA_ROUTER_CLOUD_SERVICES_TOGGLE, 0);
+  EXPECT_TRUE(menu.IsCommandIdChecked(
+      IDC_MEDIA_ROUTER_CLOUD_SERVICES_TOGGLE));
+
+  menu.ExecuteCommand(IDC_MEDIA_ROUTER_CLOUD_SERVICES_TOGGLE, 0);
+  EXPECT_FALSE(menu.IsCommandIdChecked(
+      IDC_MEDIA_ROUTER_CLOUD_SERVICES_TOGGLE));
+}
+#endif  // GOOGLE_CHROME_BUILD
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
index ea89f60..fbbcf2b 100644
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
@@ -83,12 +83,15 @@
 
 bool BrowserDesktopWindowTreeHostWin::GetClientAreaInsets(
     gfx::Insets* insets) const {
-  // Use the default client insets for an opaque frame or a glass popup/app
-  // frame.
-  if (!GetWidget()->ShouldUseNativeFrame() ||
-      !browser_view_->IsBrowserTypeNormal()) {
+  // Always use default insets for opaque frame.
+  if (!ShouldUseNativeFrame())
     return false;
-  }
+
+  // Use default insets for popups and apps, unless we are custom drawing the
+  // titlebar.
+  if (!browser_frame_->CustomDrawSystemTitlebar() &&
+      !browser_view_->IsBrowserTypeNormal())
+    return false;
 
   if (GetWidget()->IsFullscreen()) {
     // In fullscreen mode there is no frame.
@@ -242,6 +245,16 @@
 // BrowserDesktopWindowTreeHostWin, private:
 
 void BrowserDesktopWindowTreeHostWin::UpdateDWMFrame() {
+  // With a custom titlebar we want the margins to always be 2 pixels, because
+  // that gives us the 1 pixel accent color border around the window (a 1 pixel
+  // margin is not sufficient, it will draw a messed-up-looking border instead).
+  if (browser_frame_->CustomDrawSystemTitlebar() && ShouldUseNativeFrame() &&
+      !GetWidget()->IsFullscreen()) {
+    MARGINS margins = {2, 2, 2, 2};
+    DwmExtendFrameIntoClientArea(GetHWND(), &margins);
+    return;
+  }
+
   // For "normal" windows on Aero, we always need to reset the glass area
   // correctly, even if we're not currently showing the native frame (e.g.
   // because a theme is showing), so we explicitly check for that case rather
@@ -279,7 +292,7 @@
 MARGINS BrowserDesktopWindowTreeHostWin::GetDWMFrameMargins() const {
   // If we're using the opaque frame or we're fullscreen we don't extend the
   // glass in at all because it won't be visible.
-  if (!GetWidget()->ShouldUseNativeFrame() || GetWidget()->IsFullscreen())
+  if (!ShouldUseNativeFrame() || GetWidget()->IsFullscreen())
     return MARGINS{0};
 
   // The glass should extend to the bottom of the tabstrip.
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc
index 541cc22..d0ca175 100644
--- a/chrome/browser/ui/views/frame/browser_frame.cc
+++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -46,6 +46,7 @@
 #endif
 
 #if defined(OS_WIN)
+#include "base/win/windows_version.h"
 #include "ui/native_theme/native_theme_dark_win.h"
 #endif
 
@@ -145,6 +146,16 @@
   return native_browser_frame_->UseCustomFrame();
 }
 
+bool BrowserFrame::CustomDrawSystemTitlebar() const {
+#if defined(OS_WIN)
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+             switches::kWindows10CustomTitlebar) &&
+         base::win::GetVersion() >= base::win::VERSION_WIN10;
+#else
+  return false;
+#endif
+}
+
 bool BrowserFrame::ShouldSaveWindowPlacement() const {
   return native_browser_frame_->ShouldSaveWindowPlacement();
 }
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h
index 63498e2..b68adf47 100644
--- a/chrome/browser/ui/views/frame/browser_frame.h
+++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -85,6 +85,10 @@
   // Returns |true| if we should use the custom frame.
   bool UseCustomFrame() const;
 
+  // Returns whether we should custom draw the titlebar even if we're using the
+  // native frame. Only applicable to Windows.
+  bool CustomDrawSystemTitlebar() const;
+
   // Returns true when the window placement should be saved.
   bool ShouldSaveWindowPlacement() const;
 
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index ffd364c..d8db91b 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -38,11 +38,8 @@
     GlassBrowserFrameView::kThrobberIconCount];
 
 namespace {
-// Thickness of the border in the client area that separates it from the
-// non-client area. Includes but is distinct from kClientEdgeThickness, which is
-// the thickness of the border between the web content and our frame border.
-const int kClientBorderThicknessPreWin10 = 3;
-const int kClientBorderThicknessWin10 = 1;
+// Thickness of the frame edge between the non-client area and the web content.
+const int kClientBorderThickness = 3;
 // Besides the frame border, there's empty space atop the window in restored
 // mode, to use to drag the window around.
 const int kNonClientRestoredExtraThickness = 11;
@@ -215,11 +212,15 @@
 }
 
 int GlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) {
-  // If the browser isn't in normal mode, we haven't customized the frame, so
-  // Windows can figure this out.  If the point isn't within our bounds, then
-  // it's in the native portion of the frame, so again Windows can figure it
-  // out.
-  if (!browser_view()->IsBrowserTypeNormal() || !bounds().Contains(point))
+  // For app windows and popups without a custom titlebar we haven't customized
+  // the frame at all so Windows can figure it out.
+  if (!frame()->CustomDrawSystemTitlebar() &&
+      !browser_view()->IsBrowserTypeNormal())
+    return HTNOWHERE;
+
+  // If the point isn't within our bounds, then it's in the native portion of
+  // the frame so again Windows can figure it out.
+  if (!bounds().Contains(point))
     return HTNOWHERE;
 
   // See if the point is within the incognito icon or the profile switcher menu.
@@ -290,11 +291,13 @@
 // GlassBrowserFrameView, views::View overrides:
 
 void GlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) {
+  if (frame()->CustomDrawSystemTitlebar())
+    PaintTitlebar(canvas);
   if (!browser_view()->IsTabStripVisible())
     return;
   if (IsToolbarVisible())
     PaintToolbarBackground(canvas);
-  if (!frame()->IsMaximized())
+  if (ClientBorderThickness(false) > 0)
     PaintClientEdge(canvas);
 }
 
@@ -334,12 +337,14 @@
 }
 
 int GlassBrowserFrameView::ClientBorderThickness(bool restored) const {
+  // The frame ends abruptly at the 1 pixel window border drawn by Windows 10.
+  if (base::win::GetVersion() >= base::win::VERSION_WIN10)
+    return 0;
+
   if ((frame()->IsMaximized() || frame()->IsFullscreen()) && !restored)
     return 0;
 
-  return (base::win::GetVersion() < base::win::VERSION_WIN10)
-             ? kClientBorderThicknessPreWin10
-             : kClientBorderThicknessWin10;
+  return kClientBorderThickness;
 }
 
 int GlassBrowserFrameView::FrameBorderThickness() const {
@@ -384,6 +389,13 @@
       (top + kNonClientRestoredExtraThickness - exclusion);
 }
 
+int GlassBrowserFrameView::TitlebarHeight(bool restored) const {
+  if (frame()->IsFullscreen() && !restored)
+    return 0;
+  return display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYCAPTION) +
+         display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYSIZEFRAME);
+}
+
 int GlassBrowserFrameView::WindowTopY() const {
   return frame()->IsMaximized() ? FrameTopBorderThickness(false) : 1;
 }
@@ -400,6 +412,17 @@
   return base::i18n::IsRTL();
 }
 
+void GlassBrowserFrameView::PaintTitlebar(gfx::Canvas* canvas) const {
+  SkColor frame_color = 0xFFCCCCCC;
+  gfx::Rect tabstrip_bounds = GetBoundsForTabStrip(browser_view()->tabstrip());
+  const int y = WindowTopY();
+  canvas->FillRect(gfx::Rect(0, y, width(), tabstrip_bounds.bottom() - y),
+                   frame_color);
+  // The 1 pixel line at the top is drawn by Windows when we leave that section
+  // of the window blank because we have called DwmExtendFrameIntoClientArea()
+  // inside BrowserDesktopWindowTreeHostWin::UpdateDWMFrame().
+}
+
 void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) const {
   gfx::Rect toolbar_bounds(browser_view()->GetToolbarBounds());
   if (toolbar_bounds.IsEmpty())
@@ -443,7 +466,6 @@
                                         separator_rect, true);
 
     // Toolbar/content separator.
-    toolbar_bounds.Inset(kClientEdgeThickness, 0);
     BrowserView::Paint1pxHorizontalLine(canvas, separator_color, toolbar_bounds,
                                         true);
   } else {
@@ -612,8 +634,11 @@
 }
 
 gfx::Insets GlassBrowserFrameView::GetClientAreaInsets(bool restored) const {
-  if (!browser_view()->IsTabStripVisible())
-    return gfx::Insets();
+  if (!browser_view()->IsTabStripVisible()) {
+    const int top =
+        frame()->CustomDrawSystemTitlebar() ? TitlebarHeight(restored) : 0;
+    return gfx::Insets(top, 0, 0, 0);
+  }
 
   const int top_height = TopAreaHeight(restored);
   const int border_thickness = ClientBorderThickness(restored);
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
index 440c133..2beb6c7 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -76,6 +76,10 @@
   // window was restored, regardless of its current state.
   int TopAreaHeight(bool restored) const;
 
+  // Returns the height of the titlebar for popups or other browser types that
+  // don't have tabs.
+  int TitlebarHeight(bool restored) const;
+
   // Returns the y coordinate for the top of the frame, which in maximized mode
   // is the top of the screen and in restored mode is 1 pixel below the top of
   // the window to leave room for the visual border that Windows draws.
@@ -89,6 +93,7 @@
   bool CaptionButtonsOnLeadingEdge() const;
 
   // Paint various sub-components of this view.
+  void PaintTitlebar(gfx::Canvas* canvas) const;
   void PaintToolbarBackground(gfx::Canvas* canvas) const;
   void PaintClientEdge(gfx::Canvas* canvas) const;
   void FillClientEdgeRects(int x,
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index ee8d33a..0ab0ecb 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -149,7 +149,8 @@
       base::StringPrintf(
           "child-src chrome://terms/ %s/;",
           extensions::kGaiaAuthExtensionOrigin));
-  source->OverrideContentSecurityPolicyObjectSrc("object-src *;");
+  source->OverrideContentSecurityPolicyObjectSrc(
+      "object-src chrome:;");
   source->AddResourcePath("gaia_auth_host.js",
                           StartupUtils::IsWebviewSigninEnabled()
                               ? IDR_GAIA_AUTH_AUTHENTICATOR_JS
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 2f0cbd5..9cfbe67 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -94,7 +94,8 @@
       const GURL& request_url,
       const GURL& login_url,
       const net::SSLInfo& ssl_info,
-      const base::Callback<void(bool)>& callback,
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback,
       bool is_wifi,
       const std::string& wifi_ssid)
       : CaptivePortalBlockingPage(web_contents,
@@ -152,9 +153,10 @@
     options_mask |= security_interstitials::SSLErrorUI::SOFT_OVERRIDE_ENABLED;
   if (strict_enforcement)
     options_mask |= security_interstitials::SSLErrorUI::STRICT_ENFORCEMENT;
-  return new SSLBlockingPage(web_contents, cert_error, ssl_info, request_url,
-                             options_mask, time_triggered_, nullptr,
-                             base::Callback<void(bool)>());
+  return new SSLBlockingPage(
+      web_contents, cert_error, ssl_info, request_url, options_mask,
+      time_triggered_, nullptr,
+      base::Callback<void(content::CertificateRequestResultType)>());
 }
 
 BadClockBlockingPage* CreateBadClockBlockingPage(
@@ -200,9 +202,10 @@
     options_mask |= security_interstitials::SSLErrorUI::SOFT_OVERRIDE_ENABLED;
   if (strict_enforcement)
     options_mask |= security_interstitials::SSLErrorUI::STRICT_ENFORCEMENT;
-  return new BadClockBlockingPage(web_contents, cert_error, ssl_info,
-                                  request_url, base::Time::Now(), clock_state,
-                                  nullptr, base::Callback<void(bool)>());
+  return new BadClockBlockingPage(
+      web_contents, cert_error, ssl_info, request_url, base::Time::Now(),
+      clock_state, nullptr,
+      base::Callback<void(content::CertificateRequestResultType)>());
 }
 
 safe_browsing::SafeBrowsingBlockingPage* CreateSafeBrowsingBlockingPage(
@@ -294,7 +297,8 @@
   CaptivePortalBlockingPage* blocking_page =
       new CaptivePortalBlockingPageWithNetInfo(
           web_contents, request_url, landing_url, ssl_info,
-          base::Callback<void(bool)>(), is_wifi_connection, wifi_ssid);
+          base::Callback<void(content::CertificateRequestResultType)>(),
+          is_wifi_connection, wifi_ssid);
   return blocking_page;
 }
 #endif
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui.cc b/chrome/browser/ui/webui/media_router/media_router_ui.cc
index c9f1d30..a03e149 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui.cc
@@ -183,7 +183,7 @@
   // Allows UI to load extensionview.
   // TODO(haibinlu): limit object-src to current extension once crbug/514866
   // is fixed.
-  html_source->OverrideContentSecurityPolicyObjectSrc("object-src *;");
+  html_source->OverrideContentSecurityPolicyObjectSrc("object-src chrome:;");
 
   AddLocalizedStrings(html_source.get());
   AddMediaRouterUIResources(html_source.get());
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc
index b640115..b654ae9a 100644
--- a/chrome/browser/ui/webui/signin/inline_login_ui.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -29,7 +29,7 @@
   content::WebUIDataSource* source =
         content::WebUIDataSource::Create(chrome::kChromeUIChromeSigninHost);
   source->OverrideContentSecurityPolicyChildSrc("child-src chrome-extension:;");
-  source->OverrideContentSecurityPolicyObjectSrc("object-src *;");
+  source->OverrideContentSecurityPolicyObjectSrc("object-src chrome:;");
   source->SetJsonPath("strings.js");
 
   source->SetDefaultResource(IDR_NEW_INLINE_LOGIN_HTML);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index b422311..abcd3fa 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -1259,6 +1259,10 @@
 // Causes the process to run as a watcher process.
 const char kWatcherProcess[]                = "watcher";
 
+// Enables custom-drawing the titlebar and tabstrip background so that it's not
+// a garish #FFFFFF like it is by default on Windows 10.
+const char kWindows10CustomTitlebar[]       = "windows10-custom-titlebar";
+
 // Indicates that chrome was launched to service a search request in Windows 8.
 const char kWindows8Search[]                = "windows8-search";
 #endif  // defined(OS_WIN)
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 49aa1130..b6aa0cbf 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -365,6 +365,7 @@
 extern const char kUninstall[];
 extern const char kViewerLaunchViaAppId[];
 extern const char kWatcherProcess[];
+extern const char kWindows10CustomTitlebar[];
 extern const char kWindows8Search[];
 #endif  // defined(OS_WIN)
 
diff --git a/chrome/gpu/arc_gpu_video_decode_accelerator.cc b/chrome/gpu/arc_gpu_video_decode_accelerator.cc
index c0c01c9..27e0a9e 100644
--- a/chrome/gpu/arc_gpu_video_decode_accelerator.cc
+++ b/chrome/gpu/arc_gpu_video_decode_accelerator.cc
@@ -104,6 +104,9 @@
     case HAL_PIXEL_FORMAT_VP8:
       vda_config.profile = media::VP8PROFILE_ANY;
       break;
+    case HAL_PIXEL_FORMAT_VP9:
+      vda_config.profile = media::VP9PROFILE_PROFILE0;
+      break;
     default:
       DLOG(ERROR) << "Unsupported input format: " << config.input_pixel_format;
       return INVALID_ARGUMENT;
diff --git a/chrome/gpu/arc_video_accelerator.h b/chrome/gpu/arc_video_accelerator.h
index b60619a..a1ef232 100644
--- a/chrome/gpu/arc_video_accelerator.h
+++ b/chrome/gpu/arc_video_accelerator.h
@@ -22,6 +22,7 @@
   // ArcVideoAccelerator to identify the input format.
   HAL_PIXEL_FORMAT_H264 = 0x34363248,
   HAL_PIXEL_FORMAT_VP8 = 0x00385056,
+  HAL_PIXEL_FORMAT_VP9 = 0x00395056,
 };
 
 enum PortType {
diff --git a/chrome/test/data/webui/md_history/history_synced_tabs_test.js b/chrome/test/data/webui/md_history/history_synced_tabs_test.js
index f4545fa..748eb41 100644
--- a/chrome/test/data/webui/md_history/history_synced_tabs_test.js
+++ b/chrome/test/data/webui/md_history/history_synced_tabs_test.js
@@ -197,13 +197,17 @@
           assertEquals('Chromebook', args[0], 'sessionTag is correct');
           assertEquals('123', args[1], 'windowId is correct');
           assertEquals('456', args[2], 'tabId is correct');
+          assertFalse(args[4], 'altKey is defined');
+          assertFalse(args[5], 'ctrlKey is defined');
+          assertFalse(args[6], 'metaKey is defined');
+          assertFalse(args[7], 'shiftKey is defined');
           done();
         });
 
         flush().then(function() {
           var cards = getCards();
           var anchor = cards[0].root.querySelector('a');
-          MockInteractions.tap(anchor);
+          MockInteractions.tap(anchor, {emulateTouch: true});
         });
       });
 
diff --git a/chrome/test/data/webui/media_router/media_router_container_sink_list_tests.js b/chrome/test/data/webui/media_router/media_router_container_sink_list_tests.js
index c6f5766..5a66c5b8 100644
--- a/chrome/test/data/webui/media_router/media_router_container_sink_list_tests.js
+++ b/chrome/test/data/webui/media_router/media_router_container_sink_list_tests.js
@@ -103,6 +103,72 @@
         });
       });
 
+      // Tests that text shown for each sink matches their names.
+      test('updated sink list', function(done) {
+        var sinkOne = new media_router.Sink('sink id 1', 'Sink 1',
+                null, null,
+                media_router.SinkIconType.GENERIC,
+                media_router.SinkStatus.IDLE, [1, 2, 3]);
+        var sinkTwo = new media_router.Sink('sink id 2', 'Sink 2',
+                null, 'example.com',
+                media_router.SinkIconType.GENERIC,
+                media_router.SinkStatus.IDLE, [1, 2, 3]);
+        var sinkThree = new media_router.Sink('sink id 3', 'Sink 3',
+                null, 'example.com',
+                media_router.SinkIconType.GENERIC,
+                media_router.SinkStatus.IDLE, [1, 2, 3]);
+        var sinkFour = new media_router.Sink('sink id 4', 'Sink 4',
+                null, 'example.com',
+                media_router.SinkIconType.GENERIC,
+                media_router.SinkStatus.IDLE, [1, 2, 3]);
+
+        // Set the initial sink list and check that the order corresponds.
+        var listOne = [sinkOne, sinkTwo];
+        var listOneExpected = [sinkOne, sinkTwo];
+        container.allSinks = listOne;
+        setTimeout(function() {
+          var sinkList =
+              container.shadowRoot.getElementById('sink-list')
+                  .querySelectorAll('paper-item');
+          assertEquals(listOne.length, sinkList.length);
+          for (var i = 0; i < listOneExpected.length; i++) {
+            checkElementText(listOneExpected[i].name, sinkList[i]);
+          }
+
+          // Update the sink list with a new sink, but not at the end of the
+          // array. The existing sinks should appear first, then the new
+          // sink.
+          var listTwo = [sinkOne, sinkThree, sinkTwo];
+          var listTwoExpected = [sinkOne, sinkTwo, sinkThree];
+          container.allSinks = listTwo;
+          setTimeout(function() {
+            sinkList =
+                container.shadowRoot.getElementById('sink-list')
+                    .querySelectorAll('paper-item');
+            assertEquals(listTwo.length, sinkList.length);
+            for (var i = 0; i < listTwoExpected.length; i++) {
+              checkElementText(listTwoExpected[i].name, sinkList[i]);
+            }
+
+            // If any sinks are not included in a sink list update, remove
+            // them from the sink list.
+            var listThree = [sinkFour, sinkOne];
+            var listThreeExpected = [sinkOne, sinkFour];
+            container.allSinks = listThree;
+            setTimeout(function() {
+              sinkList =
+                  container.shadowRoot.getElementById('sink-list')
+                      .querySelectorAll('paper-item');
+              assertEquals(listThree.length, sinkList.length);
+              for (var i = 0; i < listThreeExpected.length; i++) {
+                checkElementText(listThreeExpected[i].name, sinkList[i]);
+              }
+              done();
+            });
+          });
+        });
+      });
+
       // Tests that text shown for sink with domain matches the name and domain.
       test('sink with domain text', function(done) {
         // Sink 1 - sink, no domain -> text = name
diff --git a/chrome/test/data/webui/media_router/route_details_tests.js b/chrome/test/data/webui/media_router/route_details_tests.js
index c4cd0b8..dcab054 100644
--- a/chrome/test/data/webui/media_router/route_details_tests.js
+++ b/chrome/test/data/webui/media_router/route_details_tests.js
@@ -157,7 +157,7 @@
       // route is not joinable.
       test('start casting button click replaces route', function(done) {
         details.addEventListener(
-            'replace-route-click', function() { done(); });
+            'change-route-source-click', function() { done(); });
         details.route = fakeRouteOne;
         details.availableCastModes = 1;
         MockInteractions.tap(details.$['start-casting-to-route-button']);
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 77fd003..f673aa8a 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -470,7 +470,7 @@
           cast_browser_process_->browser_context(),
           cast_browser_process_->pref_service(),
           url_request_context_factory_->GetSystemGetter(),
-          video_plane_controller_.get()));
+          video_plane_controller_.get(), media_caps_.get()));
   cast_browser_process_->cast_service()->Initialize();
 
 #if !defined(OS_ANDROID)
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 699f550c..73ccf496 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -127,7 +127,8 @@
     content::BrowserContext* browser_context,
     PrefService* pref_service,
     net::URLRequestContextGetter* request_context_getter,
-    media::VideoPlaneController* video_plane_controller) {
+    media::VideoPlaneController* video_plane_controller,
+    media::MediaCapsImpl* media_caps) {
   return base::WrapUnique(new CastServiceSimple(browser_context, pref_service));
 }
 
@@ -329,11 +330,13 @@
     bool overridable,
     bool strict_enforcement,
     bool expired_previous_decision,
-    const base::Callback<void(bool)>& callback,
-    content::CertificateRequestResultType* result) {
+    const base::Callback<void(content::CertificateRequestResultType)>&
+        callback) {
   // Allow developers to override certificate errors.
   // Otherwise, any fatal certificate errors will cause an abort.
-  *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
+  if (!callback.is_null()) {
+    callback.Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
+  }
   return;
 }
 
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 4c2930f..929ade6 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -12,6 +12,7 @@
 
 #include "base/macros.h"
 #include "build/build_config.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/browser/content_browser_client.h"
 
 class PrefService;
@@ -36,6 +37,7 @@
 class CastService;
 
 namespace media {
+class MediaCapsImpl;
 class MediaPipelineBackend;
 class MediaPipelineBackendManager;
 struct MediaPipelineDeviceParams;
@@ -69,7 +71,8 @@
       content::BrowserContext* browser_context,
       PrefService* pref_service,
       net::URLRequestContextGetter* request_context_getter,
-      media::VideoPlaneController* video_plane_controller);
+      media::VideoPlaneController* video_plane_controller,
+      media::MediaCapsImpl* media_caps);
 
 #if !defined(OS_ANDROID)
   // Returns the task runner that must be used for media IO.
@@ -118,8 +121,8 @@
       bool overridable,
       bool strict_enforcement,
       bool expired_previous_decision,
-      const base::Callback<void(bool)>& callback,
-      content::CertificateRequestResultType* result) override;
+      const base::Callback<void(content::CertificateRequestResultType)>&
+          callback) override;
   void SelectClientCertificate(
       content::WebContents* web_contents,
       net::SSLCertRequestInfo* cert_request_info,
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index c7dc3da..2644fae 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-8683.0.0
\ No newline at end of file
+8685.0.0
\ No newline at end of file
diff --git a/components/autofill/core/browser/autofill_assistant_unittest.cc b/components/autofill/core/browser/autofill_assistant_unittest.cc
index b1a61d8..4f93f19 100644
--- a/components/autofill/core/browser/autofill_assistant_unittest.cc
+++ b/components/autofill/core/browser/autofill_assistant_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/feature_list.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/autofill_driver.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_manager.h"
@@ -58,11 +59,7 @@
         autofill_assistant_(&autofill_manager_) {}
 
   void EnableAutofillCreditCardAssist() {
-    base::FeatureList::ClearInstanceForTesting();
-    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    feature_list->InitializeFromCommandLine(kAutofillCreditCardAssist.name,
-                                            std::string());
-    base::FeatureList::SetInstance(std::move(feature_list));
+    scoped_feature_list_.InitAndEnableFeature(kAutofillCreditCardAssist);
   }
 
   // Returns an initialized FormStructure with credit card form data. To be
@@ -105,6 +102,7 @@
   testing::NiceMock<TestAutofillDriver> autofill_driver_;
   MockAutofillManager autofill_manager_;
   AutofillAssistant autofill_assistant_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 MATCHER_P(CreditCardMatches, guid, "") {
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index fffcb83..9333062 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -24,6 +24,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -768,7 +769,6 @@
     autofill_manager_->SetExternalDelegate(external_delegate_.get());
 
     // Clear all the things.
-    base::FeatureList::ClearInstanceForTesting();
     variations::testing::ClearAllVariationParams();
   }
 
@@ -803,7 +803,7 @@
     feature_list->RegisterFieldTrialOverride(
         kAutofillCreditCardSigninPromo.name,
         base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
-    base::FeatureList::SetInstance(std::move(feature_list));
+    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
 
     // Double-checking our params made it.
     std::map<std::string, std::string> actualParams;
@@ -1000,6 +1000,7 @@
   TestAutofillDownloadManager* download_manager_;
   TestPersonalDataManager personal_data_;
   base::FieldTrialList field_trial_list_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 class TestFormStructure : public FormStructure {
diff --git a/components/autofill/core/browser/autofill_merge_unittest.cc b/components/autofill/core/browser/autofill_merge_unittest.cc
index 3baf432..dfa9314 100644
--- a/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/autofill_experiments.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/autofill_type.h"
@@ -183,6 +184,7 @@
   PersonalDataManagerMock personal_data_;
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
   std::map<std::string, ServerFieldType> string_to_field_type_map_;
 
   DISALLOW_COPY_AND_ASSIGN(AutofillMergeTest);
@@ -201,12 +203,7 @@
 
 void AutofillMergeTest::SetUp() {
   test::DisableSystemServices(nullptr);
-
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine(kAutofillProfileCleanup.name,
-                                          std::string());
-  base::FeatureList::SetInstance(std::move(feature_list));
+  scoped_feature_list_.InitAndEnableFeature(kAutofillProfileCleanup);
 }
 
 void AutofillMergeTest::TearDown() {
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 60f6296a..12263113 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -23,6 +23,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -141,11 +142,7 @@
 
     // There are no field trials enabled by default.
     field_trial_list_.reset();
-
-    // There are no features enabled by default.
-    base::FeatureList::ClearInstanceForTesting();
-    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    base::FeatureList::SetInstance(std::move(feature_list));
+    scoped_feature_list_.reset();
 
     // Reset the deduping pref to its default value.
     personal_data_->pref_service_->SetInteger(
@@ -199,11 +196,8 @@
   }
 
   void EnableAutofillProfileCleanup() {
-    base::FeatureList::ClearInstanceForTesting();
-    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    feature_list->InitializeFromCommandLine(kAutofillProfileCleanup.name,
-                                            std::string());
-    base::FeatureList::SetInstance(std::move(feature_list));
+    scoped_feature_list_.reset(new base::test::ScopedFeatureList);
+    scoped_feature_list_->InitAndEnableFeature(kAutofillProfileCleanup);
     personal_data_->is_autofill_profile_dedupe_pending_ = true;
   }
 
@@ -368,6 +362,7 @@
 
   std::unique_ptr<base::FieldTrialList> field_trial_list_;
   scoped_refptr<base::FieldTrial> field_trial_;
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
 };
 
 TEST_F(PersonalDataManagerTest, AddProfile) {
@@ -5202,9 +5197,7 @@
                        "", "Springfield", "IL", "91601", "", "");
 
   // Disable the profile cleanup before adding |profile3|.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  base::FeatureList::SetInstance(std::move(feature_list));
+  scoped_feature_list_.reset();
 
   personal_data_->AddProfile(profile3);
   EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged())
diff --git a/components/browser_sync/browser/profile_sync_service_unittest.cc b/components/browser_sync/browser/profile_sync_service_unittest.cc
index e53e159d..45b5497 100644
--- a/components/browser_sync/browser/profile_sync_service_unittest.cc
+++ b/components/browser_sync/browser/profile_sync_service_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/sequenced_worker_pool_owner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
@@ -726,9 +727,9 @@
 // Verify that OnLocalSetPassphraseEncryption triggers catch up configure sync
 // cycle, calls ClearServerData, shuts down and restarts sync.
 TEST_F(ProfileSyncServiceTest, OnLocalSetPassphraseEncryption) {
-  base::FeatureList::ClearInstanceForTesting();
-  ASSERT_TRUE(base::FeatureList::InitializeInstance(
-      switches::kSyncClearDataOnPassphraseEncryption.name, std::string()));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      switches::kSyncClearDataOnPassphraseEncryption);
   IssueTestTokens();
   CreateService(ProfileSyncService::AUTO_START);
 
@@ -778,9 +779,9 @@
 TEST_F(ProfileSyncServiceTest,
        OnLocalSetPassphraseEncryption_RestartDuringCatchUp) {
   syncer::ConfigureReason configure_reason = syncer::CONFIGURE_REASON_UNKNOWN;
-  base::FeatureList::ClearInstanceForTesting();
-  ASSERT_TRUE(base::FeatureList::InitializeInstance(
-      switches::kSyncClearDataOnPassphraseEncryption.name, std::string()));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      switches::kSyncClearDataOnPassphraseEncryption);
   IssueTestTokens();
   CreateService(ProfileSyncService::AUTO_START);
   ExpectSyncBackendHostCreation(1);
@@ -834,9 +835,9 @@
        OnLocalSetPassphraseEncryption_RestartDuringClearServerData) {
   syncer::SyncManager::ClearServerDataCallback captured_callback;
   syncer::ConfigureReason configure_reason = syncer::CONFIGURE_REASON_UNKNOWN;
-  base::FeatureList::ClearInstanceForTesting();
-  ASSERT_TRUE(base::FeatureList::InitializeInstance(
-      switches::kSyncClearDataOnPassphraseEncryption.name, std::string()));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      switches::kSyncClearDataOnPassphraseEncryption);
   IssueTestTokens();
   CreateService(ProfileSyncService::AUTO_START);
   ExpectSyncBackendHostCreationCaptureClearServerData(&captured_callback);
diff --git a/components/cronet/ios/BUILD.gn b/components/cronet/ios/BUILD.gn
index c7e4a23..38dfb99 100644
--- a/components/cronet/ios/BUILD.gn
+++ b/components/cronet/ios/BUILD.gn
@@ -64,7 +64,6 @@
 ios_framework_bundle("cronet_framework") {
   output_name = "Cronet"
   info_plist_target = ":tweak_cronet_plist"
-  code_signing_enabled = false
 
   deps = [
     ":cronet_sources",
diff --git a/components/filesystem/file_system_app.cc b/components/filesystem/file_system_app.cc
index a47ffbf1..2be93f2 100644
--- a/components/filesystem/file_system_app.cc
+++ b/components/filesystem/file_system_app.cc
@@ -43,8 +43,9 @@
   tracing_.Initialize(connector(), identity.name());
 }
 
-bool FileSystemApp::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::FileSystem>(this);
+bool FileSystemApp::OnConnect(const shell::Identity& remote_identity,
+                              shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::FileSystem>(this);
   return true;
 }
 
diff --git a/components/filesystem/file_system_app.h b/components/filesystem/file_system_app.h
index c23b070c..ee72a60 100644
--- a/components/filesystem/file_system_app.h
+++ b/components/filesystem/file_system_app.h
@@ -32,7 +32,8 @@
 
   // |shell::Service| override:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // |InterfaceFactory<Files>| implementation:
   void Create(const shell::Identity& remote_identity,
diff --git a/components/flags_ui/BUILD.gn b/components/flags_ui/BUILD.gn
index 5f226ffd..9d085a1 100644
--- a/components/flags_ui/BUILD.gn
+++ b/components/flags_ui/BUILD.gn
@@ -48,6 +48,7 @@
     ":flags_ui",
     ":switches",
     "//base",
+    "//base/test:test_support",
     "//components/prefs:test_support",
     "//components/strings",
     "//components/variations",
diff --git a/components/flags_ui/flags_state_unittest.cc b/components/flags_ui/flags_state_unittest.cc
index 8a036991..5c6bbc0a6 100644
--- a/components/flags_ui/flags_state_unittest.cc
+++ b/components/flags_ui/flags_state_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "components/flags_ui/feature_entry.h"
@@ -318,8 +319,8 @@
 
   // Set the feature_list as the main instance so that
   // variations::GetVariationParamValueByFeature below works.
-  base::FeatureList::ClearInstanceForTesting();
-  base::FeatureList::SetInstance(std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatureList(std::move(feature_list));
 
   // The param should have the value predefined in this variation.
   EXPECT_EQ(kTestParamValue,
diff --git a/components/font_service/font_service_app.cc b/components/font_service/font_service_app.cc
index 9d58644..888709f 100644
--- a/components/font_service/font_service_app.cc
+++ b/components/font_service/font_service_app.cc
@@ -52,8 +52,9 @@
   tracing_.Initialize(connector(), identity.name());
 }
 
-bool FontServiceApp::OnConnect(shell::Connection* connection) {
-  connection->AddInterface(this);
+bool FontServiceApp::OnConnect(const shell::Identity& remote_identity,
+                               shell::InterfaceRegistry* registry) {
+  registry->AddInterface(this);
   return true;
 }
 
diff --git a/components/font_service/font_service_app.h b/components/font_service/font_service_app.h
index 38abbd5..18d1f3c 100644
--- a/components/font_service/font_service_app.h
+++ b/components/font_service/font_service_app.h
@@ -28,7 +28,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // shell::InterfaceFactory<mojom::FontService>:
   void Create(const shell::Identity& remote_identity,
diff --git a/components/leveldb/leveldb_app.cc b/components/leveldb/leveldb_app.cc
index 379a2e28..b6e2aba 100644
--- a/components/leveldb/leveldb_app.cc
+++ b/components/leveldb/leveldb_app.cc
@@ -6,7 +6,7 @@
 
 #include "base/message_loop/message_loop.h"
 #include "components/leveldb/leveldb_service_impl.h"
-#include "services/shell/public/cpp/connection.h"
+#include "services/shell/public/cpp/interface_registry.h"
 
 namespace leveldb {
 
@@ -18,8 +18,9 @@
   tracing_.Initialize(connector(), identity.name());
 }
 
-bool LevelDBApp::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::LevelDBService>(this);
+bool LevelDBApp::OnConnect(const shell::Identity& remote_identity,
+                           shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::LevelDBService>(this);
   return true;
 }
 
diff --git a/components/leveldb/leveldb_app.h b/components/leveldb/leveldb_app.h
index 7e8b8282..28706c1b 100644
--- a/components/leveldb/leveldb_app.h
+++ b/components/leveldb/leveldb_app.h
@@ -24,7 +24,8 @@
  private:
   // |Service| override:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // |InterfaceFactory<mojom::LevelDBService>| implementation:
   void Create(const shell::Identity& remote_identity,
diff --git a/components/metrics/proto/BUILD.gn b/components/metrics/proto/BUILD.gn
index 3271f184..968d5de 100644
--- a/components/metrics/proto/BUILD.gn
+++ b/components/metrics/proto/BUILD.gn
@@ -10,6 +10,7 @@
     "call_stack_profile.proto",
     "cast_logs.proto",
     "chrome_user_metrics_extension.proto",
+    "execution_context.proto",
     "histogram_event.proto",
     "memory_leak_report.proto",
     "omnibox_event.proto",
diff --git a/components/metrics/proto/execution_context.proto b/components/metrics/proto/execution_context.proto
new file mode 100644
index 0000000..3d8679f
--- /dev/null
+++ b/components/metrics/proto/execution_context.proto
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+option java_outer_classname = "ExecutionContextProtos";
+option java_package = "org.chromium.components.metrics";
+
+package metrics;
+
+// Enums corresponding to the Chrome execution context in which data was
+// collected.
+
+// Chrome process type. Derived from content/public/common/process_type.h.
+enum Process {
+  UNKNOWN_PROCESS = 0;
+  BROWSER_PROCESS = 1;
+  RENDERER_PROCESS = 2;
+  GPU_PROCESS = 3;
+  UTILITY_PROCESS = 4;
+  ZYGOTE_PROCESS = 5;
+  SANDBOX_HELPER_PROCESS = 6;
+  PPAPI_PLUGIN_PROCESS = 7;
+  PPAPI_BROKER_PROCESS = 8;
+}
+
+// Chrome thread. This list is not exhaustive.
+enum Thread {
+  UNKNOWN_THREAD = 0;
+
+  // Browser process threads from content/public/browser/browser_thread.h,
+  // some of which occur in other processes as well.
+  UI_THREAD = 1;
+  FILE_THREAD = 2;
+  FILE_USER_BLOCKING_THREAD = 3;
+  PROCESS_LAUNCHER_THREAD = 4;
+  CACHE_THREAD = 5;
+  IO_THREAD = 6;
+  DB_THREAD = 7;
+
+  // GPU process thread.
+  GPU_MAIN_THREAD = 8;
+
+  // Renderer process threads.
+  RENDER_THREAD = 9;
+  UTILITY_THREAD = 10;
+}
diff --git a/components/metrics/proto/sampled_profile.proto b/components/metrics/proto/sampled_profile.proto
index b8936e1..0d8fcae4 100644
--- a/components/metrics/proto/sampled_profile.proto
+++ b/components/metrics/proto/sampled_profile.proto
@@ -11,13 +11,14 @@
 package metrics;
 
 import "call_stack_profile.proto";
+import "execution_context.proto";
 import "perf_data.proto";
 import "perf_stat.proto";
 
 // Protocol buffer for collected sample-based profiling data.
 // Contains the parameters and data from a single profile collection event.
 
-// Next tag: 11
+// Next tag: 13
 message SampledProfile {
   // Indicates the event that triggered this collection.
   enum TriggerEvent {
@@ -35,7 +36,7 @@
 
     // The profile was collected upon restoring a previous session.
     RESTORE_SESSION = 3;
-    
+
     // The profile was collected at process startup.
     PROCESS_STARTUP = 4;
 
@@ -47,6 +48,12 @@
   }
   optional TriggerEvent trigger_event = 1;
 
+  // The process in which the profile was collected.
+  optional Process process = 11;
+
+  // The thread in which the profile was collected.
+  optional Thread thread = 12;
+
   // Fields 2-3: Time durations are given in ticks, and represent system uptime
   // rather than wall time.
 
diff --git a/components/network_time/network_time_tracker_unittest.cc b/components/network_time/network_time_tracker_unittest.cc
index 98fbf6b..a3c24b83 100644
--- a/components/network_time/network_time_tracker_unittest.cc
+++ b/components/network_time/network_time_tracker_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/mock_entropy_provider.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_clock.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "components/client_update_protocol/ecdsa.h"
@@ -181,7 +182,6 @@
                                  base::FEATURE_DISABLED_BY_DEFAULT};
 
     // Clear all the things.
-    base::FeatureList::ClearInstanceForTesting();
     variations::testing::ClearAllVariationParams();
 
     std::map<std::string, std::string> params;
@@ -192,8 +192,9 @@
     // FeatureList.  Don't get confused!  The FieldTrial is reference-counted,
     // and a reference is held by the FieldTrialList.  The FieldTrialList and
     // FeatureList are both singletons.  The authorized way to reset the former
-    // for testing is to destruct it (above).  The latter, by contrast, is reset
-    // with |ClearInstanceForTesting|, above.  If this comment was useful to you
+    // for testing is to destruct it (above).  The latter, by contrast, should
+    // should already start in a clean state and can be manipulated via the
+    // ScopedFeatureList helper class. If this comment was useful to you
     // please send me a postcard.
 
     field_trial_list_.reset();  // Averts a CHECK fail in constructor below.
@@ -212,7 +213,8 @@
         kFeature.name, enable ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
                               : base::FeatureList::OVERRIDE_DISABLE_FEATURE,
         trial);
-    base::FeatureList::SetInstance(std::move(feature_list));
+    scoped_feature_list_.reset(new base::test::ScopedFeatureList);
+    scoped_feature_list_->InitWithFeatureList(std::move(feature_list));
   }
 
   base::Thread io_thread_;
@@ -226,6 +228,7 @@
   std::unique_ptr<base::FieldTrialList> field_trial_list_;
   std::unique_ptr<NetworkTimeTracker> tracker_;
   std::unique_ptr<net::EmbeddedTestServer> test_server_;
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
 };
 
 TEST_F(NetworkTimeTrackerTest, Uninitialized) {
diff --git a/components/offline_pages/background/offliner_policy.h b/components/offline_pages/background/offliner_policy.h
index 5a6591a..d640d259 100644
--- a/components/offline_pages/background/offliner_policy.h
+++ b/components/offline_pages/background/offliner_policy.h
@@ -6,7 +6,8 @@
 #define COMPONENTS_OFFLINE_PAGES_BACKGROUND_OFFLINER_POLICY_H_
 
 namespace {
-const int kMaxTries = 1;
+const int kMaxStartedTries = 5;
+const int kMaxCompletedTries = 1;
 const int kBackgroundProcessingTimeBudgetSeconds = 170;
 const int kSinglePageTimeLimitSeconds = 120;
 const int kMinimumBatteryPercentageForNonUserRequestOfflining = 50;
@@ -22,14 +23,21 @@
   OfflinerPolicy()
       : prefer_untried_requests_(false),
         prefer_earlier_requests_(true),
-        retry_count_is_more_important_than_recency_(false) {}
+        retry_count_is_more_important_than_recency_(false),
+        max_started_tries_(kMaxStartedTries),
+        max_completed_tries_(kMaxCompletedTries) {}
 
+  // Constructor for unit tests.
   OfflinerPolicy(bool prefer_untried,
                  bool prefer_earlier,
-                 bool prefer_retry_count)
+                 bool prefer_retry_count,
+                 int max_started_tries,
+                 int max_completed_tries)
       : prefer_untried_requests_(prefer_untried),
         prefer_earlier_requests_(prefer_earlier),
-        retry_count_is_more_important_than_recency_(prefer_retry_count) {}
+        retry_count_is_more_important_than_recency_(prefer_retry_count),
+        max_started_tries_(max_started_tries),
+        max_completed_tries_(max_completed_tries) {}
 
   // TODO(petewil): Numbers here are chosen arbitrarily, do the proper studies
   // to get good policy numbers.
@@ -48,8 +56,14 @@
     return retry_count_is_more_important_than_recency_;
   }
 
-  // The max number of times we will retry a request.
-  int GetMaxTries() const { return kMaxTries; }
+  // The max number of times we will start a request.  Not all started attempts
+  // will complete.  This may be caused by prerenderer issues or chromium being
+  // swapped out of memory.
+  int GetMaxStartedTries() const { return max_started_tries_; }
+
+  // The max number of times we will retry a request when the attempt
+  // completed, but failed.
+  int GetMaxCompletedTries() const { return max_completed_tries_; }
 
   bool PowerRequiredForUserRequestedPage() const { return false; }
 
@@ -92,6 +106,8 @@
   bool prefer_untried_requests_;
   bool prefer_earlier_requests_;
   bool retry_count_is_more_important_than_recency_;
+  int max_started_tries_;
+  int max_completed_tries_;
 };
 }
 
diff --git a/components/offline_pages/background/request_coordinator.cc b/components/offline_pages/background/request_coordinator.cc
index 426b90ba..20f2e745 100644
--- a/components/offline_pages/background/request_coordinator.cc
+++ b/components/offline_pages/background/request_coordinator.cc
@@ -303,9 +303,13 @@
                                      updated_request.client_id()));
 
   } else if (status == Offliner::RequestStatus::SAVED ||
-             request.attempt_count() >= policy_->GetMaxTries()) {
+             request.completed_attempt_count() + 1 >=
+                 policy_->GetMaxCompletedTries()) {
     // Remove the request from the queue if it either succeeded or exceeded the
-    // max number of retries.
+    // max number of retries.  The +1 represents the request that just
+    // completed. Since we call MarkAttemptCompleted within the if branches,
+    // the completed_attempt_count has not yet been updated when we are checking
+    // the if condition.
     queue_->RemoveRequest(
         request.request_id(),
         base::Bind(&RequestCoordinator::UpdateRequestCallback,
diff --git a/components/offline_pages/background/request_coordinator_unittest.cc b/components/offline_pages/background/request_coordinator_unittest.cc
index cd81ccc..6ef185c 100644
--- a/components/offline_pages/background/request_coordinator_unittest.cc
+++ b/components/offline_pages/background/request_coordinator_unittest.cc
@@ -459,7 +459,7 @@
   EXPECT_EQ(1UL, last_requests().size());
   // Verify foreground cancel not counted as an attempt after all.
   const SavePageRequest& found_request = last_requests().front();
-  EXPECT_EQ(0L, found_request.attempt_count());
+  EXPECT_EQ(0L, found_request.completed_attempt_count());
 }
 
 // This tests a StopProcessing call before we have actually started the
@@ -588,7 +588,7 @@
       kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested);
   offline_pages::SavePageRequest request2(
       kRequestId1 + 1, kUrl1, kClientId1, base::Time::Now(), kUserRequested);
-  request2.set_attempt_count(kAttemptCount);
+  request2.set_completed_attempt_count(kAttemptCount);
   coordinator()->queue()->AddRequest(
       request1,
       base::Bind(&RequestCoordinatorTest::AddRequestDone,
diff --git a/components/offline_pages/background/request_picker.cc b/components/offline_pages/background/request_picker.cc
index d601406..47bff56 100644
--- a/components/offline_pages/background/request_picker.cc
+++ b/components/offline_pages/background/request_picker.cc
@@ -89,7 +89,7 @@
 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) {
   // If the user did not request the page directly, make sure we are connected
   // to power and have WiFi and sufficient battery remaining before we take this
-  // reqeust.
+  // request.
   // TODO(petewil): We may later want to configure whether to allow 2G for non
   // user_requested items, add that to policy.
   if (!request.user_requested()) {
@@ -107,11 +107,18 @@
     }
   }
 
-  // If we have already tried this page the max number of times, it is not
+  // If we have already started this page the max number of times, it is not
   // eligible to try again.
-  // TODO(petewil): Instead, we should have code to remove the page from the
+  // TODO(petewil): We should have code to remove the page from the
   // queue after the last retry.
-  if (request.attempt_count() > policy_->GetMaxTries())
+  if (request.started_attempt_count() >= policy_->GetMaxStartedTries())
+    return false;
+
+  // If we have already completed trying this page the max number of times, it
+  // is not eligible to try again.
+  // TODO(petewil): We should have code to remove the page from the
+  // queue after the last retry.
+  if (request.completed_attempt_count() >= policy_->GetMaxCompletedTries())
     return false;
 
   // If the request is expired, do not consider it.
@@ -187,7 +194,8 @@
 int RequestPicker::CompareRetryCount(
     const SavePageRequest* left, const SavePageRequest* right) {
   // Check the attempt count.
-  int result = signum(left->attempt_count() - right->attempt_count());
+  int result = signum(left->completed_attempt_count() -
+                      right->completed_attempt_count());
 
   // Flip the direction of comparison if policy prefers fewer retries.
   if (fewer_retries_better_)
diff --git a/components/offline_pages/background/request_picker_unittest.cc b/components/offline_pages/background/request_picker_unittest.cc
index 633c1eb..cd74c70 100644
--- a/components/offline_pages/background/request_picker_unittest.cc
+++ b/components/offline_pages/background/request_picker_unittest.cc
@@ -29,6 +29,8 @@
 const bool kUserRequested = true;
 const int kAttemptCount = 1;
 const int kTwoWeeksInSeconds = 60 * 60 * 24 * 7 * 2;
+const int kMaxStartedTries = 5;
+const int kMaxCompletedTries = 1;
 
 // Constants for policy values - These settings represent the default values.
 const bool kPreferUntried = false;
@@ -142,12 +144,17 @@
 }
 
 TEST_F(RequestPickerTest, ChooseRequestWithHigherRetryCount) {
+  policy_.reset(new OfflinerPolicy(kPreferUntried, kPreferEarlier,
+                                   kPreferRetryCount, kMaxStartedTries,
+                                   kMaxCompletedTries + 1));
+  picker_.reset(new RequestPicker(queue_.get(), policy_.get()));
+
   base::Time creation_time = base::Time::Now();
   SavePageRequest request1(
       kRequestId1, kUrl1, kClientId1, creation_time, kUserRequested);
   SavePageRequest request2(
       kRequestId2, kUrl2, kClientId2, creation_time, kUserRequested);
-  request2.set_attempt_count(kAttemptCount);
+  request2.set_completed_attempt_count(kAttemptCount);
 
   QueueRequestsAndChooseOne(request1, request2);
 
@@ -172,8 +179,9 @@
 
 TEST_F(RequestPickerTest, ChooseEarlierRequest) {
   // We need a custom policy object prefering recency to retry count.
-  policy_.reset(
-      new OfflinerPolicy(kPreferUntried, kPreferEarlier, !kPreferRetryCount));
+  policy_.reset(new OfflinerPolicy(kPreferUntried, kPreferEarlier,
+                                   !kPreferRetryCount, kMaxStartedTries,
+                                   kMaxCompletedTries));
   picker_.reset(new RequestPicker(queue_.get(), policy_.get()));
 
   base::Time creation_time1 =
@@ -183,7 +191,7 @@
                            kUserRequested);
   SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2,
                            kUserRequested);
-  request2.set_attempt_count(kAttemptCount);
+  request2.set_completed_attempt_count(kAttemptCount);
 
   QueueRequestsAndChooseOne(request1, request2);
 
@@ -193,8 +201,9 @@
 
 TEST_F(RequestPickerTest, ChooseSameTimeRequestWithHigherRetryCount) {
   // We need a custom policy object preferring recency to retry count.
-  policy_.reset(
-      new OfflinerPolicy(kPreferUntried, kPreferEarlier, !kPreferRetryCount));
+  policy_.reset(new OfflinerPolicy(kPreferUntried, kPreferEarlier,
+                                   !kPreferRetryCount, kMaxStartedTries,
+                                   kMaxCompletedTries + 1));
   picker_.reset(new RequestPicker(queue_.get(), policy_.get()));
 
   base::Time creation_time = base::Time::Now();
@@ -202,7 +211,7 @@
                            kUserRequested);
   SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time,
                            kUserRequested);
-  request2.set_attempt_count(kAttemptCount);
+  request2.set_completed_attempt_count(kAttemptCount);
 
   QueueRequestsAndChooseOne(request1, request2);
 
@@ -212,8 +221,9 @@
 
 TEST_F(RequestPickerTest, ChooseRequestWithLowerRetryCount) {
   // We need a custom policy object preferring lower retry count.
-  policy_.reset(
-      new OfflinerPolicy(!kPreferUntried, kPreferEarlier, kPreferRetryCount));
+  policy_.reset(new OfflinerPolicy(!kPreferUntried, kPreferEarlier,
+                                   kPreferRetryCount, kMaxStartedTries,
+                                   kMaxCompletedTries + 1));
   picker_.reset(new RequestPicker(queue_.get(), policy_.get()));
 
   base::Time creation_time = base::Time::Now();
@@ -221,7 +231,7 @@
                            kUserRequested);
   SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time,
                            kUserRequested);
-  request2.set_attempt_count(kAttemptCount);
+  request2.set_completed_attempt_count(kAttemptCount);
 
   QueueRequestsAndChooseOne(request1, request2);
 
@@ -231,8 +241,9 @@
 
 TEST_F(RequestPickerTest, ChooseLaterRequest) {
   // We need a custom policy preferring recency over retry, and later requests.
-  policy_.reset(
-      new OfflinerPolicy(kPreferUntried, !kPreferEarlier, !kPreferRetryCount));
+  policy_.reset(new OfflinerPolicy(kPreferUntried, !kPreferEarlier,
+                                   !kPreferRetryCount, kMaxStartedTries,
+                                   kMaxCompletedTries));
   picker_.reset(new RequestPicker(queue_.get(), policy_.get()));
 
   base::Time creation_time1 =
@@ -264,4 +275,41 @@
   EXPECT_FALSE(request_queue_empty_called_);
 }
 
+TEST_F(RequestPickerTest, ChooseRequestThatHasNotExceededStartLimit) {
+  base::Time creation_time1 =
+      base::Time::Now() - base::TimeDelta::FromSeconds(1);
+  base::Time creation_time2 = base::Time::Now();
+  SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time1,
+                           kUserRequested);
+  SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2,
+                           kUserRequested);
+
+  // With default policy settings, we should choose the earlier request.
+  // However, we will make the earlier reqeust exceed the limit.
+  request1.set_started_attempt_count(policy_->GetMaxStartedTries());
+
+  QueueRequestsAndChooseOne(request1, request2);
+
+  EXPECT_EQ(kRequestId2, last_picked_->request_id());
+  EXPECT_FALSE(request_queue_empty_called_);
+}
+
+TEST_F(RequestPickerTest, ChooseRequestThatHasNotExceededCompletionLimit) {
+  base::Time creation_time1 =
+      base::Time::Now() - base::TimeDelta::FromSeconds(1);
+  base::Time creation_time2 = base::Time::Now();
+  SavePageRequest request1(kRequestId1, kUrl1, kClientId1, creation_time1,
+                           kUserRequested);
+  SavePageRequest request2(kRequestId2, kUrl2, kClientId2, creation_time2,
+                           kUserRequested);
+
+  // With default policy settings, we should choose the earlier request.
+  // However, we will make the earlier reqeust exceed the limit.
+  request1.set_completed_attempt_count(policy_->GetMaxCompletedTries());
+
+  QueueRequestsAndChooseOne(request1, request2);
+
+  EXPECT_EQ(kRequestId2, last_picked_->request_id());
+  EXPECT_FALSE(request_queue_empty_called_);
+}
 }  // namespace offline_pages
diff --git a/components/offline_pages/background/request_queue_store_sql.cc b/components/offline_pages/background/request_queue_store_sql.cc
index b9de0c8..264b2ac 100644
--- a/components/offline_pages/background/request_queue_store_sql.cc
+++ b/components/offline_pages/background/request_queue_store_sql.cc
@@ -31,7 +31,9 @@
                       " creation_time INTEGER NOT NULL,"
                       " activation_time INTEGER NOT NULL DEFAULT 0,"
                       " last_attempt_time INTEGER NOT NULL DEFAULT 0,"
-                      " attempt_count INTEGER NOT NULL,"
+                      " started_attempt_count INTEGER NOT NULL,"
+                      " completed_attempt_count INTEGER NOT NULL,"
+                      " state INTEGER NOT NULL DEFAULT 0,"
                       " url VARCHAR NOT NULL,"
                       " client_namespace VARCHAR NOT NULL,"
                       " client_id VARCHAR NOT NULL"
@@ -40,7 +42,15 @@
 }
 
 bool CreateSchema(sql::Connection* db) {
-  // TODO(fgorski): Upgrade code goes here and requires transaction.
+  // If there is not already a state column, we need to drop the old table.  We
+  // are choosing to drop instead of upgrade since the feature is not yet
+  // released, so we don't use a transaction to protect existing data, or try to
+  // migrate it.
+  if (!db->DoesColumnExist(REQUEST_QUEUE_TABLE_NAME, "state")) {
+    if (!db->Execute("DROP TABLE IF EXISTS " REQUEST_QUEUE_TABLE_NAME))
+      return false;
+  }
+
   if (!CreateRequestQueueTable(db))
     return false;
 
@@ -124,10 +134,13 @@
       base::Time::FromInternalValue(statement.ColumnInt64(2));
   const base::Time last_attempt_time =
       base::Time::FromInternalValue(statement.ColumnInt64(3));
-  const int64_t last_attempt_count = statement.ColumnInt64(4);
-  const GURL url(statement.ColumnString(5));
-  const ClientId client_id(statement.ColumnString(6),
-                           statement.ColumnString(7));
+  const int64_t started_attempt_count = statement.ColumnInt64(4);
+  const int64_t completed_attempt_count = statement.ColumnInt64(5);
+  const SavePageRequest::RequestState state =
+      static_cast<SavePageRequest::RequestState>(statement.ColumnInt64(6));
+  const GURL url(statement.ColumnString(7));
+  const ClientId client_id(statement.ColumnString(8),
+                           statement.ColumnString(9));
 
   DVLOG(2) << "making save page request - id " << id << " url " << url
            << " client_id " << client_id.name_space << "-" << client_id.id
@@ -137,7 +150,9 @@
   SavePageRequest request(
       id, url, client_id, creation_time, activation_time, kUserRequested);
   request.set_last_attempt_time(last_attempt_time);
-  request.set_attempt_count(last_attempt_count);
+  request.set_started_attempt_count(started_attempt_count);
+  request.set_completed_attempt_count(completed_attempt_count);
+  request.set_request_state(state);
   return request;
 }
 
@@ -149,19 +164,22 @@
   const char kInsertSql[] =
       "INSERT OR REPLACE INTO " REQUEST_QUEUE_TABLE_NAME
       " (request_id, creation_time, activation_time, last_attempt_time, "
-      " attempt_count, url, client_namespace, client_id) "
+      " started_attempt_count, completed_attempt_count, state, url, "
+      " client_namespace, client_id) "
       " VALUES "
-      " (?, ?, ?, ?, ?, ?, ?, ?)";
+      " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
 
   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kInsertSql));
   statement.BindInt64(0, request.request_id());
   statement.BindInt64(1, request.creation_time().ToInternalValue());
   statement.BindInt64(2, request.activation_time().ToInternalValue());
   statement.BindInt64(3, request.last_attempt_time().ToInternalValue());
-  statement.BindInt64(4, request.attempt_count());
-  statement.BindString(5, request.url().spec());
-  statement.BindString(6, request.client_id().name_space);
-  statement.BindString(7, request.client_id().id);
+  statement.BindInt64(4, request.started_attempt_count());
+  statement.BindInt64(5, request.completed_attempt_count());
+  statement.BindInt64(6, static_cast<int64_t>(request.request_state()));
+  statement.BindString(7, request.url().spec());
+  statement.BindString(8, request.client_id().name_space);
+  statement.BindString(9, request.client_id().id);
 
   // TODO(fgorski): Replace the UpdateStatus with boolean in the
   // RequestQueueStore interface and update this code.
@@ -218,7 +236,8 @@
     const GetRequestsCallback& callback) {
   const char kSql[] =
       "SELECT request_id, creation_time, activation_time,"
-      " last_attempt_time, attempt_count, url, client_namespace, client_id"
+      " last_attempt_time, started_attempt_count, completed_attempt_count,"
+      " state, url, client_namespace, client_id"
       " FROM " REQUEST_QUEUE_TABLE_NAME;
 
   sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
diff --git a/components/offline_pages/background/request_queue_store_unittest.cc b/components/offline_pages/background/request_queue_store_unittest.cc
index 076b650..691a52a 100644
--- a/components/offline_pages/background/request_queue_store_unittest.cc
+++ b/components/offline_pages/background/request_queue_store_unittest.cc
@@ -40,8 +40,10 @@
          lhs.client_id() == rhs.client_id() &&
          lhs.creation_time() == rhs.creation_time() &&
          lhs.activation_time() == rhs.activation_time() &&
-         lhs.attempt_count() == rhs.attempt_count() &&
-         lhs.last_attempt_time() == rhs.last_attempt_time();
+         lhs.started_attempt_count() == rhs.started_attempt_count() &&
+         lhs.completed_attempt_count() == rhs.completed_attempt_count() &&
+         lhs.last_attempt_time() == rhs.last_attempt_time() &&
+         lhs.request_state() == rhs.request_state();
 }
 
 }  // namespace
diff --git a/components/offline_pages/background/request_queue_unittest.cc b/components/offline_pages/background/request_queue_unittest.cc
index cba4f10..967257c 100644
--- a/components/offline_pages/background/request_queue_unittest.cc
+++ b/components/offline_pages/background/request_queue_unittest.cc
@@ -259,7 +259,7 @@
   PumpLoop();
 
   // Update the request, ensure it succeeded.
-  request.set_attempt_count(kRetryCount);
+  request.set_completed_attempt_count(kRetryCount);
   queue()->UpdateRequest(
       request,
       base::Bind(&RequestQueueTest::UpdateRequestDone, base::Unretained(this)));
@@ -272,7 +272,7 @@
   PumpLoop();
   ASSERT_EQ(GetRequestsResult::SUCCESS, last_get_requests_result());
   ASSERT_EQ(1ul, last_requests().size());
-  ASSERT_EQ(kRetryCount, last_requests().front().attempt_count());
+  ASSERT_EQ(kRetryCount, last_requests().front().completed_attempt_count());
 }
 
 TEST_F(RequestQueueTest, UpdateRequestNotPresent) {
diff --git a/components/offline_pages/background/save_page_request.cc b/components/offline_pages/background/save_page_request.cc
index 2ed90bd8..3d59444 100644
--- a/components/offline_pages/background/save_page_request.cc
+++ b/components/offline_pages/background/save_page_request.cc
@@ -16,8 +16,10 @@
       client_id_(client_id),
       creation_time_(creation_time),
       activation_time_(creation_time),
-      attempt_count_(0),
-      user_requested_(was_user_requested) {}
+      started_attempt_count_(0),
+      completed_attempt_count_(0),
+      user_requested_(was_user_requested),
+      state_(RequestState::AVAILABLE) {}
 
 SavePageRequest::SavePageRequest(int64_t request_id,
                                  const GURL& url,
@@ -30,8 +32,10 @@
       client_id_(client_id),
       creation_time_(creation_time),
       activation_time_(activation_time),
-      attempt_count_(0),
-      user_requested_(user_requested) {}
+      started_attempt_count_(0),
+      completed_attempt_count_(0),
+      user_requested_(user_requested),
+      state_(RequestState::AVAILABLE) {}
 
 SavePageRequest::SavePageRequest(const SavePageRequest& other)
     : request_id_(other.request_id_),
@@ -39,9 +43,11 @@
       client_id_(other.client_id_),
       creation_time_(other.creation_time_),
       activation_time_(other.activation_time_),
-      attempt_count_(other.attempt_count_),
+      started_attempt_count_(other.started_attempt_count_),
+      completed_attempt_count_(other.completed_attempt_count_),
       last_attempt_time_(other.last_attempt_time_),
-      user_requested_(other.user_requested_) {}
+      user_requested_(other.user_requested_),
+      state_(other.state_) {}
 
 SavePageRequest::~SavePageRequest() {}
 
@@ -51,19 +57,25 @@
   // check here to ensure we only start tasks in status pending, and bail out in
   // other cases.
   last_attempt_time_ = start_time;
-  ++attempt_count_;
+  ++started_attempt_count_;
+  state_ = RequestState::PRERENDERING;
 }
 
 void SavePageRequest::MarkAttemptCompleted() {
-  last_attempt_time_ = base::Time();
+  ++completed_attempt_count_;
+  state_ = RequestState::AVAILABLE;
 }
 
 void SavePageRequest::MarkAttemptAborted() {
-  DCHECK_GT(attempt_count_, 0);
-  last_attempt_time_ = base::Time();
-  // TODO(dougarnett): Would be safer if we had two persisted counters
-  // (attempts_started and attempts_completed) rather just one with decrement.
-  --attempt_count_;
+  DCHECK_GT(started_attempt_count_, 0);
+  // We intentinally do not increment the completed_attempt_count_, since this
+  // was killed before it completed, so we could use the phone or browser for
+  // other things.
+  state_ = RequestState::AVAILABLE;
+}
+
+void SavePageRequest::MarkAttemptPaused() {
+  state_ = RequestState::PAUSED;
 }
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/background/save_page_request.h b/components/offline_pages/background/save_page_request.h
index b83b9b5c..9ddff04c 100644
--- a/components/offline_pages/background/save_page_request.h
+++ b/components/offline_pages/background/save_page_request.h
@@ -16,6 +16,12 @@
 // Class representing a request to save page.
 class SavePageRequest {
  public:
+  enum class RequestState {
+    AVAILABLE = 0,     // Request can be scheduled when preconditions are met.
+    PAUSED = 1,        // Request is not available until it is unpaused
+    PRERENDERING = 2,  // Request is active in the pre-renderer
+  };
+
   SavePageRequest(int64_t request_id,
                   const GURL& url,
                   const ClientId& client_id,
@@ -40,19 +46,31 @@
   // and decrements |attempt_count_|.
   void MarkAttemptAborted();
 
+  // Mark the attempt as paused.  It is not available for future prerendering
+  // until it has been explicitly unpaused.
+  void MarkAttemptPaused();
+
   int64_t request_id() const { return request_id_; }
 
   const GURL& url() const { return url_; }
 
   const ClientId& client_id() const { return client_id_; }
 
+  RequestState request_state() const { return state_; }
+  void set_request_state(RequestState new_state) { state_ = new_state; }
+
   const base::Time& creation_time() const { return creation_time_; }
 
   const base::Time& activation_time() const { return activation_time_; }
 
-  int64_t attempt_count() const { return attempt_count_; }
-  void set_attempt_count(int64_t attempt_count) {
-    attempt_count_ = attempt_count;
+  int64_t started_attempt_count() const { return started_attempt_count_; }
+  void set_started_attempt_count(int64_t started_attempt_count) {
+    started_attempt_count_ = started_attempt_count;
+  }
+
+  int64_t completed_attempt_count() const { return completed_attempt_count_; }
+  void set_completed_attempt_count(int64_t completed_attempt_count) {
+    completed_attempt_count_ = completed_attempt_count;
   }
 
   const base::Time& last_attempt_time() const { return last_attempt_time_; }
@@ -83,8 +101,12 @@
   // Time when this request will become active.
   base::Time activation_time_;
 
-  // Number of attempts made to get the page.
-  int attempt_count_;
+  // Number of attempts started to get the page.  This may be different than the
+  // number of attempts completed because we could crash.
+  int started_attempt_count_;
+
+  // Number of attempts we actually completed to get the page.
+  int completed_attempt_count_;
 
   // Timestamp of the last request starting.
   base::Time last_attempt_time_;
@@ -92,6 +114,9 @@
   // Whether the user specifically requested this page (as opposed to a client
   // like AGSA or Now.)
   bool user_requested_;
+
+  // The current state of this request
+  RequestState state_;
 };
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/background/save_page_request_unittest.cc b/components/offline_pages/background/save_page_request_unittest.cc
index 1cccc24..0f31d4e0 100644
--- a/components/offline_pages/background/save_page_request_unittest.cc
+++ b/components/offline_pages/background/save_page_request_unittest.cc
@@ -32,7 +32,10 @@
   ASSERT_EQ(creation_time, request.creation_time());
   ASSERT_EQ(creation_time, request.activation_time());
   ASSERT_EQ(base::Time(), request.last_attempt_time());
-  ASSERT_EQ(0, request.attempt_count());
+  ASSERT_EQ(0, request.completed_attempt_count());
+  ASSERT_EQ(SavePageRequest::RequestState::AVAILABLE, request.request_state());
+  ASSERT_EQ(0, request.started_attempt_count());
+  ASSERT_EQ(0, request.completed_attempt_count());
 }
 
 TEST_F(SavePageRequestTest, StartAndCompleteRequest) {
@@ -53,7 +56,9 @@
 
   // Attempt time, attempt count and status will though.
   ASSERT_EQ(start_time, request.last_attempt_time());
-  ASSERT_EQ(1, request.attempt_count());
+  ASSERT_EQ(1, request.started_attempt_count());
+  ASSERT_EQ(SavePageRequest::RequestState::PRERENDERING,
+            request.request_state());
 
   request.MarkAttemptCompleted();
 
@@ -65,16 +70,14 @@
   ASSERT_EQ(activation_time, request.activation_time());
 
   // Last attempt time and status are updated.
-  ASSERT_EQ(base::Time(), request.last_attempt_time());
-  ASSERT_EQ(1, request.attempt_count());
+  ASSERT_EQ(1, request.completed_attempt_count());
+  ASSERT_EQ(SavePageRequest::RequestState::AVAILABLE, request.request_state());
 }
 
 TEST_F(SavePageRequestTest, StartAndAbortRequest) {
   base::Time creation_time = base::Time::Now();
   SavePageRequest request(kRequestId, kUrl, kClientId, creation_time,
                           kUserRequested);
-  int start_attempt_count = 2;
-  request.set_attempt_count(start_attempt_count);
 
   base::Time start_time = creation_time + base::TimeDelta::FromHours(3);
   request.MarkAttemptStarted(start_time);
@@ -87,7 +90,9 @@
 
   // Attempt time and attempt count will though.
   ASSERT_EQ(start_time, request.last_attempt_time());
-  ASSERT_EQ(start_attempt_count + 1, request.attempt_count());
+  ASSERT_EQ(1, request.started_attempt_count());
+  ASSERT_EQ(SavePageRequest::RequestState::PRERENDERING,
+            request.request_state());
 
   request.MarkAttemptAborted();
 
@@ -97,9 +102,9 @@
   ASSERT_EQ(kClientId, request.client_id());
   ASSERT_EQ(creation_time, request.creation_time());
 
-  // Last attempt time is updated and attempt count decremented.
-  ASSERT_EQ(base::Time(), request.last_attempt_time());
-  ASSERT_EQ(start_attempt_count, request.attempt_count());
+  // Last attempt time is updated and completed attempt count did not rise.
+  ASSERT_EQ(0, request.completed_attempt_count());
+  ASSERT_EQ(SavePageRequest::RequestState::AVAILABLE, request.request_state());
 }
 
 }  // namespace offline_pages
diff --git a/components/offline_pages/offline_page_model_impl_unittest.cc b/components/offline_pages/offline_page_model_impl_unittest.cc
index 94902093..eb6c721 100644
--- a/components/offline_pages/offline_page_model_impl_unittest.cc
+++ b/components/offline_pages/offline_page_model_impl_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -1082,80 +1083,65 @@
   EXPECT_FALSE(offline_pages::IsOfflineBookmarksEnabled());
 
   // Check if feature is correctly enabled by command-line flag.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine(
-      offline_pages::kOfflineBookmarksFeature.name, "");
-  base::FeatureList::SetInstance(std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(kOfflineBookmarksFeature);
   EXPECT_TRUE(offline_pages::IsOfflineBookmarksEnabled());
 }
 
 TEST(CommandLineFlagsTest, OffliningRecentPages) {
   // Enable offline bookmarks feature first.
   // TODO(dimich): once offline pages are enabled by default, remove this.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine(
-      offline_pages::kOfflineBookmarksFeature.name, "");
-  base::FeatureList::SetInstance(std::move(feature_list));
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list(
+      new base::test::ScopedFeatureList);
+  scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature);
 
   // This feature is still disabled by default.
   EXPECT_FALSE(offline_pages::IsOffliningRecentPagesEnabled());
 
   // Check if feature is correctly enabled by command-line flag.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
-  feature_list2->InitializeFromCommandLine(
-      std::string(offline_pages::kOfflineBookmarksFeature.name) + "," +
-          offline_pages::kOffliningRecentPagesFeature.name,
+  scoped_feature_list.reset(new base::test::ScopedFeatureList);
+  scoped_feature_list->InitFromCommandLine(
+      std::string(kOfflineBookmarksFeature.name) + "," +
+          kOffliningRecentPagesFeature.name,
       "");
-  base::FeatureList::SetInstance(std::move(feature_list2));
   EXPECT_TRUE(offline_pages::IsOffliningRecentPagesEnabled());
 }
 
 TEST(CommandLineFlagsTest, OfflinePagesBackgroundLoading) {
   // Enable offline bookmarks feature first.
   // TODO(dimich): once offline pages are enabled by default, remove this.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine(
-      offline_pages::kOfflineBookmarksFeature.name, "");
-  base::FeatureList::SetInstance(std::move(feature_list));
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list(
+      new base::test::ScopedFeatureList);
+  scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature);
 
   // This feature is still disabled by default.
   EXPECT_FALSE(offline_pages::IsOfflinePagesBackgroundLoadingEnabled());
 
   // Check if feature is correctly enabled by command-line flag.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
-  feature_list2->InitializeFromCommandLine(
-      std::string(offline_pages::kOfflineBookmarksFeature.name) + "," +
-          offline_pages::kOfflinePagesBackgroundLoadingFeature.name,
+  scoped_feature_list.reset(new base::test::ScopedFeatureList);
+  scoped_feature_list->InitFromCommandLine(
+      std::string(kOfflineBookmarksFeature.name) + "," +
+          kOfflinePagesBackgroundLoadingFeature.name,
       "");
-  base::FeatureList::SetInstance(std::move(feature_list2));
   EXPECT_TRUE(offline_pages::IsOfflinePagesBackgroundLoadingEnabled());
 }
 
 TEST(CommandLineFlagsTest, OfflinePagesSharing) {
   // Enable offline bookmarks feature first.
   // TODO(dimich): once offline pages are enabled by default, remove this.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine(
-      offline_pages::kOfflineBookmarksFeature.name, "");
-  base::FeatureList::SetInstance(std::move(feature_list));
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list(
+      new base::test::ScopedFeatureList);
+  scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature);
 
   // This feature is still disabled by default.
   EXPECT_FALSE(offline_pages::IsOfflinePagesSharingEnabled());
 
   // Check if feature is correctly enabled by command-line flag.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
-  feature_list2->InitializeFromCommandLine(
-      std::string(offline_pages::kOfflineBookmarksFeature.name) + "," +
-          offline_pages::kOfflinePagesSharingFeature.name,
+  scoped_feature_list.reset(new base::test::ScopedFeatureList);
+  scoped_feature_list->InitFromCommandLine(
+      std::string(kOfflineBookmarksFeature.name) + "," +
+          kOfflinePagesSharingFeature.name,
       "");
-  base::FeatureList::SetInstance(std::move(feature_list2));
   EXPECT_TRUE(offline_pages::IsOfflinePagesSharingEnabled());
 }
 
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index b294ad3..54a021a 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_manager.h"
 #include "components/autofill/core/browser/proto/server.pb.h"
@@ -765,16 +766,11 @@
 class PasswordFormManagerFillOnAccountSelectTest
     : public PasswordFormManagerTest {
  public:
-  PasswordFormManagerFillOnAccountSelectTest() {}
-
-  void SetUp() override {
-    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    std::vector<const base::Feature*> enabled_features;
-    std::vector<const base::Feature*> disabled_features;
-    enabled_features.push_back(&features::kFillOnAccountSelect);
-    SetFeatures(enabled_features, disabled_features, std::move(feature_list));
-    PasswordFormManagerTest::SetUp();
+  PasswordFormManagerFillOnAccountSelectTest() {
+    scoped_feature_list_.InitAndEnableFeature(features::kFillOnAccountSelect);
   }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(PasswordFormManagerTest, TestNewLogin) {
diff --git a/components/password_manager/core/browser/password_manager_test_utils.cc b/components/password_manager/core/browser/password_manager_test_utils.cc
index 39eca2f..aa58692e 100644
--- a/components/password_manager/core/browser/password_manager_test_utils.cc
+++ b/components/password_manager/core/browser/password_manager_test_utils.cc
@@ -16,18 +16,6 @@
 
 namespace password_manager {
 
-namespace {
-
-void GetFeatureOverridesAsCSV(const std::vector<const base::Feature*>& features,
-                              std::string* overrides) {
-  for (const base::Feature* feature : features) {
-    overrides->append(feature->name);
-    overrides->push_back(',');
-  }
-}
-
-}  // namespace
-
 const char kTestingIconUrlSpec[] = "https://accounts.google.com/Icon";
 const char kTestingFederationUrlSpec[] = "https://accounts.google.com/login";
 const int kTestingDaysAfterPasswordsAreSynced = 1;
@@ -107,20 +95,6 @@
   return !had_mismatched_actual_form && remaining_expectations.empty();
 }
 
-void SetFeatures(const std::vector<const base::Feature*>& enable_features,
-                 const std::vector<const base::Feature*>& disable_features,
-                 std::unique_ptr<base::FeatureList> feature_list) {
-  std::string enable_overrides;
-  std::string disable_overrides;
-
-  GetFeatureOverridesAsCSV(enable_features, &enable_overrides);
-  GetFeatureOverridesAsCSV(disable_features, &disable_overrides);
-
-  base::FeatureList::ClearInstanceForTesting();
-  feature_list->InitializeFromCommandLine(enable_overrides, disable_overrides);
-  base::FeatureList::SetInstance(std::move(feature_list));
-}
-
 MockPasswordStoreObserver::MockPasswordStoreObserver() {}
 
 MockPasswordStoreObserver::~MockPasswordStoreObserver() {}
diff --git a/components/password_manager/core/browser/password_manager_test_utils.h b/components/password_manager/core/browser/password_manager_test_utils.h
index cb9a95f3..d8b507b 100644
--- a/components/password_manager/core/browser/password_manager_test_utils.h
+++ b/components/password_manager/core/browser/password_manager_test_utils.h
@@ -73,13 +73,6 @@
                                              result_listener->stream());
 }
 
-// Helper function to initialize feature overrides via command-line flags
-// supplied as |enable_features| and |disable_features| using the
-// |feature_list|.
-void SetFeatures(const std::vector<const base::Feature*>& enable_features,
-                 const std::vector<const base::Feature*>& disable_features,
-                 std::unique_ptr<base::FeatureList> feature_list);
-
 class MockPasswordStoreObserver : public PasswordStore::Observer {
  public:
   MockPasswordStoreObserver();
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index b1293663..8c367193 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/password_manager/core/browser/mock_password_store.h"
 #include "components/password_manager/core/browser/password_autofill_manager.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
@@ -125,18 +126,6 @@
 class PasswordManagerTest : public testing::Test {
  protected:
   void SetUp() override {
-    // TODO(jww): The following FeatureList clear can be removed once
-    // https://crbug.com/620435 is resolved. This cleanup is needed because on
-    // some platforms (e.g. iOS), the base::FeatureList is not reset betwen
-    // test runs, so if these unit tests are run right after some other unit
-    // tests that turn on a feature, that might affect these tests. In
-    // particular, the earlier fill-on-account-select unit tests turned on
-    // their respective Feature and that was incorrectly left on for these
-    // tests.
-    base::FeatureList::ClearInstanceForTesting();
-    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    base::FeatureList::SetInstance(std::move(feature_list));
-
     store_ = new testing::StrictMock<MockPasswordStore>;
     EXPECT_CALL(*store_, ReportMetrics(_, _)).Times(AnyNumber());
     CHECK(store_->Init(syncer::SyncableService::StartSyncFlare()));
@@ -1359,11 +1348,9 @@
 
 TEST_F(PasswordManagerTest, ForceSavingPasswords) {
   // Add the enable-password-force-saving feature.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine(
-      password_manager::features::kEnablePasswordForceSaving.name, "");
-  base::FeatureList::SetInstance(std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      features::kEnablePasswordForceSaving);
   PasswordForm form(MakeSimpleForm());
 
   std::vector<PasswordForm> observed;
@@ -1390,11 +1377,9 @@
 // Forcing Chrome to save an empty passwords should fail without a crash.
 TEST_F(PasswordManagerTest, ForceSavingPasswords_Empty) {
   // Add the enable-password-force-saving feature.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine(
-      password_manager::features::kEnablePasswordForceSaving.name, "");
-  base::FeatureList::SetInstance(std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      features::kEnablePasswordForceSaving);
   PasswordForm empty_password_form;
 
   std::vector<PasswordForm> observed;
diff --git a/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc b/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc
index 843fde9..c4eca618 100644
--- a/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc
+++ b/components/password_manager/sync/browser/sync_credentials_filter_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/user_action_tester.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
@@ -138,12 +139,10 @@
 TEST_F(CredentialsFilterTest, FilterResults_DisallowSyncOnReauth) {
   // Only 'protect-sync-credential-on-reauth' feature is kept enabled, fill the
   // sync credential everywhere but on reauth.
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  std::vector<const base::Feature*> enabled_features;
-  std::vector<const base::Feature*> disabled_features;
-  disabled_features.push_back(&features::kProtectSyncCredential);
-  enabled_features.push_back(&features::kProtectSyncCredentialOnReauth);
-  SetFeatures(enabled_features, disabled_features, std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitFromCommandLine(
+      features::kProtectSyncCredentialOnReauth.name,
+      features::kProtectSyncCredential.name);
 
   const TestCase kTestCases[] = {
       // Reauth URL, not sync username.
@@ -184,12 +183,11 @@
 TEST_F(CredentialsFilterTest, FilterResults_DisallowSync) {
   // Both features are kept enabled, should cause sync credential to be
   // filtered.
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  std::vector<const base::Feature*> enabled_features;
-  std::vector<const base::Feature*> disabled_features;
-  enabled_features.push_back(&features::kProtectSyncCredential);
-  enabled_features.push_back(&features::kProtectSyncCredentialOnReauth);
-  SetFeatures(enabled_features, disabled_features, std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitFromCommandLine(
+      features::kProtectSyncCredential.name + std::string(",") +
+          features::kProtectSyncCredentialOnReauth.name,
+      std::string());
 
   const TestCase kTestCases[] = {
       // Reauth URL, not sync username.
@@ -262,12 +260,11 @@
 TEST_F(CredentialsFilterTest, ShouldFilterOneForm) {
   // Both features are kept enabled, should cause sync credential to be
   // filtered.
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  std::vector<const base::Feature*> enabled_features;
-  std::vector<const base::Feature*> disabled_features;
-  enabled_features.push_back(&features::kProtectSyncCredential);
-  enabled_features.push_back(&features::kProtectSyncCredentialOnReauth);
-  SetFeatures(enabled_features, disabled_features, std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitFromCommandLine(
+      features::kProtectSyncCredential.name + std::string(",") +
+          features::kProtectSyncCredentialOnReauth.name,
+      std::string());
 
   ScopedVector<autofill::PasswordForm> results;
   results.push_back(new PasswordForm(SimpleGaiaForm("test1@gmail.com")));
diff --git a/components/ssl_config/BUILD.gn b/components/ssl_config/BUILD.gn
index 54dd47e..b4802a3 100644
--- a/components/ssl_config/BUILD.gn
+++ b/components/ssl_config/BUILD.gn
@@ -30,6 +30,7 @@
   deps = [
     ":ssl_config",
     "//base",
+    "//base/test:test_support",
     "//components/prefs:test_support",
     "//net",
     "//testing/gtest",
diff --git a/components/ssl_config/ssl_config_service_manager_pref_unittest.cc b/components/ssl_config/ssl_config_service_manager_pref_unittest.cc
index ec2aefa5..cecdb8e 100644
--- a/components/ssl_config/ssl_config_service_manager_pref_unittest.cc
+++ b/components/ssl_config/ssl_config_service_manager_pref_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "components/prefs/testing_pref_service.h"
@@ -181,10 +182,8 @@
 // Tests that DHE may be re-enabled via features.
 TEST_F(SSLConfigServiceManagerPrefTest, DHEFeature) {
   // Toggle the feature.
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->InitializeFromCommandLine("DHECiphers", std::string());
-  base::FeatureList::SetInstance(std::move(feature_list));
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitFromCommandLine("DHECiphers", std::string());
 
   TestingPrefServiceSimple local_state;
   SSLConfigServiceManager::RegisterPrefs(local_state.registry());
diff --git a/components/subresource_filter/core/browser/BUILD.gn b/components/subresource_filter/core/browser/BUILD.gn
index 0f4a3f3..eb5cfc7 100644
--- a/components/subresource_filter/core/browser/BUILD.gn
+++ b/components/subresource_filter/core/browser/BUILD.gn
@@ -30,6 +30,7 @@
   deps = [
     ":browser",
     "//base",
+    "//base/test:test_support",
     "//components/variations",
     "//testing/gtest",
   ]
diff --git a/components/subresource_filter/core/browser/ruleset_service.cc b/components/subresource_filter/core/browser/ruleset_service.cc
index 8f81d80b..8ea761a 100644
--- a/components/subresource_filter/core/browser/ruleset_service.cc
+++ b/components/subresource_filter/core/browser/ruleset_service.cc
@@ -230,13 +230,19 @@
   // final segment) gets created. ReplaceFile would not create the path.
   DCHECK(base::PathExists(indexed_ruleset_version_dir.DirName()));
 
-  // This will attempt to overwrite the previously stored ruleset with the same
-  // version, if any. Doing so is needed in case the earlier write was
-  // interrupted, but will fail on Windows in case the earlier write was
-  // successful and the ruleset is in use. We should not normally get to here in
-  // that case, however, due to the same-version check above. Even if we do, the
-  // worst-case scenario is that a slightly-older ruleset version will be used
-  // until next restart/ruleset update.
+  // Need to manually delete the previously stored ruleset with the same
+  // version, if any, as ReplaceFile would not overwrite a non-empty directory.
+  // Due to the same-version check in IndexAndStoreAndPublishRulesetIfNeeded, we
+  // would not normally find a pre-existing copy at this point unless the
+  // previous write was interrupted.
+  //
+  // If there is a _file_ at the target path, do not delete and let ReplaceFile
+  // fail, to allow for error injection in unit tests.
+  if (base::DirectoryExists(indexed_ruleset_version_dir) &&
+      !base::DeleteFile(indexed_ruleset_version_dir, true)) {
+    return WriteRulesetResult::FAILED_DELETE_PREEXISTING;
+  }
+
   base::File::Error error;
   if (!base::ReplaceFile(scratch_dir.path(), indexed_ruleset_version_dir,
                          &error)) {
diff --git a/components/subresource_filter/core/browser/ruleset_service.h b/components/subresource_filter/core/browser/ruleset_service.h
index 3b8d8a0..f8bda06a 100644
--- a/components/subresource_filter/core/browser/ruleset_service.h
+++ b/components/subresource_filter/core/browser/ruleset_service.h
@@ -139,6 +139,7 @@
     FAILED_WRITING_RULESET_DATA,
     FAILED_WRITING_LICENSE,
     FAILED_REPLACE_FILE,
+    FAILED_DELETE_PREEXISTING,
 
     // Insert new values before this line.
     MAX,
@@ -160,12 +161,13 @@
       const base::FilePath& indexed_ruleset_base_dir,
       const UnindexedRulesetInfo& unindexed_ruleset_info);
 
-  // Writes, atomically, all files comprising the given |indexed_version| of the
-  // ruleset into the corresponding subdirectory in |indexed_ruleset_base_dir|.
+  // Writes all files comprising the given |indexed_version| of the ruleset
+  // into the corresponding subdirectory in |indexed_ruleset_base_dir|.
   // More specifically, it writes:
   //  -- the |indexed_ruleset_data| of the given |indexed_ruleset_size|,
   //  -- a copy of the LICENSE file at |license_path|, if exists.
   // Returns true on success. To be called on the |blocking_task_runner_|.
+  // Attempts not to leave an incomplete copy in the target directory.
   //
   // Writing is factored out into this separate function so it can be
   // independently exercised in tests.
diff --git a/components/subresource_filter/core/browser/ruleset_service_unittest.cc b/components/subresource_filter/core/browser/ruleset_service_unittest.cc
index fdb3e25..dc019c5 100644
--- a/components/subresource_filter/core/browser/ruleset_service_unittest.cc
+++ b/components/subresource_filter/core/browser/ruleset_service_unittest.cc
@@ -377,6 +377,34 @@
       test_ruleset_1().indexed.contents));
 }
 
+// Test the scenario where a faulty copy of the ruleset resides on disk, that
+// is, when there is something in the directory corresponding to a ruleset
+// version, but preferences do not indicate that a valid copy of that version is
+// stored. The expectation is that the directory is overwritten with a correct
+// contents when the same version of the ruleset is fed to the service again.
+TEST_F(SubresourceFilteringRulesetServiceTest,
+       NewRuleset_OverwritesBadCopyOfSameVersionOnDisk) {
+  // Emulate a bad ruleset by writing |test_ruleset_2| into the directory
+  // corresponding to |test_ruleset_1| and not updating prefs.
+  IndexedRulesetVersion same_version_but_incomplete(
+      kTestContentVersion1, IndexedRulesetVersion::CurrentFormatVersion());
+  WriteRuleset(test_ruleset_2(), same_version_but_incomplete);
+
+  IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
+  RunUntilIdle();
+
+  IndexedRulesetVersion stored_version;
+  stored_version.ReadFromPrefs(prefs());
+  EXPECT_EQ(kTestContentVersion1, stored_version.content_version);
+  EXPECT_EQ(IndexedRulesetVersion::CurrentFormatVersion(),
+            stored_version.format_version);
+
+  ASSERT_EQ(1u, mock_distributor()->published_rulesets().size());
+  ASSERT_NO_FATAL_FAILURE(AssertValidRulesetFileWithContents(
+      &mock_distributor()->published_rulesets()[0],
+      test_ruleset_1().indexed.contents));
+}
+
 TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_HistogramsOnSuccess) {
   base::HistogramTester histogram_tester;
   IndexAndStoreAndPublishUpdatedRuleset(test_ruleset_1(), kTestContentVersion1);
@@ -390,8 +418,8 @@
 
 TEST_F(SubresourceFilteringRulesetServiceTest, NewRuleset_HistogramsOnFailure) {
   // Create a file in place of where the version directory is supposed to go.
-  // This makes base::ReplaceFile fail on all platforms, and without interfering
-  // with clean-up even if the test was interrupted.
+  // This makes WriteRuleset fail on all platforms, without interfering with
+  // after-test clean-up.
   IndexedRulesetVersion indexed_version(
       kTestContentVersion1, IndexedRulesetVersion::CurrentFormatVersion());
   base::FilePath version_dir =
diff --git a/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc b/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc
index 87dd1a0..9977326 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc
+++ b/components/subresource_filter/core/browser/subresource_filter_features_test_support.cc
@@ -24,7 +24,6 @@
     base::FeatureList::OverrideState feature_state,
     const std::string& maximum_activation_state,
     const std::string& activation_scope) {
-  base::FeatureList::ClearInstanceForTesting();
   variations::testing::ClearAllVariationParams();
 
   std::map<std::string, std::string> variation_params;
@@ -39,12 +38,11 @@
   std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
   feature_list->RegisterFieldTrialOverride(kSafeBrowsingSubresourceFilter.name,
                                            feature_state, field_trial);
-  base::FeatureList::SetInstance(std::move(feature_list));
+  scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
 }
 
 ScopedSubresourceFilterFeatureToggle::~ScopedSubresourceFilterFeatureToggle() {
   variations::testing::ClearAllVariationParams();
-  base::FeatureList::ClearInstanceForTesting();
 }
 
 }  // namespace testing
diff --git a/components/subresource_filter/core/browser/subresource_filter_features_test_support.h b/components/subresource_filter/core/browser/subresource_filter_features_test_support.h
index eedc83c..6ef97f2 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features_test_support.h
+++ b/components/subresource_filter/core/browser/subresource_filter_features_test_support.h
@@ -9,6 +9,7 @@
 
 #include "base/feature_list.h"
 #include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
 
 namespace subresource_filter {
 namespace testing {
@@ -25,6 +26,8 @@
   ~ScopedSubresourceFilterFeatureToggle();
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   DISALLOW_COPY_AND_ASSIGN(ScopedSubresourceFilterFeatureToggle);
 };
 
diff --git a/components/translate/core/browser/translate_prefs_unittest.cc b/components/translate/core/browser/translate_prefs_unittest.cc
index 881718d..5d77a33 100644
--- a/components/translate/core/browser/translate_prefs_unittest.cc
+++ b/components/translate/core/browser/translate_prefs_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "components/pref_registry/testing_pref_service_syncable.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -50,19 +51,11 @@
     return update.GetOldestDenialTime();
   }
 
-  void SetUp() override {
-    base::FeatureList::ClearInstanceForTesting();
-    base::FeatureList::SetInstance(base::WrapUnique(new base::FeatureList()));
-  }
-
   void TurnOnTranslate2016Q2UIFlag() {
-    base::FeatureList::ClearInstanceForTesting();
-    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    feature_list->InitializeFromCommandLine(translate::kTranslateUI2016Q2.name,
-                                            std::string());
-    base::FeatureList::SetInstance(std::move(feature_list));
+    scoped_feature_list_.InitAndEnableFeature(translate::kTranslateUI2016Q2);
   }
 
+  base::test::ScopedFeatureList scoped_feature_list_;
   std::unique_ptr<user_prefs::TestingPrefServiceSyncable> prefs_;
   std::unique_ptr<translate::TranslatePrefs> translate_prefs_;
 
diff --git a/components/translate/core/browser/translate_ui_delegate_unittest.cc b/components/translate/core/browser/translate_ui_delegate_unittest.cc
index 415f67d..a24b88e 100644
--- a/components/translate/core/browser/translate_ui_delegate_unittest.cc
+++ b/components/translate/core/browser/translate_ui_delegate_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "components/infobars/core/infobar.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -93,16 +94,10 @@
         new TranslateUIDelegate(manager_->GetWeakPtr(), "ar", "fr"));
 
     ASSERT_FALSE(client_->GetTranslatePrefs()->IsTooOftenDenied("ar"));
-    base::FeatureList::ClearInstanceForTesting();
-    base::FeatureList::SetInstance(base::WrapUnique(new base::FeatureList));
   }
 
   void TurnOnTranslate2016Q2UIFlag() {
-    base::FeatureList::ClearInstanceForTesting();
-    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-    feature_list->InitializeFromCommandLine(translate::kTranslateUI2016Q2.name,
-                                            std::string());
-    base::FeatureList::SetInstance(std::move(feature_list));
+    scoped_feature_list_.InitAndEnableFeature(translate::kTranslateUI2016Q2);
   }
 
   MockTranslateDriver driver_;
@@ -110,6 +105,7 @@
   std::unique_ptr<user_prefs::TestingPrefServiceSyncable> pref_service_;
   std::unique_ptr<TranslateManager> manager_;
   std::unique_ptr<TranslateUIDelegate> delegate_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TranslateUIDelegateTest);
diff --git a/components/variations/service/variations_service_unittest.cc b/components/variations/service/variations_service_unittest.cc
index 6abfc8a..6530849 100644
--- a/components/variations/service/variations_service_unittest.cc
+++ b/components/variations/service/variations_service_unittest.cc
@@ -272,10 +272,6 @@
   TestingPrefServiceSimple prefs;
   VariationsService::RegisterPrefs(prefs.registry());
 
-  // Setup base::FeatureList.
-  base::FeatureList::ClearInstanceForTesting();
-  base::FeatureList::SetInstance(base::WrapUnique(new base::FeatureList()));
-
   // Create a local base::FieldTrialList, to hold the field trials created in
   // this test.
   base::FieldTrialList field_trial_list(nullptr);
@@ -303,10 +299,6 @@
   TestingPrefServiceSimple prefs;
   VariationsService::RegisterPrefs(prefs.registry());
 
-  // Setup base::FeatureList.
-  base::FeatureList::ClearInstanceForTesting();
-  base::FeatureList::SetInstance(base::WrapUnique(new base::FeatureList()));
-
   // Create a local base::FieldTrialList, to hold the field trials created in
   // this test.
   base::FieldTrialList field_trial_list(nullptr);
@@ -334,10 +326,6 @@
   TestingPrefServiceSimple prefs;
   VariationsService::RegisterPrefs(prefs.registry());
 
-  // Setup base::FeatureList.
-  base::FeatureList::ClearInstanceForTesting();
-  base::FeatureList::SetInstance(base::WrapUnique(new base::FeatureList()));
-
   // Create a local base::FieldTrialList, to hold the field trials created in
   // this test.
   base::FieldTrialList field_trial_list(nullptr);
diff --git a/components/variations/variations_associated_data_unittest.cc b/components/variations/variations_associated_data_unittest.cc
index 05cdece..5bdd1d84 100644
--- a/components/variations/variations_associated_data_unittest.cc
+++ b/components/variations/variations_associated_data_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/metrics/field_trial.h"
+#include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace variations {
@@ -34,16 +35,6 @@
       base::FieldTrial::SESSION_RANDOMIZED, default_group_number);
 }
 
-void CreateFeatureWithTrial(const base::Feature& feature,
-                            base::FeatureList::OverrideState override_state,
-                            base::FieldTrial* trial) {
-  base::FeatureList::ClearInstanceForTesting();
-  std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-  feature_list->RegisterFieldTrialOverride(feature.name, override_state,
-                                           trial);
-  base::FeatureList::SetInstance(std::move(feature_list));
-}
-
 }  // namespace
 
 class VariationsAssociatedDataTest : public ::testing::Test {
@@ -58,8 +49,18 @@
     testing::ClearAllVariationParams();
   }
 
+  void CreateFeatureWithTrial(const base::Feature& feature,
+                              base::FeatureList::OverrideState override_state,
+                              base::FieldTrial* trial) {
+    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+    feature_list->RegisterFieldTrialOverride(feature.name, override_state,
+                                             trial);
+    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
+  }
+
  private:
   base::FieldTrialList field_trial_list_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
   DISALLOW_COPY_AND_ASSIGN(VariationsAssociatedDataTest);
 };
diff --git a/components/variations/variations_seed_processor_unittest.cc b/components/variations/variations_seed_processor_unittest.cc
index 1ab8a49..d1e9967 100644
--- a/components/variations/variations_seed_processor_unittest.cc
+++ b/components/variations/variations_seed_processor_unittest.cc
@@ -21,6 +21,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/mock_entropy_provider.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/variations/processed_study.h"
 #include "components/variations/study_filtering.h"
 #include "components/variations/variations_associated_data.h"
@@ -117,8 +118,6 @@
     // process singletons.
     testing::ClearAllVariationIDs();
     testing::ClearAllVariationParams();
-
-    base::FeatureList::ClearInstanceForTesting();
   }
 
   bool CreateTrialFromStudy(const Study& study) {
@@ -621,7 +620,6 @@
     SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
 
     base::FieldTrialList field_trial_list(nullptr);
-    base::FeatureList::ClearInstanceForTesting();
     std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
 
     Study study;
@@ -638,7 +636,8 @@
       association->add_disable_feature(test_case.disable_feature);
 
     EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get()));
-    base::FeatureList::SetInstance(std::move(feature_list));
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitWithFeatureList(std::move(feature_list));
 
     // |kUnrelatedFeature| should not be affected.
     EXPECT_FALSE(base::FeatureList::IsEnabled(kUnrelatedFeature));
@@ -744,7 +743,6 @@
         test_case.disable_features_command_line, static_cast<int>(group)));
 
     base::FieldTrialList field_trial_list(nullptr);
-    base::FeatureList::ClearInstanceForTesting();
     std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
     feature_list->InitializeFromCommandLine(
         test_case.enable_features_command_line,
@@ -773,7 +771,8 @@
         ->set_forcing_feature_off(test_case.feature.name);
 
     EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get()));
-    base::FeatureList::SetInstance(std::move(feature_list));
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitWithFeatureList(std::move(feature_list));
 
     // Trial should not be activated initially, but later might get activated
     // depending on the expected values.
@@ -814,7 +813,6 @@
         base::StringPrintf("Test[%" PRIuS "]: %s", i, test_case.feature.name));
 
     base::FieldTrialList field_trial_list(nullptr);
-    base::FeatureList::ClearInstanceForTesting();
     std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
     feature_list->InitializeFromCommandLine(std::string(), std::string());
 
@@ -837,7 +835,8 @@
     }
 
     EXPECT_TRUE(CreateTrialFromStudyWithFeatureList(study, feature_list.get()));
-    base::FeatureList::SetInstance(std::move(feature_list));
+    base::test::ScopedFeatureList scoped_feature_list;
+    scoped_feature_list.InitWithFeatureList(std::move(feature_list));
 
     // Tthe feature should not be enabled, because the study is expired.
     EXPECT_EQ(test_case.expected_feature_enabled,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index e0bc7d1..7aaafd9 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -392,9 +392,6 @@
       "web_contents/web_contents_view_mus.cc",
       "web_contents/web_contents_view_mus.h",
     ]
-    if (toolkit_views) {
-      defines += [ "MOJO_RUNNER_CLIENT" ]
-    }
   } else {  # Not aura.
     sources -= [
       "media/capture/cursor_renderer_aura.cc",
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 6744c6a..71a74b0d 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -110,6 +110,7 @@
 #include "content/browser/android/browser_surface_texture_manager.h"
 #include "content/browser/android/tracing_controller_android.h"
 #include "content/browser/media/android/browser_media_player_manager.h"
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
 #include "content/browser/screen_orientation/screen_orientation_delegate_android.h"
 #include "content/public/browser/screen_orientation_provider.h"
 #include "gpu/ipc/client/android/in_process_surface_texture_manager.h"
@@ -972,6 +973,7 @@
 
 #if defined(OS_ANDROID)
   g_browser_main_loop_shutting_down = true;
+  ui::ContextProviderFactory::SetInstance(nullptr);
 #endif
 
   if (RenderProcessHost::run_renderer_in_process())
@@ -1120,7 +1122,7 @@
   }
   // Must happen after the IO thread is shutdown since this may be accessed from
   // it.
-  if (!shell::ShellIsRemote()) {
+  {
     TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUChannelFactory");
     if (BrowserGpuChannelHostFactory::instance())
       BrowserGpuChannelHostFactory::Terminate();
@@ -1204,6 +1206,8 @@
   established_gpu_channel = false;
   always_uses_gpu = ShouldStartGpuProcessOnBrowserStartup();
   BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
+  ui::ContextProviderFactory::SetInstance(
+      ContextProviderFactoryImpl::GetInstance());
 #elif defined(USE_AURA) || defined(OS_MACOSX)
   established_gpu_channel = true;
   if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor() ||
@@ -1213,6 +1217,13 @@
   }
   BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
   ImageTransportFactory::Initialize();
+
+  gpu::GpuChannelEstablishFactory* factory =
+      GetContentClient()->browser()->GetGpuChannelEstablishFactory();
+  if (!factory)
+    factory = BrowserGpuChannelHostFactory::instance();
+  DCHECK(factory);
+  ImageTransportFactory::GetInstance()->SetGpuChannelEstablishFactory(factory);
 #if defined(USE_AURA)
   bool use_mus_in_renderer = base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kUseMusInRenderer);
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 0a2423a..8511ff2d 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -39,7 +39,6 @@
 #include "content/browser/compositor/reflector_impl.h"
 #include "content/browser/compositor/software_browser_compositor_output_surface.h"
 #include "content/browser/compositor/software_output_device_mus.h"
-#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -51,6 +50,7 @@
 #include "gpu/command_buffer/client/shared_memory_limits.h"
 #include "gpu/command_buffer/common/mailbox.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
+#include "services/shell/runner/common/client_util.h"
 #include "third_party/khronos/GLES2/gl2.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_constants.h"
@@ -58,10 +58,9 @@
 #include "ui/compositor/layer.h"
 #include "ui/gfx/geometry/size.h"
 
-#if defined(MOJO_RUNNER_CLIENT)
+#if defined(USE_AURA)
 #include "content/browser/compositor/mus_browser_compositor_output_surface.h"
 #include "content/public/common/mojo_shell_connection.h"
-#include "services/shell/runner/common/client_util.h"
 #include "services/ui/common/gpu_service.h"
 #endif
 
@@ -104,11 +103,7 @@
 const int kNumRetriesBeforeSoftwareFallback = 4;
 
 bool IsUsingMus() {
-#if defined(MOJO_RUNNER_CLIENT)
   return shell::ShellIsRemote();
-#else
-  return false;
-#endif
 }
 
 scoped_refptr<content::ContextProviderCommandBuffer> CreateContextCommon(
@@ -205,7 +200,7 @@
 std::unique_ptr<cc::SoftwareOutputDevice>
 GpuProcessTransportFactory::CreateSoftwareOutputDevice(
     ui::Compositor* compositor) {
-#if defined(MOJO_RUNNER_CLIENT)
+#if defined(USE_AURA)
   if (shell::ShellIsRemote()) {
     return std::unique_ptr<cc::SoftwareOutputDevice>(
         new SoftwareOutputDeviceMus(compositor));
@@ -302,32 +297,25 @@
 #endif
 
   const bool use_vulkan = static_cast<bool>(SharedVulkanContextProvider());
-  const bool use_mus = IsUsingMus();
   const bool create_gpu_output_surface =
       ShouldCreateGpuOutputSurface(compositor.get());
   if (create_gpu_output_surface && !use_vulkan) {
-    base::Closure callback(
+    gpu::GpuChannelEstablishedCallback callback(
         base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel,
                    callback_factory_.GetWeakPtr(), compositor,
                    create_gpu_output_surface, 0));
-    if (!use_mus) {
-      BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(callback);
-    } else {
-#if defined(MOJO_RUNNER_CLIENT)
-      ui::GpuService::GetInstance()->EstablishGpuChannel(callback);
-#else
-      NOTREACHED();
-#endif
-    }
+    DCHECK(gpu_channel_factory_);
+    gpu_channel_factory_->EstablishGpuChannel(callback);
   } else {
-    EstablishedGpuChannel(compositor, create_gpu_output_surface, 0);
+    EstablishedGpuChannel(compositor, create_gpu_output_surface, 0, nullptr);
   }
 }
 
 void GpuProcessTransportFactory::EstablishedGpuChannel(
     base::WeakPtr<ui::Compositor> compositor,
     bool create_gpu_output_surface,
-    int num_attempts) {
+    int num_attempts,
+    scoped_refptr<gpu::GpuChannelHost> established_channel_host) {
   if (!compositor)
     return;
 
@@ -355,7 +343,6 @@
 
   scoped_refptr<cc::VulkanInProcessContextProvider> vulkan_context_provider =
       SharedVulkanContextProvider();
-  const bool use_mus = IsUsingMus();
   scoped_refptr<ContextProviderCommandBuffer> context_provider;
   if (create_gpu_output_surface && !vulkan_context_provider) {
     // Try to reuse existing worker context provider.
@@ -373,20 +360,8 @@
     }
 
     scoped_refptr<gpu::GpuChannelHost> gpu_channel_host;
-    if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
-      // We attempted to do EstablishGpuChannel already, so we just use
-      // GetGpuChannel() instead of EstablishGpuChannelSync().
-      if (!use_mus) {
-        gpu_channel_host =
-            BrowserGpuChannelHostFactory::instance()->GetGpuChannel();
-      } else {
-#if defined(MOJO_RUNNER_CLIENT)
-        gpu_channel_host = ui::GpuService::GetInstance()->GetGpuChannel();
-#else
-        NOTREACHED();
-#endif
-      }
-    }
+    if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
+      gpu_channel_host = std::move(established_channel_host);
 
     if (!gpu_channel_host) {
       shared_worker_context_provider_ = nullptr;
@@ -451,19 +426,12 @@
 
     if (!created_gpu_browser_compositor) {
       // Try again.
-      base::Closure callback(
+      gpu::GpuChannelEstablishedCallback callback(
           base::Bind(&GpuProcessTransportFactory::EstablishedGpuChannel,
                      callback_factory_.GetWeakPtr(), compositor,
                      create_gpu_output_surface, num_attempts + 1));
-      if (!use_mus) {
-        BrowserGpuChannelHostFactory::instance()->EstablishGpuChannel(callback);
-      } else {
-#if defined(MOJO_RUNNER_CLIENT)
-        ui::GpuService::GetInstance()->EstablishGpuChannel(callback);
-#else
-        NOTREACHED();
-#endif
-      }
+      DCHECK(gpu_channel_factory_);
+      gpu_channel_factory_->EstablishGpuChannel(callback);
       return;
     }
   }
@@ -530,6 +498,7 @@
       } else {
         std::unique_ptr<display_compositor::CompositorOverlayCandidateValidator>
             validator;
+        const bool use_mus = IsUsingMus();
 #if !defined(OS_MACOSX)
         // Overlays are only supported on surfaceless output surfaces on Mac.
         if (!use_mus)
@@ -541,7 +510,7 @@
                   context_provider, compositor->vsync_manager(),
                   begin_frame_source.get(), std::move(validator)));
         } else {
-#if defined(MOJO_RUNNER_CLIENT)
+#if defined(USE_AURA)
           display_output_surface =
               base::WrapUnique(new MusBrowserCompositorOutputSurface(
                   data->surface_handle, context_provider,
@@ -772,6 +741,12 @@
   return gl_helper_.get();
 }
 
+void GpuProcessTransportFactory::SetGpuChannelEstablishFactory(
+    gpu::GpuChannelEstablishFactory* factory) {
+  DCHECK(!gpu_channel_factory_ || !factory);
+  gpu_channel_factory_ = factory;
+}
+
 #if defined(OS_MACOSX)
 void GpuProcessTransportFactory::SetCompositorSuspendedForRecycle(
     ui::Compositor* compositor,
@@ -794,19 +769,9 @@
   if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
     return nullptr;
 
-  const bool use_mus = IsUsingMus();
-  scoped_refptr<gpu::GpuChannelHost> gpu_channel_host;
-  if (!use_mus) {
-    gpu_channel_host =
-        BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync();
-  } else {
-#if defined(MOJO_RUNNER_CLIENT)
-    gpu_channel_host = ui::GpuService::GetInstance()->EstablishGpuChannelSync();
-#else
-    NOTREACHED();
-#endif
-  }
-
+  DCHECK(gpu_channel_factory_);
+  scoped_refptr<gpu::GpuChannelHost> gpu_channel_host =
+      gpu_channel_factory_->EstablishGpuChannelSync();
   if (!gpu_channel_host)
     return nullptr;
 
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h
index de913bc..2f960d3 100644
--- a/content/browser/compositor/gpu_process_transport_factory.h
+++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -79,6 +79,8 @@
   ui::ContextFactory* GetContextFactory() override;
   cc::SurfaceManager* GetSurfaceManager() override;
   display_compositor::GLHelper* GetGLHelper() override;
+  void SetGpuChannelEstablishFactory(
+      gpu::GpuChannelEstablishFactory* factory) override;
 #if defined(OS_MACOSX)
   void SetCompositorSuspendedForRecycle(ui::Compositor* compositor,
                                         bool suspended) override;
@@ -90,9 +92,11 @@
   PerCompositorData* CreatePerCompositorData(ui::Compositor* compositor);
   std::unique_ptr<cc::SoftwareOutputDevice> CreateSoftwareOutputDevice(
       ui::Compositor* compositor);
-  void EstablishedGpuChannel(base::WeakPtr<ui::Compositor> compositor,
-                             bool create_gpu_output_surface,
-                             int num_attempts);
+  void EstablishedGpuChannel(
+      base::WeakPtr<ui::Compositor> compositor,
+      bool create_gpu_output_surface,
+      int num_attempts,
+      scoped_refptr<gpu::GpuChannelHost> established_channel_host);
 
   void OnLostMainThreadSharedContextInsideCallback();
   void OnLostMainThreadSharedContext();
@@ -114,6 +118,8 @@
   scoped_refptr<cc::VulkanInProcessContextProvider>
       shared_vulkan_context_provider_;
 
+  gpu::GpuChannelEstablishFactory* gpu_channel_factory_ = nullptr;
+
 #if defined(OS_WIN)
   std::unique_ptr<OutputDeviceBacking> software_backing_;
 #endif
diff --git a/content/browser/compositor/image_transport_factory.h b/content/browser/compositor/image_transport_factory.h
index 376e240..aa67205 100644
--- a/content/browser/compositor/image_transport_factory.h
+++ b/content/browser/compositor/image_transport_factory.h
@@ -36,6 +36,10 @@
 class GLHelper;
 }
 
+namespace gpu {
+class GpuChannelEstablishFactory;
+}
+
 namespace content {
 
 // This class provides the interface for creating the support for the
@@ -70,6 +74,9 @@
   // (ImageTransportFactoryObserver::OnLostResources is called).
   virtual display_compositor::GLHelper* GetGLHelper() = 0;
 
+  virtual void SetGpuChannelEstablishFactory(
+      gpu::GpuChannelEstablishFactory* factory) = 0;
+
 #if defined(OS_MACOSX)
   // Called with |suspended| as true when the ui::Compositor has been
   // disconnected from an NSView and may be attached to another one. Called
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc
index 507c063..d9e51184 100644
--- a/content/browser/compositor/surface_utils.cc
+++ b/content/browser/compositor/surface_utils.cc
@@ -19,7 +19,7 @@
 #include "ui/gfx/geometry/rect.h"
 
 #if defined(OS_ANDROID)
-#include "content/browser/renderer_host/compositor_impl_android.h"
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
 #else
 #include "content/browser/compositor/image_transport_factory.h"
 #include "ui/compositor/compositor.h"  // nogncheck
@@ -160,7 +160,7 @@
 
 uint32_t AllocateSurfaceClientId() {
 #if defined(OS_ANDROID)
-  return CompositorImpl::AllocateSurfaceClientId();
+  return ContextProviderFactoryImpl::GetInstance()->AllocateSurfaceClientId();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
   return factory->GetContextFactory()->AllocateSurfaceClientId();
@@ -169,7 +169,7 @@
 
 cc::SurfaceManager* GetSurfaceManager() {
 #if defined(OS_ANDROID)
-  return CompositorImpl::GetSurfaceManager();
+  return ContextProviderFactoryImpl::GetInstance()->GetSurfaceManager();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
   if (factory == NULL)
diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.cc b/content/browser/compositor/test/no_transport_image_transport_factory.cc
index 7d4def7..86ce0cbb 100644
--- a/content/browser/compositor/test/no_transport_image_transport_factory.cc
+++ b/content/browser/compositor/test/no_transport_image_transport_factory.cc
@@ -46,4 +46,7 @@
   return gl_helper_.get();
 }
 
+void NoTransportImageTransportFactory::SetGpuChannelEstablishFactory(
+    gpu::GpuChannelEstablishFactory* factory) {}
+
 }  // namespace content
diff --git a/content/browser/compositor/test/no_transport_image_transport_factory.h b/content/browser/compositor/test/no_transport_image_transport_factory.h
index c6de81d..0f31aec 100644
--- a/content/browser/compositor/test/no_transport_image_transport_factory.h
+++ b/content/browser/compositor/test/no_transport_image_transport_factory.h
@@ -31,6 +31,8 @@
   ui::ContextFactory* GetContextFactory() override;
   cc::SurfaceManager* GetSurfaceManager() override;
   display_compositor::GLHelper* GetGLHelper() override;
+  void SetGpuChannelEstablishFactory(
+      gpu::GpuChannelEstablishFactory* factory) override;
 #if defined(OS_MACOSX)
   void SetCompositorSuspendedForRecycle(ui::Compositor* compositor,
                                         bool suspended) override {}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 1a55641..68ec2156 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -787,7 +787,7 @@
     const shell::Identity& remote_identity,
     media::mojom::ServiceFactoryRequest request) {
   std::unique_ptr<shell::InterfaceRegistry> registry(
-      new shell::InterfaceRegistry(nullptr));
+      new shell::InterfaceRegistry);
 #if defined(OS_ANDROID) && defined(ENABLE_MOJO_CDM)
   registry->AddInterface(
       base::Bind(&ProvisionFetcherImpl::Create, this));
@@ -2467,7 +2467,7 @@
   if (interface_registry_.get())
     return;
 
-  interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+  interface_registry_.reset(new shell::InterfaceRegistry);
   if (!GetProcess()->GetRemoteInterfaces())
     return;
 
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
index 6821e3d..0ed06c3 100644
--- a/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -30,6 +30,10 @@
 #include "content/test/test_render_view_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
+#endif
+
 namespace content {
 namespace {
 class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
@@ -80,6 +84,9 @@
 #if !defined(OS_ANDROID)
     ImageTransportFactory::InitializeForUnitTests(
         base::WrapUnique(new NoTransportImageTransportFactory));
+#else
+    ui::ContextProviderFactory::SetInstance(
+        ContextProviderFactoryImpl::GetInstance());
 #endif
 
     MockRenderProcessHost* process_host =
@@ -106,6 +113,8 @@
     base::RunLoop().RunUntilIdle();
 #if !defined(OS_ANDROID)
     ImageTransportFactory::Terminate();
+#else
+    ui::ContextProviderFactory::SetInstance(nullptr);
 #endif
   }
 
diff --git a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index 47e457cb..e0a34e8 100644
--- a/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -30,6 +30,10 @@
 #include "content/test/test_web_contents.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
+#endif
+
 namespace content {
 namespace {
 class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
@@ -54,6 +58,9 @@
     ImageTransportFactory::InitializeForUnitTests(
         std::unique_ptr<ImageTransportFactory>(
             new NoTransportImageTransportFactory));
+#else
+    ui::ContextProviderFactory::SetInstance(
+        ContextProviderFactoryImpl::GetInstance());
 #endif
     browser_context_.reset(new TestBrowserContext);
     MockRenderProcessHost* process_host =
@@ -78,6 +85,8 @@
     message_loop_.RunUntilIdle();
 #if !defined(OS_ANDROID)
     ImageTransportFactory::Terminate();
+#else
+    ui::ContextProviderFactory::SetInstance(nullptr);
 #endif
   }
 
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index d3e8ceba..345ad2a 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -28,10 +28,7 @@
 #include "gpu/ipc/common/gpu_messages.h"
 #include "ipc/ipc_channel_handle.h"
 #include "ipc/message_filter.h"
-
-#if defined(MOJO_RUNNER_CLIENT)
 #include "services/shell/runner/common/client_util.h"
-#endif
 
 namespace content {
 
@@ -209,7 +206,7 @@
   DCHECK(!instance_);
   instance_ = new BrowserGpuChannelHostFactory();
   if (establish_gpu_channel) {
-    instance_->EstablishGpuChannel(base::Closure());
+    instance_->EstablishGpuChannel(gpu::GpuChannelEstablishedCallback());
   }
 }
 
@@ -249,7 +246,7 @@
   if (pending_request_.get())
     pending_request_->Cancel();
   for (size_t n = 0; n < established_callbacks_.size(); n++)
-    established_callbacks_[n].Run();
+    established_callbacks_[n].Run(nullptr);
   shutdown_event_->Signal();
   if (gpu_channel_) {
     gpu_channel_->DestroyChannel();
@@ -274,26 +271,9 @@
   return shm;
 }
 
-// Blocking the UI thread to open a GPU channel is not supported on Android.
-// (Opening the initial channel to a child process involves handling a reply
-// task on the UI thread first, so we cannot block here.)
-#if !defined(OS_ANDROID)
-scoped_refptr<gpu::GpuChannelHost>
-BrowserGpuChannelHostFactory::EstablishGpuChannelSync() {
-  EstablishGpuChannel(base::Closure());
-
-  if (pending_request_.get())
-    pending_request_->Wait();
-
-  return gpu_channel_;
-}
-#endif
-
 void BrowserGpuChannelHostFactory::EstablishGpuChannel(
-    const base::Closure& callback) {
-#if defined(MOJO_RUNNER_CLIENT)
+    const gpu::GpuChannelEstablishedCallback& callback) {
   DCHECK(!shell::ShellIsRemote());
-#endif
   if (gpu_channel_.get() && gpu_channel_->IsLost()) {
     DCHECK(!pending_request_.get());
     // Recreate the channel if it has been lost.
@@ -309,12 +289,29 @@
 
   if (!callback.is_null()) {
     if (gpu_channel_.get())
-      callback.Run();
+      callback.Run(gpu_channel_);
     else
       established_callbacks_.push_back(callback);
   }
 }
 
+// Blocking the UI thread to open a GPU channel is not supported on Android.
+// (Opening the initial channel to a child process involves handling a reply
+// task on the UI thread first, so we cannot block here.)
+scoped_refptr<gpu::GpuChannelHost>
+BrowserGpuChannelHostFactory::EstablishGpuChannelSync() {
+#if defined(OS_ANDROID)
+  NOTREACHED();
+  return nullptr;
+#endif
+  EstablishGpuChannel(gpu::GpuChannelEstablishedCallback());
+
+  if (pending_request_.get())
+    pending_request_->Wait();
+
+  return gpu_channel_;
+}
+
 gpu::GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
   if (gpu_channel_.get() && !gpu_channel_->IsLost())
     return gpu_channel_.get();
@@ -349,7 +346,7 @@
           "466866 BrowserGpuChannelHostFactory::GpuChannelEstablished2"));
 
   for (size_t n = 0; n < established_callbacks_.size(); n++)
-    established_callbacks_[n].Run();
+    established_callbacks_[n].Run(gpu_channel_);
 
   established_callbacks_.clear();
 }
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h
index aaf7f09..759f936a 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -23,7 +23,8 @@
 class BrowserGpuMemoryBufferManager;
 
 class CONTENT_EXPORT BrowserGpuChannelHostFactory
-    : public gpu::GpuChannelHostFactory {
+    : public gpu::GpuChannelHostFactory,
+      public gpu::GpuChannelEstablishFactory {
  public:
   static void Initialize(bool establish_gpu_channel);
   static void Terminate();
@@ -36,16 +37,17 @@
       size_t size) override;
 
   int GpuProcessHostId() { return gpu_host_id_; }
-#if !defined(OS_ANDROID)
-  scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync();
-#endif
-  void EstablishGpuChannel(const base::Closure& callback);
   gpu::GpuChannelHost* GetGpuChannel();
   int GetGpuChannelId() { return gpu_client_id_; }
 
   // Used to skip GpuChannelHost tests when there can be no GPU process.
   static bool CanUseForTesting();
 
+  // Overridden from gpu::GpuChannelEstablishFactory:
+  void EstablishGpuChannel(
+      const gpu::GpuChannelEstablishedCallback& callback) override;
+  scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync() override;
+
  private:
   struct CreateRequest;
   class EstablishRequest;
@@ -67,7 +69,7 @@
   std::unique_ptr<BrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_;
   int gpu_host_id_;
   scoped_refptr<EstablishRequest> pending_request_;
-  std::vector<base::Closure> established_callbacks_;
+  std::vector<gpu::GpuChannelEstablishedCallback> established_callbacks_;
 
   static BrowserGpuChannelHostFactory* instance_;
 
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc
index 3982823..7394f6d3 100644
--- a/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -6,6 +6,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "build/build_config.h"
+#include "content/browser/compositor/image_transport_factory.h"
 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
@@ -40,6 +41,39 @@
       nullptr, content::command_buffer_metrics::OFFSCREEN_CONTEXT_FOR_TESTING));
 }
 
+void OnEstablishedGpuChannel(
+    const base::Closure& quit_closure,
+    scoped_refptr<gpu::GpuChannelHost>* retvalue,
+    scoped_refptr<gpu::GpuChannelHost> established_host) {
+  if (retvalue)
+    *retvalue = std::move(established_host);
+  quit_closure.Run();
+}
+
+class EstablishGpuChannelHelper {
+ public:
+  EstablishGpuChannelHelper() {}
+  ~EstablishGpuChannelHelper() {}
+
+  scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSyncRunLoop() {
+    if (!content::BrowserGpuChannelHostFactory::instance())
+      content::BrowserGpuChannelHostFactory::Initialize(true);
+
+    content::BrowserGpuChannelHostFactory* factory =
+        content::BrowserGpuChannelHostFactory::instance();
+    CHECK(factory);
+    base::RunLoop run_loop;
+    factory->EstablishGpuChannel(base::Bind(
+        &OnEstablishedGpuChannel, run_loop.QuitClosure(), &gpu_channel_host_));
+    run_loop.Run();
+    return std::move(gpu_channel_host_);
+  }
+
+ private:
+  scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_;
+  DISALLOW_COPY_AND_ASSIGN(EstablishGpuChannelHelper);
+};
+
 class ContextTestBase : public content::ContentBrowserTest {
  public:
   void SetUpOnMainThread() override {
@@ -48,17 +82,9 @@
     if (!content::BrowserGpuChannelHostFactory::CanUseForTesting())
       return;
 
-    if (!content::BrowserGpuChannelHostFactory::instance())
-      content::BrowserGpuChannelHostFactory::Initialize(true);
-
-    content::BrowserGpuChannelHostFactory* factory =
-        content::BrowserGpuChannelHostFactory::instance();
-    CHECK(factory);
-    base::RunLoop run_loop;
-    factory->EstablishGpuChannel(run_loop.QuitClosure());
-    run_loop.Run();
-    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
-        factory->GetGpuChannel());
+    EstablishGpuChannelHelper helper;
+    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host =
+        helper.EstablishGpuChannelSyncRunLoop();
     CHECK(gpu_channel_host);
 
     provider_ = CreateContext(std::move(gpu_channel_host));
@@ -102,7 +128,6 @@
     // consistent codepath.
     if (!BrowserGpuChannelHostFactory::instance())
       BrowserGpuChannelHostFactory::Initialize(false);
-
     CHECK(GetFactory());
 
     ContentBrowserTest::SetUpOnMainThread();
@@ -119,27 +144,30 @@
     callback.Run();
   }
 
+  void Signal(bool* event,
+              scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
+    CHECK_EQ(*event, false);
+    *event = true;
+    gpu_channel_host_ = std::move(gpu_channel_host);
+  }
+
  protected:
   BrowserGpuChannelHostFactory* GetFactory() {
     return BrowserGpuChannelHostFactory::instance();
   }
 
   bool IsChannelEstablished() {
-    return GetFactory()->GetGpuChannel() != NULL;
+    return gpu_channel_host_ && !gpu_channel_host_->IsLost();
   }
 
   void EstablishAndWait() {
-    base::RunLoop run_loop;
-    GetFactory()->EstablishGpuChannel(run_loop.QuitClosure());
-    run_loop.Run();
+    EstablishGpuChannelHelper helper;
+    gpu_channel_host_ = helper.EstablishGpuChannelSyncRunLoop();
   }
 
-  gpu::GpuChannelHost* GetGpuChannel() { return GetFactory()->GetGpuChannel(); }
+  gpu::GpuChannelHost* GetGpuChannel() { return gpu_channel_host_.get(); }
 
-  static void Signal(bool *event) {
-    CHECK_EQ(*event, false);
-    *event = true;
-  }
+  scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_;
 };
 
 // Test fails on Chromeos + Mac, flaky on Windows because UI Compositor
@@ -166,7 +194,8 @@
                        MAYBE_EstablishAndTerminate) {
   DCHECK(!IsChannelEstablished());
   base::RunLoop run_loop;
-  GetFactory()->EstablishGpuChannel(run_loop.QuitClosure());
+  GetFactory()->EstablishGpuChannel(
+      base::Bind(&OnEstablishedGpuChannel, run_loop.QuitClosure(), nullptr));
   GetFactory()->Terminate();
 
   // The callback should still trigger.
@@ -190,7 +219,8 @@
   // Expect established callback immediately.
   bool event = false;
   GetFactory()->EstablishGpuChannel(
-      base::Bind(&BrowserGpuChannelHostFactoryTest::Signal, &event));
+      base::Bind(&BrowserGpuChannelHostFactoryTest::Signal,
+                 base::Unretained(this), &event));
   EXPECT_TRUE(event);
   EXPECT_EQ(gpu_channel.get(), GetGpuChannel());
 }
@@ -253,7 +283,7 @@
 // Test fails on Chromeos + Mac, flaky on Windows because UI Compositor
 // establishes a GPU channel.
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-#define MAYBE_CrashAndRecover
+#define MAYBE_CrashAndRecover CrashAndRecover
 #else
 #define MAYBE_CrashAndRecover DISABLED_CrashAndRecover
 #endif
diff --git a/content/browser/gpu/gpu_surface_tracker.cc b/content/browser/gpu/gpu_surface_tracker.cc
index d04a0e2..3c6754c 100644
--- a/content/browser/gpu/gpu_surface_tracker.cc
+++ b/content/browser/gpu/gpu_surface_tracker.cc
@@ -36,6 +36,11 @@
   return surface_handle;
 }
 
+bool GpuSurfaceTracker::IsValidSurfaceHandle(
+    gpu::SurfaceHandle surface_handle) const {
+  return surface_map_.find(surface_handle) != surface_map_.end();
+}
+
 void GpuSurfaceTracker::RemoveSurface(gpu::SurfaceHandle surface_handle) {
   base::AutoLock lock(lock_);
   DCHECK(surface_map_.find(surface_handle) != surface_map_.end());
diff --git a/content/browser/gpu/gpu_surface_tracker.h b/content/browser/gpu/gpu_surface_tracker.h
index 5e519b8..0d55b32 100644
--- a/content/browser/gpu/gpu_surface_tracker.h
+++ b/content/browser/gpu/gpu_surface_tracker.h
@@ -48,6 +48,9 @@
   // Adds a surface for a native widget. Returns the surface ID.
   int AddSurfaceForNativeWidget(gfx::AcceleratedWidget widget);
 
+  // Return true if the surface handle is registered with the tracker.
+  bool IsValidSurfaceHandle(gpu::SurfaceHandle surface_handle) const;
+
   // Removes a given existing surface.
   void RemoveSurface(gpu::SurfaceHandle surface_handle);
 
diff --git a/content/browser/mojo/mojo_child_connection.cc b/content/browser/mojo/mojo_child_connection.cc
index 7ea34cf..830fac4 100644
--- a/content/browser/mojo/mojo_child_connection.cc
+++ b/content/browser/mojo/mojo_child_connection.cc
@@ -13,6 +13,7 @@
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "services/shell/public/cpp/connector.h"
 #include "services/shell/public/cpp/identity.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/interfaces/service.mojom.h"
 
 namespace content {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 53bc140..db423cc 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -44,16 +44,15 @@
 #include "cc/surfaces/display_scheduler.h"
 #include "cc/surfaces/surface_display_output_surface.h"
 #include "cc/surfaces/surface_id_allocator.h"
-#include "cc/surfaces/surface_manager.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "components/display_compositor/compositor_overlay_candidate_validator_android.h"
 #include "components/display_compositor/gl_helper.h"
 #include "content/browser/android/child_process_launcher_android.h"
-#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/host_shared_bitmap_manager.h"
@@ -82,6 +81,64 @@
 
 const unsigned int kMaxDisplaySwapBuffers = 1U;
 
+gpu::SharedMemoryLimits GetCompositorContextSharedMemoryLimits() {
+  constexpr size_t kBytesPerPixel = 4;
+  const size_t full_screen_texture_size_in_bytes =
+      gfx::DeviceDisplayInfo().GetDisplayHeight() *
+      gfx::DeviceDisplayInfo().GetDisplayWidth() * kBytesPerPixel;
+
+  gpu::SharedMemoryLimits limits;
+  // This limit is meant to hold the contents of the display compositor
+  // drawing the scene. See discussion here:
+  // https://codereview.chromium.org/1900993002/diff/90001/content/browser/renderer_host/compositor_impl_android.cc?context=3&column_width=80&tab_spaces=8
+  limits.command_buffer_size = 64 * 1024;
+  // These limits are meant to hold the uploads for the browser UI without
+  // any excess space.
+  limits.start_transfer_buffer_size = 64 * 1024;
+  limits.min_transfer_buffer_size = 64 * 1024;
+  limits.max_transfer_buffer_size = full_screen_texture_size_in_bytes;
+  // Texture uploads may use mapped memory so give a reasonable limit for
+  // them.
+  limits.mapped_memory_reclaim_limit = full_screen_texture_size_in_bytes;
+
+  return limits;
+}
+
+gpu::gles2::ContextCreationAttribHelper GetCompositorContextAttributes(
+    bool has_transparent_background) {
+  // This is used for the browser compositor (offscreen) and for the display
+  // compositor (onscreen), so ask for capabilities needed by either one.
+  // The default framebuffer for an offscreen context is not used, so it does
+  // not need alpha, stencil, depth, antialiasing. The display compositor does
+  // not use these things either, except for alpha when it has a transparent
+  // background.
+  gpu::gles2::ContextCreationAttribHelper attributes;
+  attributes.alpha_size = -1;
+  attributes.stencil_size = 0;
+  attributes.depth_size = 0;
+  attributes.samples = 0;
+  attributes.sample_buffers = 0;
+  attributes.bind_generates_resource = false;
+
+  if (has_transparent_background) {
+    attributes.alpha_size = 8;
+  } else if (base::SysInfo::IsLowEndDevice()) {
+    // In this case we prefer to use RGB565 format instead of RGBA8888 if
+    // possible.
+    // TODO(danakj): GpuCommandBufferStub constructor checks for alpha == 0 in
+    // order to enable 565, but it should avoid using 565 when -1s are
+    // specified
+    // (IOW check that a <= 0 && rgb > 0 && rgb <= 565) then alpha should be
+    // -1.
+    attributes.alpha_size = 0;
+    attributes.red_size = 5;
+    attributes.green_size = 6;
+    attributes.blue_size = 5;
+  }
+
+  return attributes;
+}
+
 class ExternalBeginFrameSource : public cc::BeginFrameSource,
                                  public CompositorImpl::VSyncObserver {
  public:
@@ -287,16 +344,8 @@
 };
 #endif
 
-base::LazyInstance<scoped_refptr<cc::VulkanInProcessContextProvider>>
-    g_shared_vulkan_context_provider_android_ = LAZY_INSTANCE_INITIALIZER;
-
 static bool g_initialized = false;
 
-base::LazyInstance<cc::SurfaceManager> g_surface_manager =
-    LAZY_INSTANCE_INITIALIZER;
-
-int g_surface_client_id = 0;
-
 class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
  public:
   SingleThreadTaskGraphRunner() {
@@ -330,34 +379,11 @@
   return g_initialized;
 }
 
-// static
-cc::SurfaceManager* CompositorImpl::GetSurfaceManager() {
-  return g_surface_manager.Pointer();
-}
-
-// static
-uint32_t CompositorImpl::AllocateSurfaceClientId() {
-  return ++g_surface_client_id;
-}
-
-// static
-scoped_refptr<cc::VulkanInProcessContextProvider>
-CompositorImpl::SharedVulkanContextProviderAndroid() {
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableVulkan)) {
-    scoped_refptr<cc::VulkanInProcessContextProvider>* context_provider =
-        g_shared_vulkan_context_provider_android_.Pointer();
-    if (!*context_provider)
-      *context_provider = cc::VulkanInProcessContextProvider::Create();
-    return *context_provider;
-  }
-  return nullptr;
-}
-
 CompositorImpl::CompositorImpl(CompositorClient* client,
                                gfx::NativeWindow root_window)
     : surface_id_allocator_(
-          new cc::SurfaceIdAllocator(AllocateSurfaceClientId())),
+          new cc::SurfaceIdAllocator(ui::ContextProviderFactory::GetInstance()
+                                         ->AllocateSurfaceClientId())),
       resource_manager_(root_window),
       has_transparent_background_(false),
       device_scale_factor_(1),
@@ -371,8 +397,9 @@
       output_surface_request_pending_(false),
       needs_begin_frames_(false),
       weak_factory_(this) {
-  GetSurfaceManager()->RegisterSurfaceClientId(
-      surface_id_allocator_->client_id());
+  ui::ContextProviderFactory::GetInstance()
+      ->GetSurfaceManager()
+      ->RegisterSurfaceClientId(surface_id_allocator_->client_id());
   DCHECK(client);
   DCHECK(root_window);
   DCHECK(root_window->GetLayer() == nullptr);
@@ -387,8 +414,9 @@
   root_window_->SetLayer(nullptr);
   // Clean-up any surface references.
   SetSurface(NULL);
-  GetSurfaceManager()->InvalidateSurfaceClientId(
-      surface_id_allocator_->client_id());
+  ui::ContextProviderFactory::GetInstance()
+      ->GetSurfaceManager()
+      ->InvalidateSurfaceClientId(surface_id_allocator_->client_id());
 }
 
 ui::UIResourceProvider& CompositorImpl::GetUIResourceProvider() {
@@ -490,12 +518,11 @@
     if (!host_->output_surface_lost())
       host_->ReleaseOutputSurface();
     pending_swapbuffers_ = 0;
-    establish_gpu_channel_timeout_.Stop();
     display_.reset();
   } else {
     host_->SetVisible(true);
     if (output_surface_request_pending_)
-      RequestNewOutputSurface();
+      HandlePendingOutputSurfaceRequest();
   }
 }
 
@@ -538,38 +565,12 @@
   }
 }
 
-void CompositorImpl::OnGpuChannelEstablished() {
-  establish_gpu_channel_timeout_.Stop();
-  CreateOutputSurface();
-}
-
-void CompositorImpl::OnGpuChannelTimeout() {
-  LOG(FATAL) << "Timed out waiting for GPU channel.";
-}
-
 void CompositorImpl::RequestNewOutputSurface() {
+  DCHECK(!output_surface_request_pending_)
+      << "Output Surface Request is already pending?";
+
   output_surface_request_pending_ = true;
-
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
-  defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION)
-  const int64_t kGpuChannelTimeoutInSeconds = 40;
-#else
-  const int64_t kGpuChannelTimeoutInSeconds = 10;
-#endif
-
-  BrowserGpuChannelHostFactory* factory =
-      BrowserGpuChannelHostFactory::instance();
-  if (!factory->GetGpuChannel()) {
-    factory->EstablishGpuChannel(
-        base::Bind(&CompositorImpl::OnGpuChannelEstablished,
-                   weak_factory_.GetWeakPtr()));
-    establish_gpu_channel_timeout_.Start(
-        FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
-        this, &CompositorImpl::OnGpuChannelTimeout);
-    return;
-  }
-
-  CreateOutputSurface();
+  HandlePendingOutputSurfaceRequest();
 }
 
 void CompositorImpl::DidInitializeOutputSurface() {
@@ -581,24 +582,44 @@
   LOG(ERROR) << "Failed to init OutputSurface for compositor.";
   LOG_IF(FATAL, ++num_successive_context_creation_failures_ >= 2)
       << "Too many context creation failures. Giving up... ";
-  RequestNewOutputSurface();
+  HandlePendingOutputSurfaceRequest();
 }
 
-void CompositorImpl::CreateOutputSurface() {
-  // We might have had a request from a LayerTreeHost that was then
-  // hidden (and hidden means we don't have a native surface).
-  // Also make sure we only handle this once.
-  if (!output_surface_request_pending_ || !host_->visible())
+void CompositorImpl::HandlePendingOutputSurfaceRequest() {
+  DCHECK(output_surface_request_pending_);
+
+  // We might have been made invisible now.
+  if (!host_->visible())
     return;
 
-  scoped_refptr<ContextProviderCommandBuffer> context_provider;
-  scoped_refptr<cc::VulkanInProcessContextProvider> vulkan_context_provider =
-      SharedVulkanContextProviderAndroid();
-  std::unique_ptr<cc::OutputSurface> display_output_surface;
 #if defined(ENABLE_VULKAN)
-  std::unique_ptr<VulkanOutputSurface> vulkan_surface;
+  CreateVulkanOutputSurface()
+  if (display_)
+    return;
+#endif
+
+  DCHECK(surface_handle_ != gpu::kNullSurfaceHandle);
+
+  ContextProviderFactoryImpl::GetInstance()->CreateDisplayContextProvider(
+      surface_handle_, GetCompositorContextSharedMemoryLimits(),
+      GetCompositorContextAttributes(has_transparent_background_),
+      false /*support_locking*/, false /*automatic_flushes*/,
+      base::Bind(&CompositorImpl::CreateCompositorOutputSurface,
+                 weak_factory_.GetWeakPtr()));
+}
+
+#if defined(ENABLE_VULKAN)
+void CompositorImpl::CreateVulkanOutputSurface() {
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableVulkan))
+    return;
+
+  std::unique_ptr<cc::OutputSurface> display_output_surface;
+  scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider =
+      ui::ContextProviderFactory::GetInstance()
+          ->GetSharedVulkanContextProvider();
   if (vulkan_context_provider) {
-    vulkan_surface.reset(
+    std::unique_ptr<VulkanOutputSurface> vulkan_surface(
         new VulkanOutputSurface(std::move(vulkan_context_provider)));
     if (!vulkan_surface->Initialize(window_)) {
       vulkan_surface->Destroy();
@@ -607,91 +628,48 @@
       display_output_surface = std::move(vulkan_surface);
     }
   }
+
+  if (!display_output_surface)
+    return;
+
+  InitializeDisplay(std::move(display_output_surface),
+                    std::move(vulkan_context_provider), nullptr);
+}
 #endif
 
-  if (!display_output_surface) {
-    // This is used for the browser compositor (offscreen) and for the display
-    // compositor (onscreen), so ask for capabilities needed by either one.
-    // The default framebuffer for an offscreen context is not used, so it does
-    // not need alpha, stencil, depth, antialiasing. The display compositor does
-    // not use these things either, except for alpha when it has a transparent
-    // background.
-    gpu::gles2::ContextCreationAttribHelper attributes;
-    attributes.alpha_size = -1;
-    attributes.stencil_size = 0;
-    attributes.depth_size = 0;
-    attributes.samples = 0;
-    attributes.sample_buffers = 0;
-    attributes.bind_generates_resource = false;
+void CompositorImpl::CreateCompositorOutputSurface(
+    const scoped_refptr<cc::ContextProvider>& context_provider) {
+  // This callback should run only if we have a pending output surface request,
+  // since that is when we should have queued a context request.
+  // In case the surface was invalidated after the context request was queued,
+  // the request should have been dropped by the ContextProviderFactory.
+  DCHECK(output_surface_request_pending_);
+  DCHECK(host_->visible());
+  DCHECK(window_);
+  DCHECK_NE(surface_handle_, gpu::kNullSurfaceHandle);
+  DCHECK(context_provider);
 
-    if (has_transparent_background_) {
-      attributes.alpha_size = 8;
-    } else if (base::SysInfo::IsLowEndDevice()) {
-      // In this case we prefer to use RGB565 format instead of RGBA8888 if
-      // possible.
-      // TODO(danakj): GpuCommandBufferStub constructor checks for alpha == 0 in
-      // order to enable 565, but it should avoid using 565 when -1s are
-      // specified
-      // (IOW check that a <= 0 && rgb > 0 && rgb <= 565) then alpha should be
-      // -1.
-      attributes.alpha_size = 0;
-      attributes.red_size = 5;
-      attributes.green_size = 6;
-      attributes.blue_size = 5;
-    }
+  scoped_refptr<ContextProviderCommandBuffer> context_provider_command_buffer =
+      static_cast<ContextProviderCommandBuffer*>(context_provider.get());
+  std::unique_ptr<cc::OutputSurface> display_output_surface(
+      new OutputSurfaceWithoutParent(
+          context_provider_command_buffer,
+          base::Bind(&CompositorImpl::PopulateGpuCapabilities,
+                     base::Unretained(this))));
+  InitializeDisplay(std::move(display_output_surface), nullptr,
+                    std::move(context_provider));
+}
 
-    pending_swapbuffers_ = 0;
+void CompositorImpl::InitializeDisplay(
+    std::unique_ptr<cc::OutputSurface> display_output_surface,
+    scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+    scoped_refptr<cc::ContextProvider> context_provider) {
+  DCHECK(output_surface_request_pending_);
 
-    DCHECK(window_);
-    DCHECK_NE(surface_handle_, gpu::kNullSurfaceHandle);
+  pending_swapbuffers_ = 0;
 
-    BrowserGpuChannelHostFactory* factory =
-        BrowserGpuChannelHostFactory::instance();
-    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
-        factory->GetGpuChannel());
-    // If the channel was already lost, we'll get null back here and need to
-    // try again.
-    if (!gpu_channel_host) {
-      RequestNewOutputSurface();
-      return;
-    }
-
-    GURL url("chrome://gpu/CompositorImpl::CreateOutputSurface");
-    constexpr bool automatic_flushes = false;
-    constexpr bool support_locking = false;
-
-    constexpr size_t kBytesPerPixel = 4;
-    const size_t full_screen_texture_size_in_bytes =
-        gfx::DeviceDisplayInfo().GetDisplayHeight() *
-        gfx::DeviceDisplayInfo().GetDisplayWidth() * kBytesPerPixel;
-
-    gpu::SharedMemoryLimits limits;
-    // This limit is meant to hold the contents of the display compositor
-    // drawing the scene. See discussion here:
-    // https://codereview.chromium.org/1900993002/diff/90001/content/browser/renderer_host/compositor_impl_android.cc?context=3&column_width=80&tab_spaces=8
-    limits.command_buffer_size = 64 * 1024;
-    // These limits are meant to hold the uploads for the browser UI without
-    // any excess space.
-    limits.start_transfer_buffer_size = 64 * 1024;
-    limits.min_transfer_buffer_size = 64 * 1024;
-    limits.max_transfer_buffer_size = full_screen_texture_size_in_bytes;
-    // Texture uploads may use mapped memory so give a reasonable limit for
-    // them.
-    limits.mapped_memory_reclaim_limit = full_screen_texture_size_in_bytes;
-
-    context_provider = new ContextProviderCommandBuffer(
-        std::move(gpu_channel_host), gpu::GPU_STREAM_DEFAULT,
-        gpu::GpuStreamPriority::NORMAL, surface_handle_, url, automatic_flushes,
-        support_locking, limits, attributes, nullptr,
-        command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
-    DCHECK(context_provider.get());
-
-    display_output_surface = base::WrapUnique(new OutputSurfaceWithoutParent(
-        context_provider, base::Bind(&CompositorImpl::PopulateGpuCapabilities,
-                                     base::Unretained(this))));
-  }
-
-  cc::SurfaceManager* manager = GetSurfaceManager();
+  cc::SurfaceManager* manager =
+      ui::ContextProviderFactory::GetInstance()->GetSurfaceManager();
   auto* task_runner = base::ThreadTaskRunnerHandle::Get().get();
   std::unique_ptr<ExternalBeginFrameSource> begin_frame_source(
       new ExternalBeginFrameSource(this));
@@ -707,14 +685,12 @@
       base::MakeUnique<cc::TextureMailboxDeleter>(task_runner)));
 
   std::unique_ptr<cc::SurfaceDisplayOutputSurface> delegated_output_surface(
-      vulkan_context_provider
-          ? new cc::SurfaceDisplayOutputSurface(
-                manager, surface_id_allocator_.get(), display_.get(),
-                static_cast<scoped_refptr<cc::VulkanContextProvider>>(
-                    vulkan_context_provider))
-          : new cc::SurfaceDisplayOutputSurface(
-                manager, surface_id_allocator_.get(), display_.get(),
-                context_provider, nullptr));
+      vulkan_context_provider ? new cc::SurfaceDisplayOutputSurface(
+                                    manager, surface_id_allocator_.get(),
+                                    display_.get(), vulkan_context_provider)
+                              : new cc::SurfaceDisplayOutputSurface(
+                                    manager, surface_id_allocator_.get(),
+                                    display_.get(), context_provider, nullptr));
 
   display_->Resize(size_);
   host_->SetOutputSurface(std::move(delegated_output_surface));
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index e77dd91..1b53f8b 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -23,6 +23,7 @@
 #include "gpu/command_buffer/common/capabilities.h"
 #include "gpu/ipc/common/surface_handle.h"
 #include "third_party/khronos/GLES2/gl2.h"
+#include "ui/android/context_provider_factory.h"
 #include "ui/android/resources/resource_manager_impl.h"
 #include "ui/android/resources/ui_resource_provider.h"
 #include "ui/android/window_android_compositor.h"
@@ -36,6 +37,7 @@
 class LayerTreeHost;
 class SurfaceIdAllocator;
 class SurfaceManager;
+class VulkanContextProvider;
 class VulkanInProcessContextProvider;
 }
 
@@ -63,12 +65,6 @@
 
   static bool IsInitialized();
 
-  static cc::SurfaceManager* GetSurfaceManager();
-  static uint32_t AllocateSurfaceClientId();
-
-  static scoped_refptr<cc::VulkanInProcessContextProvider>
-  SharedVulkanContextProviderAndroid();
-
   void PopulateGpuCapabilities(gpu::Capabilities gpu_capabilities);
 
   void AddObserver(VSyncObserver* observer);
@@ -122,11 +118,19 @@
                base::TimeDelta vsync_period) override;
   void SetNeedsAnimate() override;
   void SetVisible(bool visible);
-  void CreateOutputSurface();
   void CreateLayerTreeHost();
 
-  void OnGpuChannelEstablished();
-  void OnGpuChannelTimeout();
+  void HandlePendingOutputSurfaceRequest();
+
+#if defined(ENABLE_VULKAN)
+  void CreateVulkanOutputSurface();
+#endif
+  void CreateCompositorOutputSurface(
+      const scoped_refptr<cc::ContextProvider>& context_provider);
+  void InitializeDisplay(
+      std::unique_ptr<cc::OutputSurface> display_output_surface,
+      scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider,
+      scoped_refptr<cc::ContextProvider> context_provider);
 
   // root_layer_ is the persistent internal root layer, while subroot_layer_
   // is the one attached by the compositor client.
@@ -160,8 +164,6 @@
 
   size_t num_successive_context_creation_failures_;
 
-  base::OneShotTimer establish_gpu_channel_timeout_;
-
   // Whether there is an OutputSurface request pending from the current
   // |host_|. Becomes |true| if RequestNewOutputSurface is called, and |false|
   // if |host_| is deleted or we succeed in creating *and* initializing an
diff --git a/content/browser/renderer_host/context_provider_factory_impl_android.cc b/content/browser/renderer_host/context_provider_factory_impl_android.cc
new file mode 100644
index 0000000..d3db966
--- /dev/null
+++ b/content/browser/renderer_host/context_provider_factory_impl_android.cc
@@ -0,0 +1,249 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
+
+#include "base/auto_reset.h"
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/memory/singleton.h"
+#include "cc/output/context_provider.h"
+#include "cc/output/vulkan_in_process_context_provider.h"
+#include "cc/surfaces/surface_manager.h"
+#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+#include "content/browser/gpu/compositor_util.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/host_shared_bitmap_manager.h"
+#include "content/public/common/content_switches.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
+
+namespace content {
+
+namespace {
+
+command_buffer_metrics::ContextType ToCommandBufferContextType(
+    ui::ContextProviderFactory::ContextType context_type) {
+  switch (context_type) {
+    case ui::ContextProviderFactory::ContextType::
+        BLIMP_RENDER_COMPOSITOR_CONTEXT:
+      return command_buffer_metrics::BLIMP_RENDER_COMPOSITOR_CONTEXT;
+    case ui::ContextProviderFactory::ContextType::BLIMP_RENDER_WORKER_CONTEXT:
+      return command_buffer_metrics::BLIMP_RENDER_WORKER_CONTEXT;
+  }
+  NOTREACHED();
+  return command_buffer_metrics::CONTEXT_TYPE_UNKNOWN;
+}
+
+}  // namespace
+
+// static
+ContextProviderFactoryImpl* ContextProviderFactoryImpl::GetInstance() {
+  return base::Singleton<ContextProviderFactoryImpl>::get();
+}
+
+ContextProviderFactoryImpl::ContextProviderFactoryImpl()
+    : in_handle_pending_requests_(false),
+      surface_client_id_(0),
+      weak_factory_(this) {}
+
+ContextProviderFactoryImpl::~ContextProviderFactoryImpl() {}
+
+ContextProviderFactoryImpl::ContextProvidersRequest::ContextProvidersRequest()
+    : context_type(command_buffer_metrics::CONTEXT_TYPE_UNKNOWN),
+      surface_handle(gpu::kNullSurfaceHandle),
+      support_locking(false),
+      automatic_flushes(false),
+      shared_context_provider(nullptr) {}
+
+ContextProviderFactoryImpl::ContextProvidersRequest::ContextProvidersRequest(
+    const ContextProvidersRequest& other) = default;
+
+ContextProviderFactoryImpl::ContextProvidersRequest::
+    ~ContextProvidersRequest() = default;
+
+scoped_refptr<cc::VulkanContextProvider>
+ContextProviderFactoryImpl::GetSharedVulkanContextProvider() {
+  if (!shared_vulkan_context_provider_)
+    shared_vulkan_context_provider_ =
+        cc::VulkanInProcessContextProvider::Create();
+
+  return shared_vulkan_context_provider_.get();
+}
+
+void ContextProviderFactoryImpl::CreateDisplayContextProvider(
+    gpu::SurfaceHandle surface_handle,
+    gpu::SharedMemoryLimits shared_memory_limits,
+    gpu::gles2::ContextCreationAttribHelper attributes,
+    bool support_locking,
+    bool automatic_flushes,
+    ContextProviderCallback result_callback) {
+  DCHECK(surface_handle != gpu::kNullSurfaceHandle);
+  CreateContextProviderInternal(
+      command_buffer_metrics::DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT,
+      surface_handle, shared_memory_limits, attributes, support_locking,
+      automatic_flushes, nullptr, result_callback);
+}
+
+void ContextProviderFactoryImpl::CreateOffscreenContextProvider(
+    ContextType context_type,
+    gpu::SharedMemoryLimits shared_memory_limits,
+    gpu::gles2::ContextCreationAttribHelper attributes,
+    bool support_locking,
+    bool automatic_flushes,
+    cc::ContextProvider* shared_context_provider,
+    ContextProviderCallback result_callback) {
+  CreateContextProviderInternal(ToCommandBufferContextType(context_type),
+                                gpu::kNullSurfaceHandle, shared_memory_limits,
+                                attributes, support_locking, automatic_flushes,
+                                shared_context_provider, result_callback);
+}
+
+cc::SurfaceManager* ContextProviderFactoryImpl::GetSurfaceManager() {
+  if (!surface_manager_)
+    surface_manager_ = base::WrapUnique(new cc::SurfaceManager);
+
+  return surface_manager_.get();
+}
+
+uint32_t ContextProviderFactoryImpl::AllocateSurfaceClientId() {
+  return ++surface_client_id_;
+}
+
+cc::SharedBitmapManager* ContextProviderFactoryImpl::GetSharedBitmapManager() {
+  return HostSharedBitmapManager::current();
+}
+
+gpu::GpuMemoryBufferManager*
+ContextProviderFactoryImpl::GetGpuMemoryBufferManager() {
+  return BrowserGpuMemoryBufferManager::current();
+}
+
+void ContextProviderFactoryImpl::CreateContextProviderInternal(
+    command_buffer_metrics::ContextType context_type,
+    gpu::SurfaceHandle surface_handle,
+    gpu::SharedMemoryLimits shared_memory_limits,
+    gpu::gles2::ContextCreationAttribHelper attributes,
+    bool support_locking,
+    bool automatic_flushes,
+    cc::ContextProvider* shared_context_provider,
+    ContextProviderCallback result_callback) {
+  DCHECK(!result_callback.is_null());
+
+  ContextProvidersRequest context_request;
+  context_request.context_type = context_type;
+  context_request.surface_handle = surface_handle;
+  context_request.shared_memory_limits = shared_memory_limits;
+  context_request.attributes = attributes;
+  context_request.support_locking = support_locking;
+  context_request.automatic_flushes = automatic_flushes;
+  context_request.shared_context_provider = shared_context_provider;
+  context_request.result_callback = result_callback;
+
+  context_provider_requests_.push_back(context_request);
+  HandlePendingRequests();
+}
+
+void ContextProviderFactoryImpl::HandlePendingRequests() {
+  DCHECK(!context_provider_requests_.empty())
+      << "We don't have any pending requests?";
+
+  // Failure to initialize the context could result in new requests. Handle
+  // them after going through the current list.
+  if (in_handle_pending_requests_)
+    return;
+
+  {
+    base::AutoReset<bool> auto_reset_in_handle_requests(
+        &in_handle_pending_requests_, true);
+
+    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
+        EnsureGpuChannelEstablished());
+
+    // If we don't have a Gpu Channel Host, we will come back here when the Gpu
+    // channel is established, since OnGpuChannelEstablished triggers handling
+    // of the requests we couldn't process right now.
+    if (!gpu_channel_host)
+      return;
+
+    std::list<ContextProvidersRequest> context_requests =
+        context_provider_requests_;
+    context_provider_requests_.clear();
+
+    for (ContextProvidersRequest& context_request : context_requests) {
+      scoped_refptr<cc::ContextProvider> context_provider;
+
+      const bool create_onscreen_context =
+          context_request.surface_handle != gpu::kNullSurfaceHandle;
+
+      // Is the request for an onscreen context? Make sure the surface is
+      // still valid in that case. DO NOT run the callback if we don't have a
+      // valid surface.
+      if (create_onscreen_context &&
+          !GpuSurfaceTracker::GetInstance()->IsValidSurfaceHandle(
+              context_request.surface_handle)) {
+        continue;
+      }
+
+      context_provider = new ContextProviderCommandBuffer(
+          gpu_channel_host, gpu::GPU_STREAM_DEFAULT,
+          gpu::GpuStreamPriority::NORMAL, context_request.surface_handle,
+          GURL(std::string("chrome://gpu/ContextProviderFactoryImpl::") +
+               std::string("CompositorContextProvider")),
+          context_request.automatic_flushes, context_request.support_locking,
+          context_request.shared_memory_limits, context_request.attributes,
+          static_cast<ContextProviderCommandBuffer*>(
+              context_request.shared_context_provider),
+          context_request.context_type);
+      context_request.result_callback.Run(context_provider);
+    }
+  }
+
+  if (!context_provider_requests_.empty())
+    HandlePendingRequests();
+}
+
+gpu::GpuChannelHost* ContextProviderFactoryImpl::EnsureGpuChannelEstablished() {
+#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || \
+    defined(SYZYASAN) || defined(CYGPROFILE_INSTRUMENTATION)
+  const int64_t kGpuChannelTimeoutInSeconds = 40;
+#else
+  const int64_t kGpuChannelTimeoutInSeconds = 10;
+#endif
+
+  BrowserGpuChannelHostFactory* factory =
+      BrowserGpuChannelHostFactory::instance();
+
+  if (factory->GetGpuChannel())
+    return factory->GetGpuChannel();
+
+  factory->EstablishGpuChannel(
+      base::Bind(&ContextProviderFactoryImpl::OnGpuChannelEstablished,
+                 weak_factory_.GetWeakPtr()));
+  establish_gpu_channel_timeout_.Start(
+      FROM_HERE, base::TimeDelta::FromSeconds(kGpuChannelTimeoutInSeconds),
+      this, &ContextProviderFactoryImpl::OnGpuChannelTimeout);
+
+  return nullptr;
+}
+
+void ContextProviderFactoryImpl::OnGpuChannelEstablished(
+    scoped_refptr<gpu::GpuChannelHost> gpu_channel) {
+  establish_gpu_channel_timeout_.Stop();
+
+  // We can queue the Gpu Channel initialization requests multiple times as
+  // we get context requests. So we might have already handled any pending
+  // requests when this callback runs.
+  if (!context_provider_requests_.empty())
+    HandlePendingRequests();
+}
+
+void ContextProviderFactoryImpl::OnGpuChannelTimeout() {
+  LOG(FATAL) << "Timed out waiting for GPU channel.";
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/context_provider_factory_impl_android.h b/content/browser/renderer_host/context_provider_factory_impl_android.h
new file mode 100644
index 0000000..3a820fb
--- /dev/null
+++ b/content/browser/renderer_host/context_provider_factory_impl_android.h
@@ -0,0 +1,127 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_CONTEXT_PROVIDER_FACTORY_IMPL_ANDROID_H_
+#define CONTENT_BROWSER_RENDERER_HOST_CONTEXT_PROVIDER_FACTORY_IMPL_ANDROID_H_
+
+#include <list>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+#include "content/common/gpu/client/command_buffer_metrics.h"
+#include "gpu/command_buffer/client/shared_memory_limits.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/ipc/common/surface_handle.h"
+#include "ui/android/context_provider_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace cc {
+class VulkanInProcessContextProvider;
+}
+
+namespace gpu {
+class GpuChannelHost;
+}
+
+namespace content {
+class ContextProviderCommandBuffer;
+
+class CONTENT_EXPORT ContextProviderFactoryImpl
+    : public ui::ContextProviderFactory {
+ public:
+  static ContextProviderFactoryImpl* GetInstance();
+
+  ~ContextProviderFactoryImpl() override;
+
+  // The callback may be triggered synchronously, if the Gpu Channel is already
+  // initialized. In case the surface_handle is invalidated before the context
+  // can be created, the request is dropped and the callback will *not* run.
+  void CreateDisplayContextProvider(
+      gpu::SurfaceHandle surface_handle,
+      gpu::SharedMemoryLimits shared_memory_limits,
+      gpu::gles2::ContextCreationAttribHelper attributes,
+      bool support_locking,
+      bool automatic_flushes,
+      ContextProviderCallback result_callback);
+
+  // ContextProviderFactory implementation.
+  scoped_refptr<cc::VulkanContextProvider> GetSharedVulkanContextProvider()
+      override;
+  void CreateOffscreenContextProvider(
+      ContextType context_type,
+      gpu::SharedMemoryLimits shared_memory_limits,
+      gpu::gles2::ContextCreationAttribHelper attributes,
+      bool support_locking,
+      bool automatic_flushes,
+      cc::ContextProvider* shared_context_provider,
+      ContextProviderCallback result_callback) override;
+  cc::SurfaceManager* GetSurfaceManager() override;
+  uint32_t AllocateSurfaceClientId() override;
+  cc::SharedBitmapManager* GetSharedBitmapManager() override;
+  gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override;
+
+ private:
+  friend struct base::DefaultSingletonTraits<ContextProviderFactoryImpl>;
+
+  void CreateContextProviderInternal(
+      command_buffer_metrics::ContextType context_type,
+      gpu::SurfaceHandle surface_handle,
+      gpu::SharedMemoryLimits shared_memory_limits,
+      gpu::gles2::ContextCreationAttribHelper attributes,
+      bool support_locking,
+      bool automatic_flushes,
+      cc::ContextProvider* shared_context_provider,
+      ContextProviderCallback result_callback);
+
+  struct ContextProvidersRequest {
+    ContextProvidersRequest();
+    ContextProvidersRequest(const ContextProvidersRequest& other);
+    ~ContextProvidersRequest();
+
+    command_buffer_metrics::ContextType context_type;
+    gpu::SurfaceHandle surface_handle;
+    gpu::SharedMemoryLimits shared_memory_limits;
+    gpu::gles2::ContextCreationAttribHelper attributes;
+    bool support_locking;
+    bool automatic_flushes;
+    cc::ContextProvider* shared_context_provider;
+    ContextProviderCallback result_callback;
+  };
+
+  ContextProviderFactoryImpl();
+
+  // Will return nullptr if the Gpu channel has not been established.
+  gpu::GpuChannelHost* EnsureGpuChannelEstablished();
+  void OnGpuChannelEstablished(scoped_refptr<gpu::GpuChannelHost> gpu_channel);
+  void OnGpuChannelTimeout();
+
+  void HandlePendingRequests();
+
+  std::list<ContextProvidersRequest> context_provider_requests_;
+
+  scoped_refptr<ContextProviderCommandBuffer> shared_worker_context_provider_;
+
+  scoped_refptr<cc::VulkanContextProvider> shared_vulkan_context_provider_;
+
+  bool in_handle_pending_requests_;
+
+  base::OneShotTimer establish_gpu_channel_timeout_;
+
+  std::unique_ptr<cc::SurfaceManager> surface_manager_;
+  int surface_client_id_;
+
+  base::WeakPtrFactory<ContextProviderFactoryImpl> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ContextProviderFactoryImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_CONTEXT_PROVIDER_FACTORY_IMPL_ANDROID_H_
diff --git a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
index fece159d..ec2da942 100644
--- a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
+++ b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
@@ -209,11 +209,10 @@
 // static
 void VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread(
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-    base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this) {
+    base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this,
+    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
-      BrowserGpuChannelHostFactory::instance()->GetGpuChannel());
   task_runner->PostTask(
       FROM_HERE, base::Bind(&VideoCaptureGpuJpegDecoder::FinishInitialization,
                             weak_this, std::move(gpu_channel_host)));
diff --git a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
index 85f94f03..c1541ec7 100644
--- a/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
+++ b/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
@@ -92,7 +92,8 @@
 
   static void GpuChannelEstablishedOnUIThread(
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
-      base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this);
+      base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this,
+      scoped_refptr<gpu::GpuChannelHost> established_channel_host);
 
   void FinishInitialization(
       scoped_refptr<gpu::GpuChannelHost> gpu_channel_host);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index a411c91..9919ef6 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -479,13 +479,13 @@
 
  private:
   // ConnectionFilter:
-  bool OnConnect(shell::Connection* connection,
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry,
                  shell::Connector* connector) override {
     if (!weak_factory_)
       weak_factory_.reset(new base::WeakPtrFactory<ConnectionFilterImpl>(this));
 
     // We only fulfill connections from the renderer we host.
-    const shell::Identity& remote_identity = connection->GetRemoteIdentity();
     if (child_identity_.name() != remote_identity.name() ||
         child_identity_.instance() != remote_identity.instance()) {
       return false;
@@ -496,11 +496,10 @@
     for (auto& interface_name : interface_names) {
       // Note that the added callbacks may outlive this object, which is
       // destroyed in RPH::Cleanup().
-      connection->GetInterfaceRegistry()->AddInterface(
-          interface_name,
-          base::Bind(&ConnectionFilterImpl::GetInterface,
-                     weak_factory_->GetWeakPtr(),
-                     interface_name));
+      registry->AddInterface(interface_name,
+                             base::Bind(&ConnectionFilterImpl::GetInterface,
+                                        weak_factory_->GetWeakPtr(),
+                                        interface_name));
     }
     return true;
   }
@@ -1106,7 +1105,7 @@
 
 void RenderProcessHostImpl::RegisterMojoInterfaces() {
   std::unique_ptr<shell::InterfaceRegistry> registry(
-      new shell::InterfaceRegistry(nullptr));
+      new shell::InterfaceRegistry);
 #if defined(OS_ANDROID)
   interface_registry_android_ =
       InterfaceRegistryAndroid::Create(registry.get());
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index b83c7e27..367cfd7 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -37,6 +37,7 @@
 #include "ui/gfx/canvas.h"
 
 #if defined(OS_ANDROID)
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
 #include "content/browser/renderer_host/render_widget_host_view_android.h"
 #endif
 
@@ -466,6 +467,10 @@
         std::unique_ptr<ImageTransportFactory>(
             new NoTransportImageTransportFactory));
 #endif
+#if defined(OS_ANDROID)
+    ui::ContextProviderFactory::SetInstance(
+        ContextProviderFactoryImpl::GetInstance());
+#endif
 #if defined(USE_AURA)
     screen_.reset(aura::TestScreen::Create(gfx::Size()));
     display::Screen::SetScreenInstance(screen_.get());
@@ -494,6 +499,9 @@
 #if defined(USE_AURA) || defined(OS_MACOSX)
     ImageTransportFactory::Terminate();
 #endif
+#if defined(OS_ANDROID)
+    ui::ContextProviderFactory::SetInstance(nullptr);
+#endif
 
     // Process all pending tasks to avoid leaks.
     base::RunLoop().RunUntilIdle();
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index cadbf88b..f29806a 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -75,6 +75,7 @@
 #include "third_party/khronos/GLES2/gl2.h"
 #include "third_party/khronos/GLES2/gl2ext.h"
 #include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/android/context_provider_factory.h"
 #include "ui/android/window_android.h"
 #include "ui/android/window_android_compositor.h"
 #include "ui/base/layout.h"
@@ -289,7 +290,8 @@
     const cc::SurfaceId& surface_id,
     const gfx::Size& size) {
   DCHECK(!surface_id.is_null());
-  cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
+  cc::SurfaceManager* manager =
+      ui::ContextProviderFactory::GetInstance()->GetSurfaceManager();
   DCHECK(manager);
   // manager must outlive compositors using it.
   scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create(
@@ -344,10 +346,14 @@
       locks_on_frame_count_(0),
       observing_root_window_(false),
       weak_ptr_factory_(this) {
-  id_allocator_.reset(
-      new cc::SurfaceIdAllocator(CompositorImpl::AllocateSurfaceClientId()));
-  CompositorImpl::GetSurfaceManager()->RegisterSurfaceClientId(
-      id_allocator_->client_id());
+  if (using_browser_compositor_) {
+    id_allocator_.reset(new cc::SurfaceIdAllocator(
+        ui::ContextProviderFactory::GetInstance()->AllocateSurfaceClientId()));
+    ui::ContextProviderFactory::GetInstance()
+        ->GetSurfaceManager()
+        ->RegisterSurfaceClientId(id_allocator_->client_id());
+  }
+
   host_->SetView(this);
   SetContentViewCore(content_view_core);
 }
@@ -797,8 +803,11 @@
     surface_id_ = cc::SurfaceId();
   }
   surface_factory_.reset();
-  CompositorImpl::GetSurfaceManager()->InvalidateSurfaceClientId(
-      id_allocator_->client_id());
+  if (id_allocator_) {
+    ui::ContextProviderFactory::GetInstance()
+        ->GetSurfaceManager()
+        ->InvalidateSurfaceClientId(id_allocator_->client_id());
+  }
 
   // The RenderWidgetHost's destruction led here, so don't call it.
   host_ = NULL;
@@ -954,8 +963,9 @@
   RemoveLayers();
   if (!surface_id_.is_null()) {
     DCHECK(surface_factory_.get());
-    surface_factory_->Destroy(surface_id_);
-    surface_id_ = cc::SurfaceId();
+    cc::SurfaceId surface_id;
+    std::swap(surface_id, surface_id_);
+    surface_factory_->Destroy(surface_id);
   }
   view_.SetLayer(nullptr);
 }
@@ -975,7 +985,8 @@
 
 void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
     cc::CompositorFrame frame) {
-  cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
+  cc::SurfaceManager* manager =
+      ui::ContextProviderFactory::GetInstance()->GetSurfaceManager();
   if (!surface_factory_) {
     surface_factory_ = base::WrapUnique(new cc::SurfaceFactory(manager, this));
   }
@@ -1012,7 +1023,6 @@
     cc::CompositorFrame frame) {
   last_scroll_offset_ = frame.metadata.root_scroll_offset;
   DCHECK(frame.delegated_frame_data);
-  DCHECK(CompositorImpl::GetSurfaceManager());
 
   if (locks_on_frame_count_ > 0) {
     DCHECK(HasValidFrame());
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index 1508dd75..1e78b205 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -436,7 +436,7 @@
   status_ = EmbeddedWorkerStatus::STARTING;
   starting_phase_ = ALLOCATING_PROCESS;
   network_accessed_for_script_ = false;
-  interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+  interface_registry_.reset(new shell::InterfaceRegistry);
   remote_interfaces_.reset(new shell::InterfaceProvider);
   FOR_EACH_OBSERVER(Listener, listener_list_, OnStarting());
 
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index d2b5385..bdefff4 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -102,8 +102,7 @@
                                     NewMessagePortMessageFilter());
 
   // Setup process level interface registry.
-  render_process_interface_registry_.reset(
-      new shell::InterfaceRegistry(nullptr));
+  render_process_interface_registry_.reset(new shell::InterfaceRegistry);
   render_process_interface_registry_->AddInterface(
       base::Bind(&MockEmbeddedWorkerSetup::Create, weak_factory_.GetWeakPtr()));
   shell::mojom::InterfaceProviderPtr interfaces;
@@ -420,7 +419,7 @@
     shell::mojom::InterfaceProviderRequest request,
     shell::mojom::InterfaceProviderPtr remote_interfaces) {
   std::unique_ptr<shell::InterfaceRegistry> local(
-      new shell::InterfaceRegistry(nullptr));
+      new shell::InterfaceRegistry);
   local->Bind(std::move(request));
 
   std::unique_ptr<shell::InterfaceProvider> remote(
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index add5865..8018c03 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -411,13 +411,13 @@
   void OnReportConsoleMessageOnUI(const base::string16& message) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     messages_.push_back(message);
-    if (messages_.size() == expected_message_count_)
+    if (!quit_.is_null() && messages_.size() == expected_message_count_)
       quit_.Run();
   }
 
   // These parameters must be accessed on the UI thread.
   std::vector<base::string16> messages_;
-  size_t expected_message_count_;
+  size_t expected_message_count_ = 0;
   base::Closure quit_;
 };
 
@@ -1115,11 +1115,8 @@
   EXPECT_EQ("cache_name", response2.cache_storage_cache_name);
 }
 
-// Disabled because console_listener->OnReportConsoleMessageOnUI() will be
-// called before WaitForConsoleMessages() is called to set the expected number
-// of messages.  https://crbug.com/635599
 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
-                       DISABLED_FetchEvent_respondWithRejection) {
+                       FetchEvent_respondWithRejection) {
   ServiceWorkerFetchEventResult result;
   ServiceWorkerResponse response;
   std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
diff --git a/content/browser/ssl/ssl_cert_error_handler.cc b/content/browser/ssl/ssl_cert_error_handler.cc
deleted file mode 100644
index 54b165d9..0000000
--- a/content/browser/ssl/ssl_cert_error_handler.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/ssl/ssl_cert_error_handler.h"
-
-#include "content/browser/ssl/ssl_manager.h"
-#include "content/browser/ssl/ssl_policy.h"
-#include "net/cert/cert_status_flags.h"
-#include "net/cert/x509_certificate.h"
-
-namespace content {
-
-SSLCertErrorHandler::SSLCertErrorHandler(
-    const base::WeakPtr<Delegate>& delegate,
-    ResourceType resource_type,
-    const GURL& url,
-    const net::SSLInfo& ssl_info,
-    bool fatal)
-    : SSLErrorHandler(delegate, resource_type, url),
-      ssl_info_(ssl_info),
-      cert_error_(net::MapCertStatusToNetError(ssl_info.cert_status)),
-      fatal_(fatal) {}
-
-SSLCertErrorHandler* SSLCertErrorHandler::AsSSLCertErrorHandler() {
-  return this;
-}
-
-void SSLCertErrorHandler::OnDispatchFailed() {
-  // Requests can fail to dispatch because they don't have a WebContents. See
-  // <http://crbug.com/86537>. In this case we have to make a decision in this
-  // function, so we ignore revocation check failures.
-  if (net::IsCertStatusMinorError(ssl_info().cert_status)) {
-    ContinueRequest();
-  } else {
-    CancelRequest();
-  }
-}
-
-void SSLCertErrorHandler::OnDispatched() {
-  manager_->policy()->OnCertError(this);
-}
-
-SSLCertErrorHandler::~SSLCertErrorHandler() {}
-
-}  // namespace content
diff --git a/content/browser/ssl/ssl_cert_error_handler.h b/content/browser/ssl/ssl_cert_error_handler.h
deleted file mode 100644
index e5d098b3..0000000
--- a/content/browser/ssl/ssl_cert_error_handler.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_
-#define CONTENT_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/ssl/ssl_error_handler.h"
-#include "net/ssl/ssl_info.h"
-
-namespace content {
-
-// A CertError represents an error that occurred with the certificate in an
-// SSL session.  A CertError object exists both on the IO thread and on the UI
-// thread and allows us to cancel/continue a request it is associated with.
-class SSLCertErrorHandler : public SSLErrorHandler {
- public:
-  // Construct on the IO thread.
-  SSLCertErrorHandler(const base::WeakPtr<Delegate>& delegate,
-                      ResourceType resource_type,
-                      const GURL& url,
-                      const net::SSLInfo& ssl_info,
-                      bool fatal);
-
-  SSLCertErrorHandler* AsSSLCertErrorHandler() override;
-
-  // These accessors are available on either thread
-  const net::SSLInfo& ssl_info() const { return ssl_info_; }
-  int cert_error() const { return cert_error_; }
-  bool fatal() const { return fatal_; }
-
- protected:
-  // SSLErrorHandler methods
-  void OnDispatchFailed() override;
-  void OnDispatched() override;
-
- private:
-  ~SSLCertErrorHandler() override;
-
-  // These read-only members may be accessed on any thread.
-  const net::SSLInfo ssl_info_;
-  const int cert_error_;  // The error we represent.
-  const bool fatal_;  // True if the error is from a host requiring
-                      // certificate errors to be fatal.
-
-  DISALLOW_COPY_AND_ASSIGN(SSLCertErrorHandler);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_SSL_SSL_CERT_ERROR_HANDLER_H_
diff --git a/content/browser/ssl/ssl_error_handler.cc b/content/browser/ssl/ssl_error_handler.cc
index 40b2b564..11e68910 100644
--- a/content/browser/ssl/ssl_error_handler.cc
+++ b/content/browser/ssl/ssl_error_handler.cc
@@ -7,11 +7,13 @@
 #include "base/bind.h"
 #include "content/browser/frame_host/navigation_controller_impl.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/ssl/ssl_cert_error_handler.h"
+#include "content/browser/ssl/ssl_manager.h"
+#include "content/browser/ssl/ssl_policy.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/resource_request_info.h"
 #include "net/base/net_errors.h"
+#include "net/cert/cert_status_flags.h"
 #include "net/url_request/url_request.h"
 
 using net::SSLInfo;
@@ -20,12 +22,17 @@
 
 SSLErrorHandler::SSLErrorHandler(const base::WeakPtr<Delegate>& delegate,
                                  ResourceType resource_type,
-                                 const GURL& url)
+                                 const GURL& url,
+                                 const net::SSLInfo& ssl_info,
+                                 bool fatal)
     : manager_(NULL),
       delegate_(delegate),
+      request_has_been_notified_(false),
       request_url_(url),
       resource_type_(resource_type),
-      request_has_been_notified_(false) {
+      ssl_info_(ssl_info),
+      cert_error_(net::MapCertStatusToNetError(ssl_info.cert_status)),
+      fatal_(fatal) {
   DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(delegate.get());
 
@@ -40,15 +47,18 @@
 SSLErrorHandler::~SSLErrorHandler() {}
 
 void SSLErrorHandler::OnDispatchFailed() {
-  TakeNoAction();
+  // Requests can fail to dispatch because they don't have a WebContents. See
+  // <http://crbug.com/86537>. In this case we have to make a decision in this
+  // function, so we ignore revocation check failures.
+  if (net::IsCertStatusMinorError(ssl_info().cert_status)) {
+    ContinueRequest();
+  } else {
+    CancelRequest();
+  }
 }
 
 void SSLErrorHandler::OnDispatched() {
-  TakeNoAction();
-}
-
-SSLCertErrorHandler* SSLErrorHandler::AsSSLCertErrorHandler() {
-  return NULL;
+  manager_->policy()->OnCertError(this);
 }
 
 void SSLErrorHandler::Dispatch(
@@ -125,12 +135,8 @@
   if (request_has_been_notified_)
     return;
 
-  SSLCertErrorHandler* cert_error = AsSSLCertErrorHandler();
-  const SSLInfo* ssl_info = NULL;
-  if (cert_error)
-    ssl_info = &cert_error->ssl_info();
   if (delegate_.get())
-    delegate_->CancelSSLRequest(error, ssl_info);
+    delegate_->CancelSSLRequest(error, &ssl_info_);
   request_has_been_notified_ = true;
 
   // We're done with this object on the IO thread.
diff --git a/content/browser/ssl/ssl_error_handler.h b/content/browser/ssl/ssl_error_handler.h
index 658ec01..b981e7e 100644
--- a/content/browser/ssl/ssl_error_handler.h
+++ b/content/browser/ssl/ssl_error_handler.h
@@ -13,17 +13,16 @@
 #include "content/common/content_export.h"
 #include "content/public/browser/global_request_id.h"
 #include "content/public/common/resource_type.h"
+#include "net/ssl/ssl_info.h"
 #include "url/gurl.h"
 
 namespace net {
-class SSLInfo;
 class URLRequest;
 }  // namespace net
 
 namespace content {
 
 class ResourceDispatcherHostImpl;
-class SSLCertErrorHandler;
 class SSLManager;
 class WebContents;
 
@@ -60,7 +59,12 @@
     virtual ~Delegate() {}
   };
 
-  virtual SSLCertErrorHandler* AsSSLCertErrorHandler();
+  // Construct on the IO thread.
+  SSLErrorHandler(const base::WeakPtr<Delegate>& delegate,
+                  ResourceType resource_type,
+                  const GURL& url,
+                  const net::SSLInfo& ssl_info,
+                  bool fatal);
 
   // Find the appropriate SSLManager for the net::URLRequest and begin handling
   // this error.
@@ -68,50 +72,40 @@
   // Call on UI thread.
   void Dispatch(const base::Callback<WebContents*(void)>& web_contents_getter);
 
-  // Available on either thread.
+  // These accessors are available on either thread
+  const net::SSLInfo& ssl_info() const { return ssl_info_; }
+  int cert_error() const { return cert_error_; }
+  bool fatal() const { return fatal_; }
   const GURL& request_url() const { return request_url_; }
-
-  // Available on either thread.
   ResourceType resource_type() const { return resource_type_; }
 
   // Cancels the associated net::URLRequest.
-  // This method can be called from OnDispatchFailed and OnDispatched.
   CONTENT_EXPORT void CancelRequest();
 
   // Continue the net::URLRequest ignoring any previous errors.  Note that some
   // errors cannot be ignored, in which case this will result in the request
   // being canceled.
-  // This method can be called from OnDispatchFailed and OnDispatched.
   void ContinueRequest();
 
   // Cancels the associated net::URLRequest and mark it as denied.  The renderer
   // processes such request in a special manner, optionally replacing them
   // with alternate content (typically frames content is replaced with a
   // warning message).
-  // This method can be called from OnDispatchFailed and OnDispatched.
   void DenyRequest();
 
   // Does nothing on the net::URLRequest but ensures the current instance ref
-  // count is decremented appropriately.  Subclasses that do not want to
-  // take any specific actions in their OnDispatched/OnDispatchFailed should
-  // call this.
+  // count is decremented appropriately.
   void TakeNoAction();
 
   // Returns the manager associated with this SSLErrorHandler.
   // Should only be accessed on the UI thread.
   SSLManager* GetManager() const;
 
- protected:
+ private:
   friend class base::RefCountedThreadSafe<SSLErrorHandler>;
 
-  // Construct on the IO thread.
-  SSLErrorHandler(const base::WeakPtr<Delegate>& delegate,
-                  ResourceType resource_type,
-                  const GURL& url);
-
   virtual ~SSLErrorHandler();
 
-  // The following 2 methods are the methods subclasses should implement.
   virtual void OnDispatchFailed();
 
   // Can use the manager_ member.
@@ -123,7 +117,6 @@
   // The delegate we are associated with.
   base::WeakPtr<Delegate> delegate_;
 
- private:
   // Completes the CancelRequest operation on the IO thread.
   // Call on the IO thread.
   void CompleteCancelRequest(int error);
@@ -137,19 +130,28 @@
   // Call on the IO thread.
   void CompleteTakeNoAction();
 
-  // The URL that we requested.
-  // This read-only member can be accessed on any thread.
-  const GURL request_url_;
-
-  // What kind of resource is associated with the requested that generated
-  // that error.
-  // This read-only member can be accessed on any thread.
-  const ResourceType resource_type_;
-
   // A flag to make sure we notify the net::URLRequest exactly once.
   // Should only be accessed on the IO thread
   bool request_has_been_notified_;
 
+  // The below read-only members may be accessed on any thread.
+
+  // The URL that we requested.
+  const GURL request_url_;
+
+  // What kind of resource is associated with the request that generated
+  // the error.
+  const ResourceType resource_type_;
+
+  // The SSLInfo associated with the request that generated the error.
+  const net::SSLInfo ssl_info_;
+
+  // The net error code that occurred on the request.
+  const int cert_error_;
+
+  // True if the error is from a host requiring certificate errors to be fatal.
+  const bool fatal_;
+
   DISALLOW_COPY_AND_ASSIGN(SSLErrorHandler);
 };
 
diff --git a/content/browser/ssl/ssl_manager.cc b/content/browser/ssl/ssl_manager.cc
index 4526ab3..bcec1167 100644
--- a/content/browser/ssl/ssl_manager.cc
+++ b/content/browser/ssl/ssl_manager.cc
@@ -13,7 +13,7 @@
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
-#include "content/browser/ssl/ssl_cert_error_handler.h"
+#include "content/browser/ssl/ssl_error_handler.h"
 #include "content/browser/ssl/ssl_policy.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/ssl_status_serialization.h"
@@ -61,14 +61,14 @@
            << " url: " << url.spec()
            << " cert_status: " << std::hex << ssl_info.cert_status;
 
-  // A certificate error occurred.  Construct a SSLCertErrorHandler object and
+  // A certificate error occurred.  Construct a SSLErrorHandler object and
   // hand it over to the UI thread for processing.
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
-      base::Bind(&SSLCertErrorHandler::Dispatch,
-                 new SSLCertErrorHandler(delegate, resource_type, url, ssl_info,
-                                         fatal),
-                 web_contents_getter));
+      base::Bind(
+          &SSLErrorHandler::Dispatch,
+          new SSLErrorHandler(delegate, resource_type, url, ssl_info, fatal),
+          web_contents_getter));
 }
 
 // static
diff --git a/content/browser/ssl/ssl_policy.cc b/content/browser/ssl/ssl_policy.cc
index b962c59..4c44226 100644
--- a/content/browser/ssl/ssl_policy.cc
+++ b/content/browser/ssl/ssl_policy.cc
@@ -15,7 +15,7 @@
 #include "content/browser/renderer_host/render_process_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/site_instance_impl.h"
-#include "content/browser/ssl/ssl_cert_error_handler.h"
+#include "content/browser/ssl/ssl_error_handler.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/web_contents.h"
@@ -42,7 +42,7 @@
   DCHECK(backend_);
 }
 
-void SSLPolicy::OnCertError(SSLCertErrorHandler* handler) {
+void SSLPolicy::OnCertError(SSLErrorHandler* handler) {
   bool expired_previous_decision = false;
   // First we check if we know the policy for this error.
   DCHECK(handler->ssl_info().is_valid());
@@ -156,9 +156,6 @@
   if (web_contents->DisplayedInsecureContent())
     entry->GetSSL().content_status |= SSLStatus::DISPLAYED_INSECURE_CONTENT;
 
-  if (entry->GetSSL().security_style == SECURITY_STYLE_AUTHENTICATION_BROKEN)
-    return;
-
   SiteInstance* site_instance = entry->site_instance();
   // Note that |site_instance| can be NULL here because NavigationEntries don't
   // necessarily have site instances.  Without a process, the entry can't
@@ -169,7 +166,6 @@
     entry->GetSSL().security_style =
         SECURITY_STYLE_AUTHENTICATION_BROKEN;
     entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT;
-    return;
   }
 }
 
@@ -194,61 +190,51 @@
   return SECURITY_STYLE_AUTHENTICATED;
 }
 
-void SSLPolicy::OnAllowCertificate(scoped_refptr<SSLCertErrorHandler> handler,
-                                   bool allow) {
+void SSLPolicy::OnAllowCertificate(scoped_refptr<SSLErrorHandler> handler,
+                                   CertificateRequestResultType decision) {
   DCHECK(handler->ssl_info().is_valid());
-  if (allow) {
-    // Default behavior for accepting a certificate.
-    // Note that we should not call SetMaxSecurityStyle here, because the active
-    // NavigationEntry has just been deleted (in HideInterstitialPage) and the
-    // new NavigationEntry will not be set until DidNavigate.  This is ok,
-    // because the new NavigationEntry will have its max security style set
-    // within DidNavigate.
-    //
-    // While AllowCertForHost() executes synchronously on this thread,
-    // ContinueRequest() gets posted to a different thread. Calling
-    // AllowCertForHost() first ensures deterministic ordering.
-    backend_->AllowCertForHost(*handler->ssl_info().cert.get(),
-                               handler->request_url().host(),
-                               handler->cert_error());
-    handler->ContinueRequest();
-  } else {
-    // Default behavior for rejecting a certificate.
-    handler->CancelRequest();
+  switch (decision) {
+    case CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE:
+      // Note that we should not call SetMaxSecurityStyle here, because the
+      // active
+      // NavigationEntry has just been deleted (in HideInterstitialPage) and the
+      // new NavigationEntry will not be set until DidNavigate.  This is ok,
+      // because the new NavigationEntry will have its max security style set
+      // within DidNavigate.
+      //
+      // While AllowCertForHost() executes synchronously on this thread,
+      // ContinueRequest() gets posted to a different thread. Calling
+      // AllowCertForHost() first ensures deterministic ordering.
+      backend_->AllowCertForHost(*handler->ssl_info().cert.get(),
+                                 handler->request_url().host(),
+                                 handler->cert_error());
+      handler->ContinueRequest();
+      return;
+    case CERTIFICATE_REQUEST_RESULT_TYPE_DENY:
+      handler->DenyRequest();
+      return;
+    case CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL:
+      handler->CancelRequest();
+      return;
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Certificate Error Routines
 
-void SSLPolicy::OnCertErrorInternal(SSLCertErrorHandler* handler,
+void SSLPolicy::OnCertErrorInternal(SSLErrorHandler* handler,
                                     int options_mask) {
   bool overridable = (options_mask & OVERRIDABLE) != 0;
   bool strict_enforcement = (options_mask & STRICT_ENFORCEMENT) != 0;
   bool expired_previous_decision =
       (options_mask & EXPIRED_PREVIOUS_DECISION) != 0;
-  CertificateRequestResultType result =
-      CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE;
   GetContentClient()->browser()->AllowCertificateError(
       handler->GetManager()->controller()->GetWebContents(),
       handler->cert_error(), handler->ssl_info(), handler->request_url(),
       handler->resource_type(), overridable, strict_enforcement,
       expired_previous_decision,
       base::Bind(&SSLPolicy::OnAllowCertificate, base::Unretained(this),
-                 make_scoped_refptr(handler)),
-      &result);
-  switch (result) {
-    case CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE:
-      break;
-    case CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL:
-      handler->CancelRequest();
-      break;
-    case CERTIFICATE_REQUEST_RESULT_TYPE_DENY:
-      handler->DenyRequest();
-      break;
-    default:
-      NOTREACHED();
-  }
+                 make_scoped_refptr(handler)));
 }
 
 void SSLPolicy::InitializeEntryIfNeeded(NavigationEntryImpl* entry) {
diff --git a/content/browser/ssl/ssl_policy.h b/content/browser/ssl/ssl_policy.h
index 93bd861..cdcbebe 100644
--- a/content/browser/ssl/ssl_policy.h
+++ b/content/browser/ssl/ssl_policy.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "content/public/common/resource_type.h"
 #include "content/public/common/security_style.h"
 #include "net/cert/cert_status_flags.h"
@@ -17,7 +18,7 @@
 
 namespace content {
 class NavigationEntryImpl;
-class SSLCertErrorHandler;
+class SSLErrorHandler;
 class SSLPolicyBackend;
 class WebContents;
 
@@ -32,7 +33,7 @@
   explicit SSLPolicy(SSLPolicyBackend* backend);
 
   // An error occurred with the certificate in an SSL connection.
-  void OnCertError(SSLCertErrorHandler* handler);
+  void OnCertError(SSLErrorHandler* handler);
 
   void DidRunInsecureContent(NavigationEntryImpl* entry,
                              const GURL& security_origin);
@@ -64,8 +65,8 @@
   };
 
   // Callback that the user chose to accept or deny the certificate.
-  void OnAllowCertificate(scoped_refptr<SSLCertErrorHandler> handler,
-                          bool allow);
+  void OnAllowCertificate(scoped_refptr<SSLErrorHandler> handler,
+                          CertificateRequestResultType decision);
 
   // Helper method for derived classes handling certificate errors.
   //
@@ -77,7 +78,7 @@
   // certificate validation (e.g. with HTTP Strict-Transport-Security).
   // EXPIRED_PREVIOUS_DECISION indicates whether a user decision had been
   // previously made but the decision has expired.
-  void OnCertErrorInternal(SSLCertErrorHandler* handler, int options_mask);
+  void OnCertErrorInternal(SSLErrorHandler* handler, int options_mask);
 
   // If the security style of |entry| has not been initialized, then initialize
   // it with the default style for its URL.
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index e4e008bb..f0b739c 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -642,7 +642,7 @@
 
 shell::InterfaceRegistry* ChildThreadImpl::GetInterfaceRegistry() {
   if (!interface_registry_.get())
-    interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+    interface_registry_.reset(new shell::InterfaceRegistry);
   return interface_registry_.get();
 }
 
diff --git a/content/common/gpu/client/command_buffer_metrics.cc b/content/common/gpu/client/command_buffer_metrics.cc
index bc70c88..391f043 100644
--- a/content/common/gpu/client/command_buffer_metrics.cc
+++ b/content/common/gpu/client/command_buffer_metrics.cc
@@ -117,6 +117,12 @@
       UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.Media", reason,
                                 CONTEXT_LOST_REASON_MAX_ENUM);
       break;
+    case BLIMP_RENDER_COMPOSITOR_CONTEXT:
+      UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.BlimpRenderCompositor", reason,
+                                CONTEXT_LOST_REASON_MAX_ENUM);
+    case BLIMP_RENDER_WORKER_CONTEXT:
+      UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.BlimpRenderWorker", reason,
+                                CONTEXT_LOST_REASON_MAX_ENUM);
     case CONTEXT_TYPE_UNKNOWN:
       UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.Unknown", reason,
                                 CONTEXT_LOST_REASON_MAX_ENUM);
@@ -150,6 +156,10 @@
       return "Offscreen-For-WebGL";
     case MEDIA_CONTEXT:
       return "Media";
+    case BLIMP_RENDER_COMPOSITOR_CONTEXT:
+      return "BlimpRenderCompositor";
+    case BLIMP_RENDER_WORKER_CONTEXT:
+      return "BlimpRenderWorker";
     default:
       NOTREACHED();
       return "unknown";
diff --git a/content/common/gpu/client/command_buffer_metrics.h b/content/common/gpu/client/command_buffer_metrics.h
index 67f609ca..f508fa7d8 100644
--- a/content/common/gpu/client/command_buffer_metrics.h
+++ b/content/common/gpu/client/command_buffer_metrics.h
@@ -24,6 +24,8 @@
   OFFSCREEN_CONTEXT_FOR_WEBGL,
   CONTEXT_TYPE_UNKNOWN,
   MEDIA_CONTEXT,
+  BLIMP_RENDER_COMPOSITOR_CONTEXT,
+  BLIMP_RENDER_WORKER_CONTEXT,
   OFFSCREEN_CONTEXT_FOR_TESTING = CONTEXT_TYPE_UNKNOWN,
 };
 
diff --git a/content/common/mojo/mojo_shell_connection_impl.cc b/content/common/mojo/mojo_shell_connection_impl.cc
index 7187892..ac66294 100644
--- a/content/common/mojo/mojo_shell_connection_impl.cc
+++ b/content/common/mojo/mojo_shell_connection_impl.cc
@@ -114,16 +114,6 @@
         base::ThreadTaskRunnerHandle::Get(), binder);
   }
 
-  // Safe to call any time after Start() is called.
-  void GetRemoteInterface(const mojo::String& interface_name,
-                          mojo::ScopedMessagePipeHandle request_handle) {
-    DCHECK(started_);
-    io_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&IOThreadContext::GetRemoteInterfaceOnIOThread, this,
-                   interface_name, base::Passed(&request_handle)));
-  }
-
  private:
   friend class base::RefCountedThreadSafe<IOThreadContext>;
 
@@ -144,22 +134,9 @@
     factory_bindings_.CloseAllBindings();
   }
 
-  void GetRemoteInterfaceOnIOThread(
-      const mojo::String& interface_name,
-      mojo::ScopedMessagePipeHandle request_handle) {
-    DCHECK(io_thread_checker_.CalledOnValidThread());
-    if (browser_connection_) {
-      browser_connection_->GetRemoteInterfaces()->GetInterface(
-          interface_name, std::move(request_handle));
-    } else {
-      pending_remote_interface_requests_.emplace(interface_name,
-                                                 std::move(request_handle));
-    }
-  }
-
   void OnBrowserConnectionLost() {
     DCHECK(io_thread_checker_.CalledOnValidThread());
-    browser_connection_ = nullptr;
+    has_browser_connection_ = false;
   }
 
   /////////////////////////////////////////////////////////////////////////////
@@ -173,38 +150,29 @@
     callback_task_runner_->PostTask(FROM_HERE, base::Bind(handler, identity));
   }
 
-  bool OnConnect(shell::Connection* connection) override {
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
     DCHECK(io_thread_checker_.CalledOnValidThread());
-    std::string remote_app = connection->GetRemoteIdentity().name();
+    std::string remote_app = remote_identity.name();
     if (remote_app == "mojo:shell") {
       // Only expose the SCF interface to the shell.
-      connection->AddInterface<shell::mojom::ServiceFactory>(this);
+      registry->AddInterface<shell::mojom::ServiceFactory>(this);
       return true;
     }
 
     bool accept = false;
     for (auto& filter : connection_filters_) {
       accept = accept ||
-        filter->OnConnect(connection, service_context_->connector());
+        filter->OnConnect(remote_identity, registry,
+                          service_context_->connector());
     }
 
-    // Capture the browser connection if possible.
-    if (remote_app == "exe:content_browser" && !browser_connection_) {
-      browser_connection_ = connection;
-      connection->GetInterfaceRegistry()->set_default_binder(
-          default_browser_binder_);
-      connection->SetConnectionLostClosure(
+    if (remote_identity.name() == "exe:content_browser" &&
+        !has_browser_connection_) {
+      has_browser_connection_ = true;
+      registry->set_default_binder(default_browser_binder_);
+      registry->SetConnectionLostClosure(
           base::Bind(&IOThreadContext::OnBrowserConnectionLost, this));
-      shell::InterfaceProvider* remote_interfaces =
-          connection->GetRemoteInterfaces();
-
-      // Flush any pending outgoing interface requests.
-      while (!pending_remote_interface_requests_.empty()) {
-        auto& request = pending_remote_interface_requests_.front();
-        remote_interfaces->GetInterface(
-            request.first, std::move(request.second));
-        pending_remote_interface_requests_.pop();
-      }
       return true;
     }
 
@@ -269,25 +237,9 @@
   // Callback to run if the service is stopped by the service manager.
   base::Closure stop_callback_;
 
-  // The incoming Connection from the browser process. This is captured the
-  // first time the browser connects to this Service and persists until shutdown
-  // or a connection error is detected. This connection is used to fulfill
-  // remote interface requests from legacy code which does not use
-  // shell::Connector.
-  //
-  // TODO(rockot): Remove this once all child-to-browser interface connections
-  // are made via a Connector rather than directly through an InterfaceProvider
-  // and all interfaces exposed to the browser are exposed via a
-  // ConnectionFilter.
-  shell::Connection* browser_connection_ = nullptr;
-
-  // A queue of remote interface requests destined for the browser, which will
-  // remain pending until an incoming connection is accepted from the browser.
-  //
-  // TODO(rockot): Remove this once all child-to-browser interface connections
-  // are made via a Connector rather than directly through an InterfaceProvider.
-  std::queue<std::pair<mojo::String, mojo::ScopedMessagePipeHandle>>
-      pending_remote_interface_requests_;
+  // Called once a connection has been received from the browser process & the
+  // default binder (below) has been set up.
+  bool has_browser_connection_ = false;
 
   // Default binder callback used for the browser connection's
   // InterfaceRegistry.
@@ -405,14 +357,7 @@
       base::Bind(&MojoShellConnectionImpl::GetInterface,
                  weak_factory_.GetWeakPtr(), registry));
 
-  if (!provider)
-    return;
-
-  // Forward all remote interface requests on |provider| to our IO-thread
-  // context. This will ensure they're forwarded to the provider on the
-  // incoming browser connection.
-  provider->Forward(base::Bind(&IOThreadContext::GetRemoteInterface,
-                                context_));
+  // TODO(beng): remove provider parameter.
 }
 
 void MojoShellConnectionImpl::AddConnectionFilter(
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 4fd4b67..2e09e241 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1463,8 +1463,6 @@
       'browser/speech/speech_recognizer_impl.h',
       'browser/speech/speech_recognizer_impl_android.cc',
       'browser/speech/speech_recognizer_impl_android.h',
-      'browser/ssl/ssl_cert_error_handler.cc',
-      'browser/ssl/ssl_cert_error_handler.h',
       'browser/ssl/ssl_client_auth_handler.cc',
       'browser/ssl/ssl_client_auth_handler.h',
       'browser/ssl/ssl_error_handler.cc',
@@ -1641,6 +1639,8 @@
       'browser/media/capture/screen_capture_device_android.h',
       'browser/renderer_host/compositor_impl_android.cc',
       'browser/renderer_host/compositor_impl_android.h',
+      'browser/renderer_host/context_provider_factory_impl_android.cc',
+      'browser/renderer_host/context_provider_factory_impl_android.h',
       'browser/renderer_host/ime_adapter_android.cc',
       'browser/renderer_host/ime_adapter_android.h',
       'browser/renderer_host/input/synthetic_gesture_target_android.cc',
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java
index cdb2c539..efc8f18 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/AddressDetectionTest.java
@@ -26,7 +26,6 @@
     public void testMultipleAddressesInText() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/geo_address_multiple.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "1600 Amphitheatre Parkway Mountain View, CA 94043"));
@@ -40,7 +39,6 @@
     public void testSplitAddresses() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/geo_address_split.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "9606 North MoPac Expressway Suite 400 Austin, TX 78759"));
@@ -60,7 +58,6 @@
     public void testAddressLimits() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/geo_address_limits.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "2590 Pearl Street Suite 100 Boulder, CO 80302"));
@@ -80,7 +77,6 @@
     public void testRealAddresses() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/geo_address_real.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "57th Street and Lake Shore Drive Chicago, IL 60637"));
@@ -100,7 +96,6 @@
     public void testSpecialChars() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/geo_address_special_chars.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         assertTrue(isExpectedGeoIntent(scrollAndTapExpectingIntent("test1"),
                 "100 34th Avenue , San Francisco, CA 94121"));
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ClickListenerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ClickListenerTest.java
index 2c57e814..6d9e8079 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ClickListenerTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ClickListenerTest.java
@@ -18,7 +18,6 @@
     public void testClickContentOnLink() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/click_listeners.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // Clicks on addresses in links should change the url.
         scrollAndTapNavigatingOut("linktest");
@@ -30,7 +29,6 @@
     public void testClickContentOnJSListener1() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/click_listeners.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // Clicks on addresses in elements listening to click events should be
         // processed normally without address detection.
@@ -43,7 +41,6 @@
     public void testClickContentOnJSListener2() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/click_listeners.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // Same as previous test, but using addEventListener instead of onclick.
         scrollAndTapNavigatingOut("clicktest2");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
index 5499a4f..715c30a 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java
@@ -50,7 +50,6 @@
         waitForActiveShellToBeDoneLoading();
 
         mContentViewCore = getContentViewCore();
-        assertWaitForPageScaleFactorMatch(1.1f);
         waitForSelectActionBarVisible(false);
         waitForPastePopupStatus(false);
     }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
index d20e507..d5fbd4d 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
@@ -155,7 +155,6 @@
 
         launchContentShellWithUrl(LARGE_PAGE);
         waitForActiveShellToBeDoneLoading();
-        assertWaitForPageScaleFactorMatch(2.0f);
 
         assertEquals(0, getContentViewCore().getNativeScrollXForTest());
         assertEquals(0, getContentViewCore().getNativeScrollYForTest());
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewZoomingTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewZoomingTest.java
index a8708e32..26dff8fb 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewZoomingTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewZoomingTest.java
@@ -82,7 +82,6 @@
         super.setUp();
         launchContentShellWithUrl(LARGE_PAGE);
         waitForActiveShellToBeDoneLoading();
-        assertWaitForPageScaleFactorMatch(2.0f);
     }
 
     @SmallTest
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java
index 95aa5d9..11d12d6 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java
@@ -25,7 +25,6 @@
     @Feature({"ContentDetection", "TabContents"})
     public void testValidEmailAddresses() throws Throwable {
         startActivityWithTestUrl("content/test/data/android/content_detection/email.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // valid_1: i.want.a.pony@chromium.org.
         String intentUrl = scrollAndTapExpectingIntent("valid_1");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java
index 899dda3c..af150264 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java
@@ -30,7 +30,6 @@
     public void testInternationalNumberIntents() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/phone_international.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // US: +1 650-253-0000.
         String intentUrl = scrollAndTapExpectingIntent("US");
@@ -147,7 +146,6 @@
     public void testLocalUSNumbers() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/phone_local.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // US_1: 1-888-433-5788.
         String intentUrl = scrollAndTapExpectingIntent("US_1");
@@ -172,7 +170,6 @@
     public void testLocalUKNumbers() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/phone_local.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // GB_1: (0) 20 7323 8299.
         String intentUrl = scrollAndTapExpectingIntent("GB_1");
@@ -197,7 +194,6 @@
     public void testLocalFRNumbers() throws Throwable {
         startActivityWithTestUrl(
                 "content/test/data/android/content_detection/phone_local.html");
-        assertWaitForPageScaleFactorMatch(1.0f);
 
         // FR_1: 01 40 20 50 50.
         String intentUrl = scrollAndTapExpectingIntent("FR_1");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/SelectPopupTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/SelectPopupTest.java
index d0788356..39f630a9 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/SelectPopupTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/SelectPopupTest.java
@@ -67,8 +67,6 @@
         super.setUp();
         launchContentShellWithUrl(SELECT_URL);
         waitForActiveShellToBeDoneLoading();
-        // TODO(aurimas) remove this wait once crbug.com/179511 is fixed.
-        assertWaitForPageScaleFactorMatch(1);
     }
 
     /**
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 1753e125..0b3e019 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -325,6 +325,11 @@
   return nullptr;
 }
 
+gpu::GpuChannelEstablishFactory*
+ContentBrowserClient::GetGpuChannelEstablishFactory() {
+  return nullptr;
+}
+
 bool ContentBrowserClient::AllowPepperSocketAPI(
     BrowserContext* browser_context,
     const GURL& url,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 1726f1a..9bbe5f4 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -56,6 +56,10 @@
 class ImageSkia;
 }
 
+namespace gpu {
+class GpuChannelEstablishFactory;
+}
+
 namespace media {
 class CdmFactory;
 }
@@ -460,19 +464,17 @@
   // Informs the embedder that a certificate error has occured.  If
   // |overridable| is true and if |strict_enforcement| is false, the user
   // can ignore the error and continue. The embedder can call the callback
-  // asynchronously. If |result| is not set to
-  // CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE, the request will be cancelled
-  // or denied immediately, and the callback won't be run.
-  virtual void AllowCertificateError(WebContents* web_contents,
-                                     int cert_error,
-                                     const net::SSLInfo& ssl_info,
-                                     const GURL& request_url,
-                                     ResourceType resource_type,
-                                     bool overridable,
-                                     bool strict_enforcement,
-                                     bool expired_previous_decision,
-                                     const base::Callback<void(bool)>& callback,
-                                     CertificateRequestResultType* result) {}
+  // asynchronously.
+  virtual void AllowCertificateError(
+      WebContents* web_contents,
+      int cert_error,
+      const net::SSLInfo& ssl_info,
+      const GURL& request_url,
+      ResourceType resource_type,
+      bool overridable,
+      bool strict_enforcement,
+      bool expired_previous_decision,
+      const base::Callback<void(CertificateRequestResultType)>& callback) {}
 
   // Selects a SSL client certificate and returns it to the |delegate|. Note:
   // |delegate| may be called synchronously or asynchronously.
@@ -571,6 +573,9 @@
   virtual BrowserPpapiHost* GetExternalBrowserPpapiHost(
       int plugin_child_id);
 
+  // Gets the factory to use to establish a connection to the GPU process.
+  virtual gpu::GpuChannelEstablishFactory* GetGpuChannelEstablishFactory();
+
   // Returns true if the socket operation specified by |params| is allowed from
   // the given |browser_context| and |url|. If |params| is nullptr, this method
   // checks the basic "socket" permission, which is for those operations that
diff --git a/content/public/common/connection_filter.h b/content/public/common/connection_filter.h
index be8da3f..60679a8 100644
--- a/content/public/common/connection_filter.h
+++ b/content/public/common/connection_filter.h
@@ -8,8 +8,9 @@
 #include "content/common/content_export.h"
 
 namespace shell {
-class Connection;
 class Connector;
+class Identity;
+class InterfaceRegistry;
 }
 
 namespace content {
@@ -23,7 +24,7 @@
   virtual ~ConnectionFilter() {}
 
   // Called for every new connection accepted. Implementations may add
-  // interfaces to |connection|, in which case they should return |true|.
+  // interfaces to |registry|, in which case they should return |true|.
   // |connector| is a corresponding outgoing Connector that may be used by any
   // interfaces added to the connection. Note that references to |connector|
   // must not be retained, but an owned copy may be obtained by calling
@@ -31,7 +32,8 @@
   //
   // If a ConnectionFilter is not interested in an incoming connection, it
   // should return |false|.
-  virtual bool OnConnect(shell::Connection* connection,
+  virtual bool OnConnect(const shell::Identity& remote_identity,
+                         shell::InterfaceRegistry* registry,
                          shell::Connector* connector) = 0;
 };
 
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index 84cbc9c..ceeac534 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -190,7 +190,7 @@
 
 shell::InterfaceRegistry* MockRenderThread::GetInterfaceRegistry() {
   if (!interface_registry_)
-    interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+    interface_registry_.reset(new shell::InterfaceRegistry);
   return interface_registry_.get();
 }
 
diff --git a/content/public/test/test_mojo_app.cc b/content/public/test/test_mojo_app.cc
index a33c3de..d3ab0f7 100644
--- a/content/public/test/test_mojo_app.cc
+++ b/content/public/test/test_mojo_app.cc
@@ -21,9 +21,10 @@
 TestMojoApp::~TestMojoApp() {
 }
 
-bool TestMojoApp::OnConnect(shell::Connection* connection) {
-  requestor_name_ = connection->GetRemoteIdentity().name();
-  connection->AddInterface<mojom::TestMojoService>(this);
+bool TestMojoApp::OnConnect(const shell::Identity& remote_identity,
+                            shell::InterfaceRegistry* registry) {
+  requestor_name_ = remote_identity.name();
+  registry->AddInterface<mojom::TestMojoService>(this);
   return true;
 }
 
diff --git a/content/public/test/test_mojo_app.h b/content/public/test/test_mojo_app.h
index 0210ff9..dc1a516c 100644
--- a/content/public/test/test_mojo_app.h
+++ b/content/public/test/test_mojo_app.h
@@ -28,7 +28,8 @@
 
  private:
   // shell::Service:
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // shell::InterfaceFactory<mojom::TestMojoService>:
   void Create(const shell::Identity& remote_identity,
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index a7ff602e..d385871 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -28,6 +28,10 @@
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/test/material_design_controller_test_api.h"
 
+#if defined(OS_ANDROID)
+#include "content/browser/renderer_host/context_provider_factory_impl_android.h"
+#endif
+
 #if defined(OS_WIN)
 #include "ui/base/win/scoped_ole_initializer.h"
 #endif
@@ -198,6 +202,9 @@
 #if !defined(OS_ANDROID)
   ImageTransportFactory::InitializeForUnitTests(
       base::WrapUnique(new NoTransportImageTransportFactory));
+#else
+  ui::ContextProviderFactory::SetInstance(
+      ContextProviderFactoryImpl::GetInstance());
 #endif
 #if defined(USE_AURA)
   ui::ContextFactory* context_factory =
@@ -263,6 +270,8 @@
     // RenderWidgetHostView holds on to a reference to SurfaceManager, so it
     // must be shut down before the ImageTransportFactory.
     ImageTransportFactory::Terminate();
+#else
+  ui::ContextProviderFactory::SetInstance(nullptr);
 #endif
 }
 
diff --git a/content/renderer/mus/render_widget_window_tree_client_factory.cc b/content/renderer/mus/render_widget_window_tree_client_factory.cc
index acaf5c2f..3df64afd 100644
--- a/content/renderer/mus/render_widget_window_tree_client_factory.cc
+++ b/content/renderer/mus/render_widget_window_tree_client_factory.cc
@@ -50,9 +50,10 @@
 
  private:
   // ConnectionFilter implementation:
-  bool OnConnect(shell::Connection* connection,
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry,
                  shell::Connector* connector) override {
-    connection->AddInterface<mojom::RenderWidgetWindowTreeClientFactory>(this);
+    registry->AddInterface<mojom::RenderWidgetWindowTreeClientFactory>(this);
     return true;
   }
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 672e2d8..ce82145 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1076,7 +1076,7 @@
   // We don't have a shell::Connection at this point, so use nullptr.
   // TODO(beng): We should fix this, so we can apply policy about which
   //             interfaces get exposed.
-  interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+  interface_registry_.reset(new shell::InterfaceRegistry);
   shell::mojom::InterfaceProviderPtr remote_interfaces;
   pending_remote_interface_provider_request_ = GetProxy(&remote_interfaces);
   remote_interfaces_.reset(new shell::InterfaceProvider);
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index e96ac8a..fbb10ca 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -180,9 +180,7 @@
             IDMapOwnPointer>;
 
   explicit WorkerContextData(ServiceWorkerContextClient* owner)
-      : interface_registry(nullptr),
-        weak_factory(owner),
-        proxy_weak_factory(owner->proxy_) {}
+      : weak_factory(owner), proxy_weak_factory(owner->proxy_) {}
 
   ~WorkerContextData() {
     DCHECK(thread_checker.CalledOnValidThread());
diff --git a/content/shell/android/browsertests/src/org/chromium/content_shell/browsertests/ContentShellBrowserTestActivity.java b/content/shell/android/browsertests/src/org/chromium/content_shell/browsertests/ContentShellBrowserTestActivity.java
index 32a5816..1262712 100644
--- a/content/shell/android/browsertests/src/org/chromium/content_shell/browsertests/ContentShellBrowserTestActivity.java
+++ b/content/shell/android/browsertests/src/org/chromium/content_shell/browsertests/ContentShellBrowserTestActivity.java
@@ -76,7 +76,7 @@
         setContentView(getTestActivityViewId());
         mShellManager = (ShellManager) findViewById(getShellManagerViewId());
         mWindowAndroid = new ActivityWindowAndroid(this);
-        mShellManager.setWindow(mWindowAndroid, false);
+        mShellManager.setWindow(mWindowAndroid);
 
         Window wind = this.getWindow();
         wind.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
diff --git a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
index ab3ccce..d41997f2 100644
--- a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
+++ b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java
@@ -12,7 +12,6 @@
 import android.widget.FrameLayout;
 
 import org.chromium.base.ThreadUtils;
-import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.content.browser.ActivityContentVideoViewEmbedder;
@@ -29,7 +28,6 @@
 public class ShellManager extends FrameLayout {
 
     public static final String DEFAULT_SHELL_URL = "http://www.google.com";
-    private static boolean sStartup = true;
     private WindowAndroid mWindow;
     private Shell mActiveShell;
 
@@ -69,26 +67,9 @@
      * @param window The window used to generate all shells.
      */
     public void setWindow(WindowAndroid window) {
-        setWindow(window, true);
-    }
-
-    /**
-     * @param window The window used to generate all shells.
-     * @param initialLoadingNeeded Whether initial loading is needed or not.
-     */
-    @VisibleForTesting
-    public void setWindow(WindowAndroid window, final boolean initialLoadingNeeded) {
         assert window != null;
         mWindow = window;
-        mContentViewRenderView = new ContentViewRenderView(getContext()) {
-            @Override
-            protected void onReadyToRender() {
-                if (sStartup) {
-                    if (initialLoadingNeeded) mActiveShell.loadUrl(mStartupUrl);
-                    sStartup = false;
-                }
-            }
-        };
+        mContentViewRenderView = new ContentViewRenderView(getContext());
         mContentViewRenderView.onNativeLibraryLoaded(window);
     }
 
diff --git a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java
index 8206ff5d..23675f9 100644
--- a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java
+++ b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellTestBase.java
@@ -121,12 +121,12 @@
                     updateFailureReason("Shell is null.");
                     return false;
                 }
-                if (TextUtils.isEmpty(shell.getContentViewCore().getWebContents().getUrl())) {
-                    updateFailureReason("Shell's URL is empty or null.");
+                if (shell.isLoading()) {
+                    updateFailureReason("Shell is still loading.");
                     return false;
                 }
-                if (!shell.getContentViewCore().getWebContents().isReady()) {
-                    updateFailureReason("Shell's view is not ready.");
+                if (TextUtils.isEmpty(shell.getContentViewCore().getWebContents().getUrl())) {
+                    updateFailureReason("Shell's URL is empty or null.");
                     return false;
                 }
                 return true;
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
index af13bbf..881bfc0 100644
--- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
+++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
@@ -42,6 +42,7 @@
     private ShellManager mShellManager;
     private ActivityWindowAndroid mWindowAndroid;
     private Intent mLastSentIntent;
+    private String mStartupUrl;
 
     @Override
     @SuppressFBWarnings("DM_EXIT")
@@ -81,9 +82,9 @@
         mWindowAndroid.setAnimationPlaceholderView(
                 mShellManager.getContentViewRenderView().getSurfaceView());
 
-        String startupUrl = getUrlFromIntent(getIntent());
-        if (!TextUtils.isEmpty(startupUrl)) {
-            mShellManager.setStartupUrl(Shell.sanitizeUrl(startupUrl));
+        mStartupUrl = getUrlFromIntent(getIntent());
+        if (!TextUtils.isEmpty(mStartupUrl)) {
+            mShellManager.setStartupUrl(Shell.sanitizeUrl(mStartupUrl));
         }
 
         if (CommandLine.getInstance().hasSwitch(ContentSwitches.RUN_LAYOUT_TEST)) {
@@ -118,7 +119,13 @@
     }
 
     private void finishInitialization(Bundle savedInstanceState) {
-        String shellUrl = ShellManager.DEFAULT_SHELL_URL;
+        String shellUrl;
+        if (!TextUtils.isEmpty(mStartupUrl)) {
+            shellUrl = mStartupUrl;
+        } else {
+            shellUrl = ShellManager.DEFAULT_SHELL_URL;
+        }
+
         if (savedInstanceState != null
                 && savedInstanceState.containsKey(ACTIVE_SHELL_URL_KEY)) {
             shellUrl = savedInstanceState.getString(ACTIVE_SHELL_URL_KEY);
diff --git a/content/shell/browser/shell_mojo_test_utils_android.cc b/content/shell/browser/shell_mojo_test_utils_android.cc
index 0dbec57..1036d91 100644
--- a/content/shell/browser/shell_mojo_test_utils_android.cc
+++ b/content/shell/browser/shell_mojo_test_utils_android.cc
@@ -56,7 +56,7 @@
       reinterpret_cast<TestEnvironment*>(native_test_environment);
 
   std::unique_ptr<shell::InterfaceRegistry> registry(
-      new shell::InterfaceRegistry(nullptr));
+      new shell::InterfaceRegistry);
   std::unique_ptr<shell::InterfaceProvider> provider(
       new shell::InterfaceProvider);
 
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 65583d1..09f0305 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -38,6 +38,10 @@
         ['linux'], bug=483282)
 
     # All platforms.
+    self.Fail('conformance/glsl/bugs/' +
+              'invariant-does-not-leak-across-shaders.html',
+              bug=634813)
+
     self.Flaky('conformance2/query/occlusion-query.html', bug=603168)
 
     # All platforms with AMD GPU.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index 70b1549..bdaeb264 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -549,6 +549,10 @@
     # ========================
     # Fails on all platforms
 
+    self.Fail('conformance/glsl/bugs/' +
+              'invariant-does-not-leak-across-shaders.html',
+              bug=634813)
+
     # We need to add WebGL 1 check in command buffer that format/type from
     # TexSubImage2D have to match the current texture's.
     self.Fail('conformance/textures/misc/tex-sub-image-2d-bad-args.html',
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java
index ebc9dc659..d487ad9 100644
--- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java
+++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothAdapter.java
@@ -19,6 +19,7 @@
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.components.location.LocationUtils;
 
+import java.util.HashSet;
 import java.util.List;
 
 /**
@@ -242,10 +243,18 @@
             Log.v(TAG, "onScanResult %d %s %s", callbackType, result.getDevice().getAddress(),
                     result.getDevice().getName());
 
+            HashSet<String> uuid_strings = new HashSet<>();
             List<ParcelUuid> uuids = result.getScanRecord_getServiceUuids();
 
+            if (uuids != null) {
+                for (ParcelUuid uuid : uuids) {
+                    uuid_strings.add(uuid.toString());
+                }
+            }
+
             nativeCreateOrUpdateDeviceOnScan(mNativeBluetoothAdapterAndroid,
-                    result.getDevice().getAddress(), result.getDevice(), uuids);
+                    result.getDevice().getAddress(), result.getDevice(),
+                    uuid_strings.toArray(new String[uuid_strings.size()]));
         }
 
         @Override
@@ -305,7 +314,7 @@
     // Wrappers.BluetoothDeviceWrapper reference is not handled by jni_generator.py JavaToJni.
     // http://crbug.com/505554
     private native void nativeCreateOrUpdateDeviceOnScan(long nativeBluetoothAdapterAndroid,
-            String address, Object bluetoothDeviceWrapper, List<ParcelUuid> advertisedUuids);
+            String address, Object bluetoothDeviceWrapper, String[] advertisedUuids);
 
     // Binds to BluetoothAdapterAndroid::nativeOnAdapterStateChanged
     private native void nativeOnAdapterStateChanged(
diff --git a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java
index 2741e7c..447326cc 100644
--- a/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java
+++ b/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothDevice.java
@@ -8,7 +8,6 @@
 import android.bluetooth.BluetoothDevice;
 import android.content.Context;
 import android.os.Build;
-import android.os.ParcelUuid;
 
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
@@ -16,8 +15,6 @@
 import org.chromium.base.annotations.JNINamespace;
 
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
 
 /**
  * Exposes android.bluetooth.BluetoothDevice as necessary for C++
@@ -32,7 +29,6 @@
 
     private long mNativeBluetoothDeviceAndroid;
     final Wrappers.BluetoothDeviceWrapper mDevice;
-    private HashSet<String> mUuidsFromScan;
     Wrappers.BluetoothGattWrapper mBluetoothGatt;
     private final BluetoothGattCallbackImpl mBluetoothGattCallbackImpl;
     final HashMap<Wrappers.BluetoothGattCharacteristicWrapper,
@@ -44,7 +40,6 @@
             long nativeBluetoothDeviceAndroid, Wrappers.BluetoothDeviceWrapper deviceWrapper) {
         mNativeBluetoothDeviceAndroid = nativeBluetoothDeviceAndroid;
         mDevice = deviceWrapper;
-        mUuidsFromScan = new HashSet<String>();
         mBluetoothGattCallbackImpl = new BluetoothGattCallbackImpl();
         mWrapperToChromeCharacteristicsMap =
                 new HashMap<Wrappers.BluetoothGattCharacteristicWrapper,
@@ -79,19 +74,6 @@
                 nativeBluetoothDeviceAndroid, (Wrappers.BluetoothDeviceWrapper) deviceWrapper);
     }
 
-    // Implements BluetoothDeviceAndroid::UpdateAdvertisedUUIDs.
-    @CalledByNative
-    private boolean updateAdvertisedUUIDs(List<ParcelUuid> uuidsFromScan) {
-        if (uuidsFromScan == null) {
-            return false;
-        }
-        boolean uuidsUpdated = false;
-        for (ParcelUuid uuid : uuidsFromScan) {
-            uuidsUpdated |= mUuidsFromScan.add(uuid.toString());
-        }
-        return uuidsUpdated;
-    }
-
     // Implements BluetoothDeviceAndroid::GetBluetoothClass.
     @CalledByNative
     private int getBluetoothClass() {
@@ -116,14 +98,6 @@
         return mDevice.getBondState() == BluetoothDevice.BOND_BONDED;
     }
 
-    // Implements BluetoothDeviceAndroid::GetUUIDs.
-    @CalledByNative
-    private String[] getUuids() {
-        // TODO(scheib): return merged list of UUIDs from scan results and,
-        // after a device is connected, discoverServices. crbug.com/508648
-        return mUuidsFromScan.toArray(new String[mUuidsFromScan.size()]);
-    }
-
     // Implements BluetoothDeviceAndroid::CreateGattConnectionImpl.
     @CalledByNative
     private void createGattConnectionImpl(Context context) {
diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h
index 5e2e8260..ba81281a 100644
--- a/device/bluetooth/bluetooth_adapter.h
+++ b/device/bluetooth/bluetooth_adapter.h
@@ -97,6 +97,11 @@
     //  * IsPaired()
     //  * IsTrustable()
     //
+    // On Android and MacOS this method is called for each advertisement packet
+    // received. On Chrome OS and Linux, we can't guarantee that this method
+    // will be called for each Adv. Packet received but, because the RSSI is
+    // always changing, it's very likely this method will be called for each
+    // Adv. Packet.
     // |device| should not be cached. Instead, copy its Bluetooth address.
     virtual void DeviceChanged(BluetoothAdapter* adapter,
                                BluetoothDevice* device) {}
diff --git a/device/bluetooth/bluetooth_adapter_android.cc b/device/bluetooth/bluetooth_adapter_android.cc
index d877899..13759fd 100644
--- a/device/bluetooth/bluetooth_adapter_android.cc
+++ b/device/bluetooth/bluetooth_adapter_android.cc
@@ -182,7 +182,7 @@
     const JavaParamRef<jstring>& address,
     const JavaParamRef<jobject>&
         bluetooth_device_wrapper,  // Java Type: bluetoothDeviceWrapper
-    const JavaParamRef<jobject>&
+    const JavaParamRef<jobjectArray>&
         advertised_uuids) {  // Java Type: List<ParcelUuid>
   std::string device_address = ConvertJavaStringToUTF8(env, address);
   DevicesMap::const_iterator iter = devices_.find(device_address);
@@ -202,10 +202,10 @@
     BluetoothDeviceAndroid* device_android =
         static_cast<BluetoothDeviceAndroid*>(iter->second);
     device_android->UpdateTimestamp();
-    if (device_android->UpdateAdvertisedUUIDs(advertised_uuids)) {
-      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
-                        DeviceChanged(this, device_android));
-    }
+    device_android->UpdateAdvertisedUUIDs(advertised_uuids);
+
+    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
+                      DeviceChanged(this, device_android));
   }
 }
 
diff --git a/device/bluetooth/bluetooth_adapter_android.h b/device/bluetooth/bluetooth_adapter_android.h
index 0a34baf..ea4adce 100644
--- a/device/bluetooth/bluetooth_adapter_android.h
+++ b/device/bluetooth/bluetooth_adapter_android.h
@@ -105,8 +105,8 @@
       const base::android::JavaParamRef<jstring>& address,
       const base::android::JavaParamRef<jobject>&
           bluetooth_device_wrapper,  // Java Type: bluetoothDeviceWrapper
-      const base::android::JavaParamRef<jobject>&
-          advertised_uuids);  // Java Type: List<ParcelUuid>
+      const base::android::JavaParamRef<jobjectArray>&
+          advertised_uuids);  // Java Type: String[]
 
  protected:
   BluetoothAdapterAndroid();
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
index 0db7131..dca907f 100644
--- a/device/bluetooth/bluetooth_adapter_mac.mm
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -515,7 +515,7 @@
   // A device has an update.
   VLOG(2) << "LowEnergyDeviceUpdated";
   device_mac->Update(advertisement_data, rssi);
-  // TODO(scheib): Call DeviceChanged only if UUIDs change. crbug.com/547106
+
   FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
                     DeviceChanged(this, device_mac));
 }
diff --git a/device/bluetooth/bluetooth_adapter_unittest.cc b/device/bluetooth/bluetooth_adapter_unittest.cc
index a262e73d..42e141df 100644
--- a/device/bluetooth/bluetooth_adapter_unittest.cc
+++ b/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -647,8 +647,8 @@
   EXPECT_EQ(1u, adapter_->GetDevices().size());
   EXPECT_EQ(device, observer.last_device());
 
-  // Expect new AND old UUIDs:
-  EXPECT_TRUE(
+  // Expect only new UUIDs:
+  EXPECT_FALSE(
       ContainsValue(device->GetUUIDs(), BluetoothUUID(kTestUUIDGenericAccess)));
   EXPECT_TRUE(ContainsValue(device->GetUUIDs(),
                             BluetoothUUID(kTestUUIDImmediateAlert)));
@@ -657,16 +657,11 @@
   observer.Reset();
   SimulateLowEnergyDevice(3);
   EXPECT_EQ(0, observer.device_added_count());
-#if defined(OS_MACOSX)
-  // TODO(scheib): Call DeviceChanged only if UUIDs change. crbug.com/547106
   EXPECT_EQ(1, observer.device_changed_count());
-#else
-  EXPECT_EQ(0, observer.device_changed_count());
-#endif
   EXPECT_EQ(1u, adapter_->GetDevices().size());
 
-  // Expect all UUIDs:
-  EXPECT_EQ(4u, device->GetUUIDs().size());
+  // Expect no UUIDs:
+  EXPECT_EQ(0u, device->GetUUIDs().size());
 }
 #endif  // defined(OS_ANDROID) || defined(OS_MACOSX)
 
diff --git a/device/bluetooth/bluetooth_device.cc b/device/bluetooth/bluetooth_device.cc
index bac4b63..6f61fae 100644
--- a/device/bluetooth/bluetooth_device.cc
+++ b/device/bluetooth/bluetooth_device.cc
@@ -243,6 +243,22 @@
   return false;
 }
 
+BluetoothDevice::UUIDList BluetoothDevice::GetUUIDs() const {
+  if (!IsGattConnected()) {
+    DCHECK(service_uuids_.empty());
+    return advertised_uuids_;
+  }
+
+  if (IsGattServicesDiscoveryComplete()) {
+    DCHECK(advertised_uuids_.empty());
+    return service_uuids_;
+  }
+
+  DCHECK(service_uuids_.empty());
+  DCHECK(advertised_uuids_.empty());
+  return BluetoothDevice::UUIDList();
+}
+
 void BluetoothDevice::CreateGattConnection(
     const GattConnectionCallback& callback,
     const ConnectErrorCallback& error_callback) {
@@ -333,6 +349,7 @@
 }
 
 void BluetoothDevice::DidConnectGatt() {
+  advertised_uuids_.clear();
   for (const auto& callback : create_gatt_connection_success_callbacks_) {
     callback.Run(
         base::WrapUnique(new BluetoothGattConnection(adapter_, GetAddress())));
@@ -379,6 +396,14 @@
     DisconnectGatt();
 }
 
+void BluetoothDevice::UpdateServiceUUIDs() {
+  std::unordered_set<BluetoothUUID, BluetoothUUIDHash> uuid_set;
+  for (const auto& gatt_service_pair : gatt_services_) {
+    uuid_set.insert(gatt_service_pair.second->GetUUID());
+  }
+  service_uuids_ = UUIDList(uuid_set.begin(), uuid_set.end());
+}
+
 void BluetoothDevice::ClearServiceData() { services_data_->Clear(); }
 
 void BluetoothDevice::SetServiceData(BluetoothUUID serviceUUID,
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h
index d7dc030..8b4c5b0 100644
--- a/device/bluetooth/bluetooth_device.h
+++ b/device/bluetooth/bluetooth_device.h
@@ -288,11 +288,21 @@
   // such as vendor and product id.
   bool IsTrustable() const;
 
-  // Returns the set of UUIDs that this device supports. For classic Bluetooth
-  // devices this data is collected from both the EIR data and SDP tables,
-  // for Low Energy devices this data is collected from AD and GATT primary
-  // services, for dual mode devices this may be collected from both./
-  virtual UUIDList GetUUIDs() const = 0;
+  // Returns the set of UUIDs that this device supports.
+  //  * For classic Bluetooth devices this data is collected from both the EIR
+  //    data and SDP tables.
+  //  * For non-connected Low Energy Devices this returns the latest advertised
+  //    UUIDs.
+  //  * For connected Low Energy Devices for which services have not been
+  //    discovered returns an empty list.
+  //  * For connected Low Energy Devices for which services have been discovered
+  //    returns the UUIDs of the device's services.
+  //  * For dual mode devices this may be collected from both.
+  //
+  // Note: On ChromeOS and Linux, Bluez persists all services meaning if
+  // a device stops advertising a service this function will still return
+  // its UUID.
+  virtual UUIDList GetUUIDs() const;
 
   // The received signal strength, in dBm. This field is avaliable and valid
   // only during discovery. If not during discovery, or RSSI wasn't reported,
@@ -492,6 +502,7 @@
  protected:
   // BluetoothGattConnection is a friend to call Add/RemoveGattConnection.
   friend BluetoothGattConnection;
+  FRIEND_TEST_ALL_PREFIXES(BluetoothTest, GetUUIDs);
   FRIEND_TEST_ALL_PREFIXES(
       BluetoothTest,
       BluetoothGattConnection_DisconnectGatt_SimulateConnect);
@@ -536,6 +547,8 @@
   void AddGattConnection(BluetoothGattConnection*);
   void RemoveGattConnection(BluetoothGattConnection*);
 
+  void UpdateServiceUUIDs();
+
   // Clears the list of service data.
   void ClearServiceData();
 
@@ -565,6 +578,12 @@
   GattServiceMap gatt_services_;
   bool gatt_services_discovery_complete_;
 
+  // Last advertised service UUIDs. Should be empty if the device is connected.
+  UUIDList advertised_uuids_;
+  // UUIDs of the device's services. Should be empty if the device is not
+  // connected or it's services have not been discovered yet.
+  UUIDList service_uuids_;
+
   // Mapping from service UUID represented as a std::string of a bluetooth
   // service to
   // the specific data. The data is stored as BinaryValue.
diff --git a/device/bluetooth/bluetooth_device_android.cc b/device/bluetooth/bluetooth_device_android.cc
index ca182ca18..bfd2ea6 100644
--- a/device/bluetooth/bluetooth_device_android.cc
+++ b/device/bluetooth/bluetooth_device_android.cc
@@ -51,9 +51,13 @@
       AttachCurrentThread(), j_device_.obj());
 }
 
-bool BluetoothDeviceAndroid::UpdateAdvertisedUUIDs(jobject advertised_uuids) {
-  return Java_ChromeBluetoothDevice_updateAdvertisedUUIDs(
-      AttachCurrentThread(), j_device_.obj(), advertised_uuids);
+void BluetoothDeviceAndroid::UpdateAdvertisedUUIDs(
+    jobjectArray advertised_uuids) {
+  JNIEnv* env = AttachCurrentThread();
+  std::vector<std::string> uuid_strings;
+  AppendJavaStringArrayToStringVector(env, advertised_uuids, &uuid_strings);
+
+  advertised_uuids_ = UUIDList(uuid_strings.begin(), uuid_strings.end());
 }
 
 // static
@@ -135,20 +139,6 @@
   return false;
 }
 
-BluetoothDevice::UUIDList BluetoothDeviceAndroid::GetUUIDs() const {
-  JNIEnv* env = AttachCurrentThread();
-  std::vector<std::string> uuid_strings;
-  AppendJavaStringArrayToStringVector(
-      env, Java_ChromeBluetoothDevice_getUuids(env, j_device_.obj()).obj(),
-      &uuid_strings);
-  BluetoothDevice::UUIDList uuids;
-  uuids.reserve(uuid_strings.size());
-  for (auto uuid_string : uuid_strings) {
-    uuids.push_back(BluetoothUUID(uuid_string));
-  }
-  return uuids;
-}
-
 int16_t BluetoothDeviceAndroid::GetInquiryRSSI() const {
   NOTIMPLEMENTED();
   return kUnknownPower;
@@ -252,6 +242,7 @@
     // Otherwise an existing connection was terminated.
     RecordConnectionTerminatedResult(status);
     gatt_services_.clear();
+    service_uuids_.clear();
     SetGattServicesDiscoveryComplete(false);
     DidDisconnectGatt();
   }
@@ -260,6 +251,7 @@
 void BluetoothDeviceAndroid::OnGattServicesDiscovered(
     JNIEnv* env,
     const JavaParamRef<jobject>& jcaller) {
+  UpdateServiceUUIDs();
   SetGattServicesDiscoveryComplete(true);
   adapter_->NotifyGattServicesDiscovered(this);
 }
diff --git a/device/bluetooth/bluetooth_device_android.h b/device/bluetooth/bluetooth_device_android.h
index 89ea49d..d4d9ca6 100644
--- a/device/bluetooth/bluetooth_device_android.h
+++ b/device/bluetooth/bluetooth_device_android.h
@@ -49,10 +49,9 @@
     return static_cast<BluetoothAdapterAndroid*>(adapter_);
   }
 
-  // Updates cached copy of advertised UUIDs discovered during a scan.
-  // Returns true if new UUIDs differed from cached values.
-  bool UpdateAdvertisedUUIDs(
-      jobject advertised_uuids);  // Java Type: List<ParcelUuid>
+  // Replaces cached copy of advertised UUIDs discovered during a scan.
+  void UpdateAdvertisedUUIDs(
+      jobjectArray advertised_uuids);  // Java Type: String[]
 
   // BluetoothDevice:
   uint32_t GetBluetoothClass() const override;
@@ -68,7 +67,6 @@
   bool IsGattConnected() const override;
   bool IsConnectable() const override;
   bool IsConnecting() const override;
-  UUIDList GetUUIDs() const override;
   int16_t GetInquiryRSSI() const override;
   int16_t GetInquiryTxPower() const override;
   bool ExpectingPinCode() const override;
diff --git a/device/bluetooth/bluetooth_device_unittest.cc b/device/bluetooth/bluetooth_device_unittest.cc
index bbfde53d..cb2d8ac9 100644
--- a/device/bluetooth/bluetooth_device_unittest.cc
+++ b/device/bluetooth/bluetooth_device_unittest.cc
@@ -118,6 +118,81 @@
 #endif  // defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
 
 #if defined(OS_ANDROID) || defined(OS_MACOSX)
+// Tests GetUUIDs returns the right UUIDs when device connects and disconnects.
+TEST_F(BluetoothTest, GetUUIDs) {
+  if (!PlatformSupportsLowEnergy()) {
+    LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+    return;
+  }
+  InitWithFakeAdapter();
+  StartLowEnergyDiscoverySession();
+  BluetoothDevice* device = SimulateLowEnergyDevice(1);
+
+  // Check advertised UUIDs:
+  EXPECT_EQ(2u, device->GetUUIDs().size());
+  EXPECT_TRUE(
+      ContainsValue(device->GetUUIDs(), BluetoothUUID(kTestUUIDGenericAccess)));
+  EXPECT_TRUE(ContainsValue(device->GetUUIDs(),
+                            BluetoothUUID(kTestUUIDGenericAttribute)));
+
+  // Connect.
+  device->CreateGattConnection(GetGattConnectionCallback(Call::EXPECTED),
+                               GetConnectErrorCallback(Call::NOT_EXPECTED));
+  TestBluetoothAdapterObserver observer(adapter_);
+  SimulateGattConnection(device);
+  ASSERT_TRUE(device->IsConnected());
+
+  // No UUIDs until services are completely discovered.
+  EXPECT_EQ(0u, device->GetUUIDs().size());
+
+  // Discover services.
+  std::vector<std::string> services;
+  services.push_back(BluetoothUUID(kTestUUIDGenericAccess).canonical_value());
+  SimulateGattServicesDiscovered(device, services);
+
+  // GetUUIDs should return UUIDs of services in device.
+  EXPECT_EQ(1u, device->GetUUIDs().size());
+  EXPECT_TRUE(
+      ContainsValue(device->GetUUIDs(), BluetoothUUID(kTestUUIDGenericAccess)));
+
+#if defined(OS_MACOSX)
+  // Android and Windows don't yet support service changed events.
+  // http://crbug.com/548280
+  // http://crbug.com/579202
+  SimulateGattServicesChanged(device);
+
+  // After service changed event we don't know what UUIDs the device has.
+  ASSERT_FALSE(device->IsGattServicesDiscoveryComplete());
+  EXPECT_EQ(0u, device->GetUUIDs().size());
+
+  SimulateGattServicesDiscovered(device, {} /* services */);
+
+  // GetUUIDs should return UUIDs of services in device.
+  EXPECT_EQ(1u, device->GetUUIDs().size());
+  EXPECT_TRUE(
+      ContainsValue(device->GetUUIDs(), BluetoothUUID(kTestUUIDGenericAccess)));
+#endif  // defined(OS_MACOSX)
+
+  // Disconnect.
+  device->DisconnectGatt();
+  SimulateGattDisconnection(device);
+
+  // After disconnection we don't know what UUIDs the device has.
+  EXPECT_EQ(0u, device->GetUUIDs().size());
+
+  // Discover the device again with different UUIDs.
+  device = SimulateLowEnergyDevice(2);
+
+  // Check advertised UUIDs.
+  EXPECT_EQ(2u, device->GetUUIDs().size());
+  EXPECT_TRUE(ContainsValue(device->GetUUIDs(),
+                            BluetoothUUID(kTestUUIDImmediateAlert)));
+  EXPECT_TRUE(
+      ContainsValue(device->GetUUIDs(), BluetoothUUID(kTestUUIDLinkLoss)));
+}
+#endif  // defined(OS_ANDROID) || defined(OS_MACOSX)
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
 // GetName for Device with no name.
 TEST_F(BluetoothTest, GetName_NullName) {
   if (!PlatformSupportsLowEnergy()) {
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.h b/device/bluetooth/bluetooth_low_energy_device_mac.h
index d41dbf9..123015cd 100644
--- a/device/bluetooth/bluetooth_low_energy_device_mac.h
+++ b/device/bluetooth/bluetooth_low_energy_device_mac.h
@@ -56,7 +56,6 @@
   bool IsGattConnected() const override;
   bool IsConnectable() const override;
   bool IsConnecting() const override;
-  BluetoothDevice::UUIDList GetUUIDs() const override;
   int16_t GetInquiryRSSI() const override;
   int16_t GetInquiryTxPower() const override;
   bool ExpectingPinCode() const override;
@@ -150,9 +149,6 @@
   // identifier.
   std::string hash_address_;
 
-  // The services (identified by UUIDs) that this device provides.
-  std::set<BluetoothUUID> advertised_uuids_;
-
   DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyDeviceMac);
 };
 
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.mm b/device/bluetooth/bluetooth_low_energy_device_mac.mm
index e335e5fb..0db9ce1 100644
--- a/device/bluetooth/bluetooth_low_energy_device_mac.mm
+++ b/device/bluetooth/bluetooth_low_energy_device_mac.mm
@@ -61,18 +61,20 @@
     SetServiceData(service_uuid, static_cast<const char*>([data bytes]),
                    [data length]);
   }
+
+  std::unordered_set<BluetoothUUID, BluetoothUUIDHash> uuid_set;
   NSArray* service_uuids =
       [advertisement_data objectForKey:CBAdvertisementDataServiceUUIDsKey];
   for (CBUUID* uuid in service_uuids) {
-    advertised_uuids_.insert(
-        BluetoothUUID(std::string([[uuid UUIDString] UTF8String])));
+    uuid_set.emplace([[uuid UUIDString] UTF8String]);
   }
   NSArray* overflow_service_uuids = [advertisement_data
       objectForKey:CBAdvertisementDataOverflowServiceUUIDsKey];
   for (CBUUID* uuid in overflow_service_uuids) {
-    advertised_uuids_.insert(
-        BluetoothUUID(std::string([[uuid UUIDString] UTF8String])));
+    uuid_set.emplace([[uuid UUIDString] UTF8String]);
   }
+
+  advertised_uuids_ = UUIDList(uuid_set.begin(), uuid_set.end());
 }
 
 std::string BluetoothLowEnergyDeviceMac::GetIdentifier() const {
@@ -141,11 +143,6 @@
   return ([peripheral_ state] == CBPeripheralStateConnecting);
 }
 
-BluetoothDevice::UUIDList BluetoothLowEnergyDeviceMac::GetUUIDs() const {
-  return BluetoothDevice::UUIDList(advertised_uuids_.begin(),
-                                   advertised_uuids_.end());
-}
-
 int16_t BluetoothLowEnergyDeviceMac::GetInquiryRSSI() const {
   return kUnknownPower;
 }
@@ -303,6 +300,7 @@
                 ->IsDiscoveryComplete();
           }) == gatt_services_.end();
   if (discovery_complete) {
+    UpdateServiceUUIDs();
     SetGattServicesDiscoveryComplete(true);
     adapter_->NotifyGattServicesDiscovered(this);
   }
@@ -318,6 +316,7 @@
         gatt_services_.take_and_erase(gatt_service->GetIdentifier());
     adapter_->NotifyGattServiceRemoved(scoped_service.get());
   }
+  service_uuids_.clear();
   SetGattServicesDiscoveryComplete(false);
   [GetPeripheral() discoverServices:nil];
 }
diff --git a/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm b/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm
index 77dafb0..eeb1ace 100644
--- a/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm
+++ b/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm
@@ -64,7 +64,15 @@
   };
 
   VLOG(1) << "TryStartDiscovery scanForPeripheralsWithServices";
-  [central_manager_ scanForPeripheralsWithServices:services options:nil];
+  // Start a scan with the Allow Duplicates option so that we get notified
+  // of each new Advertisement Packet. This allows us to provide up to date
+  // values for RSSI, Advertised Services, Advertised Data, etc.
+  [central_manager_
+      scanForPeripheralsWithServices:services
+                             options:@{
+                               CBCentralManagerScanOptionAllowDuplicatesKey :
+                                   @YES
+                             }];
   pending_ = false;
 }
 
diff --git a/device/bluetooth/test/bluetooth_test.h b/device/bluetooth/test/bluetooth_test.h
index cdb85a6..cec8fe0 100644
--- a/device/bluetooth/test/bluetooth_test.h
+++ b/device/bluetooth/test/bluetooth_test.h
@@ -136,6 +136,9 @@
       BluetoothDevice* device,
       const std::vector<std::string>& uuids) {}
 
+  // Simulates a GATT Services changed event.
+  virtual void SimulateGattServicesChanged(BluetoothDevice* device) {}
+
   // Simulates remove of a |service|.
   virtual void SimulateGattServiceRemoved(BluetoothRemoteGattService* service) {
   }
diff --git a/device/bluetooth/test/bluetooth_test_mac.h b/device/bluetooth/test/bluetooth_test_mac.h
index 455fd8f..0111e58c 100644
--- a/device/bluetooth/test/bluetooth_test_mac.h
+++ b/device/bluetooth/test/bluetooth_test_mac.h
@@ -48,6 +48,7 @@
   void SimulateGattServicesDiscovered(
       BluetoothDevice* device,
       const std::vector<std::string>& uuids) override;
+  void SimulateGattServicesChanged(BluetoothDevice* device) override;
   void SimulateGattServiceRemoved(BluetoothRemoteGattService* service) override;
   void SimulateGattCharacteristic(BluetoothRemoteGattService* service,
                                   const std::string& uuid,
diff --git a/device/bluetooth/test/bluetooth_test_mac.mm b/device/bluetooth/test/bluetooth_test_mac.mm
index 16a6ab83..5ee9944d3 100644
--- a/device/bluetooth/test/bluetooth_test_mac.mm
+++ b/device/bluetooth/test/bluetooth_test_mac.mm
@@ -247,6 +247,14 @@
   DidDiscoverServices(peripheral_mock);
 }
 
+void BluetoothTestMac::SimulateGattServicesChanged(BluetoothDevice* device) {
+  BluetoothLowEnergyDeviceMac* device_mac =
+      static_cast<BluetoothLowEnergyDeviceMac*>(device);
+  CBPeripheral* peripheral = device_mac->GetPeripheral();
+  MockCBPeripheral* peripheral_mock = ObjCCast<MockCBPeripheral>(peripheral);
+  [peripheral_mock didModifyServices:@[]];
+}
+
 void BluetoothTestMac::SimulateGattServiceRemoved(
     BluetoothRemoteGattService* service) {
   BluetoothUUID bluetooth_service_uuid = service->GetUUID();
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 2b3757b..b00a6cef 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -482,7 +482,7 @@
   GLint max_len = 0;
   glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
   if (max_len == 0) {
-    set_log_info(NULL);
+    set_log_info(nullptr);
     return;
   }
   std::unique_ptr<char[]> temp(new char[max_len]);
@@ -491,7 +491,8 @@
   DCHECK(max_len == 0 || len < max_len);
   DCHECK(len == 0 || temp[len] == '\0');
   std::string log(temp.get(), len);
-  set_log_info(ProcessLogInfo(log).c_str());
+  log = ProcessLogInfo(log);
+  set_log_info(log.empty() ? nullptr : log.c_str());
 }
 
 void Program::ClearUniforms(std::vector<uint8_t>* zero_buffer) {
diff --git a/gpu/ipc/client/gpu_channel_host.h b/gpu/ipc/client/gpu_channel_host.h
index 94fb98d..733a7e41 100644
--- a/gpu/ipc/client/gpu_channel_host.h
+++ b/gpu/ipc/client/gpu_channel_host.h
@@ -43,6 +43,19 @@
 
 namespace gpu {
 
+class GpuChannelHost;
+using GpuChannelEstablishedCallback =
+    base::Callback<void(scoped_refptr<GpuChannelHost>)>;
+
+class GPU_EXPORT GpuChannelEstablishFactory {
+ public:
+  virtual ~GpuChannelEstablishFactory() {}
+
+  virtual void EstablishGpuChannel(
+      const GpuChannelEstablishedCallback& callback) = 0;
+  virtual scoped_refptr<GpuChannelHost> EstablishGpuChannelSync() = 0;
+};
+
 class GPU_EXPORT GpuChannelHostFactory {
  public:
   virtual ~GpuChannelHostFactory() {}
diff --git a/infra/config/recipes.cfg b/infra/config/recipes.cfg
index 7815386..012c74a 100644
--- a/infra/config/recipes.cfg
+++ b/infra/config/recipes.cfg
@@ -5,13 +5,13 @@
   project_id: "build"
   url: "https://chromium.googlesource.com/chromium/tools/build.git"
   branch: "master"
-  revision: "b10eaabb7d78114de37325fe33b8f8ae703d5ca0"
+  revision: "c6d5023583562d95e3f309a86c97929490265cc2"
 }
 deps {
   project_id: "depot_tools"
   url: "https://chromium.googlesource.com/chromium/tools/depot_tools.git"
   branch: "master"
-  revision: "4b8ed59b7bab45995f48623f83dd3d46b3854f98"
+  revision: "13f9c37185750d4212a125204d22302376c77f8e"
 }
 deps {
   project_id: "recipe_engine"
diff --git a/ios/BUILD.gn b/ios/BUILD.gn
index 5a799b2..8aadf88c 100644
--- a/ios/BUILD.gn
+++ b/ios/BUILD.gn
@@ -9,6 +9,7 @@
 group("all") {
   testonly = true
   deps = [
+    "//components/sync:sync_unit_tests",
     "//ios/chrome:ios_chrome_unittests",
     "//ios/chrome/app",
     "//ios/chrome/browser",
diff --git a/ios/build/bots/tests/common_tests.json b/ios/build/bots/tests/common_tests.json
index 81f4634..f5aca97 100644
--- a/ios/build/bots/tests/common_tests.json
+++ b/ios/build/bots/tests/common_tests.json
@@ -37,6 +37,9 @@
       "app": "sql_unittests"
     },
     {
+      "app": "sync_unit_tests"
+    },
+    {
       "app": "ui_base_unittests"
     },
     {
diff --git a/ios/chrome/browser/ui/webui/mojo_web_ui_ios_controller.h b/ios/chrome/browser/ui/webui/mojo_web_ui_ios_controller.h
index c04ebb0d..c5e87e53 100644
--- a/ios/chrome/browser/ui/webui/mojo_web_ui_ios_controller.h
+++ b/ios/chrome/browser/ui/webui/mojo_web_ui_ios_controller.h
@@ -34,7 +34,7 @@
 
  private:
   // shell::InterfaceFactory overrides:
-  void Create(shell::Connection*,
+  void Create(const shell::Identity& remote_identity,
               mojo::InterfaceRequest<Interface> request) override {
     BindUIHandler(std::move(request));
   }
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index a70b99a07..72023be 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -190,8 +190,6 @@
     "web_state/js/credential_util.mm",
     "web_state/js/crw_js_injection_manager.mm",
     "web_state/js/crw_js_injection_receiver.mm",
-    "web_state/js/crw_js_invoke_parameter_queue.h",
-    "web_state/js/crw_js_invoke_parameter_queue.mm",
     "web_state/js/crw_js_plugin_placeholder_manager.h",
     "web_state/js/crw_js_plugin_placeholder_manager.mm",
     "web_state/js/crw_js_post_request_loader.h",
@@ -473,7 +471,6 @@
     "web_state/js/core_js_unittest.mm",
     "web_state/js/credential_util_unittest.mm",
     "web_state/js/crw_js_injection_manager_unittest.mm",
-    "web_state/js/crw_js_invoke_parameter_queue_unittest.mm",
     "web_state/js/crw_js_post_request_loader_unittest.mm",
     "web_state/js/crw_js_window_id_manager_unittest.mm",
     "web_state/js/page_script_util_unittest.mm",
diff --git a/ios/web/ios_web.gyp b/ios/web/ios_web.gyp
index b4759397..5c88f8d 100644
--- a/ios/web/ios_web.gyp
+++ b/ios/web/ios_web.gyp
@@ -224,8 +224,6 @@
         'web_state/js/credential_util.mm',
         'web_state/js/crw_js_injection_manager.mm',
         'web_state/js/crw_js_injection_receiver.mm',
-        'web_state/js/crw_js_invoke_parameter_queue.h',
-        'web_state/js/crw_js_invoke_parameter_queue.mm',
         'web_state/js/crw_js_plugin_placeholder_manager.h',
         'web_state/js/crw_js_plugin_placeholder_manager.mm',
         'web_state/js/crw_js_post_request_loader.h',
diff --git a/ios/web/ios_web_unittests.gyp b/ios/web/ios_web_unittests.gyp
index 51fdfac2..d4107e1a 100644
--- a/ios/web/ios_web_unittests.gyp
+++ b/ios/web/ios_web_unittests.gyp
@@ -57,7 +57,6 @@
         'web_state/js/core_js_unittest.mm',
         'web_state/js/credential_util_unittest.mm',
         'web_state/js/crw_js_injection_manager_unittest.mm',
-        'web_state/js/crw_js_invoke_parameter_queue_unittest.mm',
         'web_state/js/crw_js_post_request_loader_unittest.mm',
         'web_state/js/crw_js_window_id_manager_unittest.mm',
         'web_state/js/page_script_util_unittest.mm',
diff --git a/ios/web/web_state/js/crw_js_invoke_parameter_queue.h b/ios/web/web_state/js/crw_js_invoke_parameter_queue.h
deleted file mode 100644
index 7a6811a..0000000
--- a/ios/web/web_state/js/crw_js_invoke_parameter_queue.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_WEB_STATE_JS_CRW_JS_INVOKE_PARAMETER_QUEUE_H_
-#define IOS_WEB_WEB_STATE_JS_CRW_JS_INVOKE_PARAMETER_QUEUE_H_
-
-#import <UIKit/UIKit.h>
-
-class GURL;
-
-// Manages access to individual invoke parameters.
-@interface CRWJSInvokeParameters : NSObject
-
-// The designated initializer.
-- (id)initWithCommandString:(NSString*)commandString
-          userIsInteracting:(BOOL)userIsInteracting
-                  originURL:(const GURL&)originURL
-                forWindowId:(NSString*)windowId;
-
-// An escaped string with commands requested by JavaScript.
-@property(nonatomic, readonly) NSString* commandString;
-
-// Whether the user was interacting when the command was issued.
-@property(nonatomic, readonly) BOOL userIsInteracting;
-
-// Returns window id of the originating window.
-@property(nonatomic, readonly) NSString* windowId;
-
-// Returns URL that was current when the crwebinvoke was issued.
-@property(nonatomic, readonly) const GURL& originURL;
-
-@end
-
-
-// Stores parameters passed from JavaScript for deferred processing.
-@interface CRWJSInvokeParameterQueue : NSObject
-
-// YES if there are no more queued messages.
-@property(nonatomic, readonly) BOOL isEmpty;
-
-// Adds a new item to the queue. |commandString| is the escaped command string,
-// |userIsInteracting| is true if the user was interacting with the page,
-// |originURL| is the URL the command came from, and |windowId| is the id of the
-// window that sent the command.
-- (void)addCommandString:(NSString*)commandString
-       userIsInteracting:(BOOL)userIsInteracting
-               originURL:(const GURL&)originURL
-             forWindowId:(NSString*)windowId;
-
-// Removes from |queue_| any CRWJSInvokeParameters whose command string contains
-// |commandString|.
-- (void)removeCommandString:(NSString*)commandString;
-
-// Removes the oldest item from the queue and returns it.
-- (CRWJSInvokeParameters*)popInvokeParameters;
-
-@end
-
-@interface CRWJSInvokeParameterQueue (Testing)
-// The number of items in the queue.
-@property(nonatomic, readonly) NSUInteger queueLength;
-@end
-
-#endif  // IOS_WEB_WEB_STATE_JS_CRW_JS_INVOKE_PARAMETER_QUEUE_H_
diff --git a/ios/web/web_state/js/crw_js_invoke_parameter_queue.mm b/ios/web/web_state/js/crw_js_invoke_parameter_queue.mm
deleted file mode 100644
index 403bcb7..0000000
--- a/ios/web/web_state/js/crw_js_invoke_parameter_queue.mm
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/web/web_state/js/crw_js_invoke_parameter_queue.h"
-
-#import "base/mac/scoped_nsobject.h"
-#include "url/gurl.h"
-
-@implementation CRWJSInvokeParameters {
-  base::scoped_nsobject<NSString> _commandString;
-  BOOL _userIsInteracting;
-  base::scoped_nsobject<NSString> _windowId;
-  GURL _originURL;
-}
-
-@synthesize userIsInteracting = _userIsInteracting;
-
-- (id)initWithCommandString:(NSString*)commandString
-          userIsInteracting:(BOOL)userIsInteracting
-                  originURL:(const GURL&)originURL
-                forWindowId:(NSString*)windowId {
-  if ((self = [super init])) {
-    _commandString.reset([commandString copy]);
-    _userIsInteracting = userIsInteracting;
-    _windowId.reset([windowId copy]);
-    _originURL = originURL;
-  }
-  return self;
-}
-
-- (NSString*)commandString {
-  return _commandString.get();
-}
-
-- (NSString*)windowId {
-  return _windowId.get();
-}
-
-- (const GURL&)originURL {
-  return _originURL;
-}
-
-@end
-
-@implementation CRWJSInvokeParameterQueue {
-  base::scoped_nsobject<NSMutableArray> _queue;
-}
-
-- (id)init {
-  if ((self = [super init])) {
-    // Under normal circumstainces there will be maximum one message queued.
-    _queue.reset([[NSMutableArray arrayWithCapacity:1] retain]);
-  }
-  return self;
-}
-
-- (BOOL)isEmpty {
-  return [_queue count] == 0;
-}
-
-- (NSUInteger)queueLength {
-  return [_queue count];
-}
-
-- (void)addCommandString:(NSString*)commandString
-       userIsInteracting:(BOOL)userIsInteracting
-               originURL:(const GURL&)originURL
-             forWindowId:(NSString*)windowId {
-  base::scoped_nsobject<CRWJSInvokeParameters> invokeParameters(
-      [[CRWJSInvokeParameters alloc] initWithCommandString:commandString
-                                         userIsInteracting:userIsInteracting
-                                                 originURL:originURL
-                                               forWindowId:windowId]);
-  [_queue addObject:invokeParameters];
-}
-
-- (void)removeCommandString:(NSString*)commandString {
-  NSMutableArray* commandsToRemove = [NSMutableArray array];
-  for (CRWJSInvokeParameters* params in _queue.get()) {
-    NSRange range =
-        [[params commandString] rangeOfString:commandString
-                                      options:NSCaseInsensitiveSearch];
-    if (range.location != NSNotFound)
-      [commandsToRemove addObject:params];
-  }
-  [_queue removeObjectsInArray:commandsToRemove];
-}
-
-- (CRWJSInvokeParameters*)popInvokeParameters {
-  if (![_queue count])
-    return nil;
-  CRWJSInvokeParameters* invokeParameters =
-      [[[_queue objectAtIndex:0] retain] autorelease];
-  [_queue removeObjectAtIndex:0];
-  return invokeParameters;
-}
-
-@end
diff --git a/ios/web/web_state/js/crw_js_invoke_parameter_queue_unittest.mm b/ios/web/web_state/js/crw_js_invoke_parameter_queue_unittest.mm
deleted file mode 100644
index 5be2fa8..0000000
--- a/ios/web/web_state/js/crw_js_invoke_parameter_queue_unittest.mm
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/web/web_state/js/crw_js_invoke_parameter_queue.h"
-
-#include "base/mac/scoped_nsobject.h"
-#include "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-#include "url/gurl.h"
-
-namespace {
-
-class CRWJSInvokeParameterQueueTest : public PlatformTest {
- public:
-  CRWJSInvokeParameterQueueTest() {}
-  ~CRWJSInvokeParameterQueueTest() override {}
-  void SetUp() override;
-  void TearDown() override;
-
- protected:
-  base::scoped_nsobject<CRWJSInvokeParameterQueue> js_invoke_parameter_queue_;
-};
-
-void CRWJSInvokeParameterQueueTest::SetUp() {
-  js_invoke_parameter_queue_.reset([[CRWJSInvokeParameterQueue alloc] init]);
-}
-
-void CRWJSInvokeParameterQueueTest::TearDown() {
-  js_invoke_parameter_queue_.reset();
-}
-
-TEST_F(CRWJSInvokeParameterQueueTest, testRemoveFromEmptyQueue) {
-  EXPECT_TRUE([js_invoke_parameter_queue_ isEmpty]);
-  EXPECT_NSEQ(nil, [js_invoke_parameter_queue_ popInvokeParameters]);
-}
-
-TEST_F(CRWJSInvokeParameterQueueTest, testFifoOrdering) {
-  GURL url1("http://url1.example.com/path1");
-  GURL url2("https://url2.example.com/path2");
-  EXPECT_TRUE([js_invoke_parameter_queue_ isEmpty]);
-  [js_invoke_parameter_queue_ addCommandString:@"command1"
-                             userIsInteracting:YES
-                                     originURL:url1
-                                   forWindowId:@"one"];
-  [js_invoke_parameter_queue_ addCommandString:@"command2"
-                             userIsInteracting:NO
-                                     originURL:url2
-                                   forWindowId:@"two"];
-  EXPECT_FALSE([js_invoke_parameter_queue_ isEmpty]);
-
-  CRWJSInvokeParameters* param1 =
-      [js_invoke_parameter_queue_ popInvokeParameters];
-  EXPECT_NSEQ(@"command1", [param1 commandString]);
-  EXPECT_TRUE([param1 userIsInteracting]);
-  EXPECT_EQ(url1, [param1 originURL]);
-  EXPECT_NSEQ(@"one", [param1 windowId]);
-
-  CRWJSInvokeParameters* param2 =
-      [js_invoke_parameter_queue_ popInvokeParameters];
-  EXPECT_NSEQ(@"command2", [param2 commandString]);
-  EXPECT_FALSE([param2 userIsInteracting]);
-  EXPECT_EQ(url2, [param2 originURL]);
-  EXPECT_NSEQ(@"two", [param2 windowId]);
-
-  EXPECT_TRUE([js_invoke_parameter_queue_ isEmpty]);
-  EXPECT_NSEQ(nil, [js_invoke_parameter_queue_ popInvokeParameters]);
-}
-
-}  // namespace
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm
index df1a635..7f27fa7 100644
--- a/ios/web/web_state/ui/crw_web_controller_unittest.mm
+++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -31,7 +31,6 @@
 #import "ios/web/test/web_test_with_web_controller.h"
 #import "ios/web/test/wk_web_view_crash_utils.h"
 #include "ios/web/web_state/blocked_popup_info.h"
-#import "ios/web/web_state/js/crw_js_invoke_parameter_queue.h"
 #import "ios/web/web_state/ui/crw_web_controller_container_view.h"
 #import "ios/web/web_state/web_state_impl.h"
 #import "ios/web/web_state/wk_web_view_security_util.h"
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index 69d966d07..22227dde 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -542,7 +542,7 @@
 
 shell::InterfaceRegistry* WebStateImpl::GetMojoInterfaceRegistry() {
   if (!mojo_interface_registry_) {
-    mojo_interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+    mojo_interface_registry_.reset(new shell::InterfaceRegistry);
   }
   return mojo_interface_registry_.get();
 }
diff --git a/ios/web/webui/mojo_facade_unittest.mm b/ios/web/webui/mojo_facade_unittest.mm
index a88b236..669ed4b 100644
--- a/ios/web/webui/mojo_facade_unittest.mm
+++ b/ios/web/webui/mojo_facade_unittest.mm
@@ -61,7 +61,7 @@
 class MojoFacadeTest : public WebTest {
  protected:
   MojoFacadeTest() {
-    interface_registry_.reset(new shell::InterfaceRegistry(nullptr));
+    interface_registry_.reset(new shell::InterfaceRegistry);
     interface_registry_->AddInterface(&ui_handler_factory_);
     evaluator_.reset([[OCMockObject
         mockForProtocol:@protocol(CRWJSInjectionEvaluator)] retain]);
diff --git a/mash/app_driver/app_driver.cc b/mash/app_driver/app_driver.cc
index 19de487..db42859 100644
--- a/mash/app_driver/app_driver.cc
+++ b/mash/app_driver/app_driver.cc
@@ -91,7 +91,8 @@
   AddAccelerators();
 }
 
-bool AppDriver::OnConnect(shell::Connection* connection) {
+bool AppDriver::OnConnect(const shell::Identity& remote_identity,
+                          shell::InterfaceRegistry* registry) {
   return true;
 }
 
diff --git a/mash/app_driver/app_driver.h b/mash/app_driver/app_driver.h
index ebebce6..1664b175 100644
--- a/mash/app_driver/app_driver.h
+++ b/mash/app_driver/app_driver.h
@@ -31,7 +31,8 @@
 
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
   bool OnStop() override;
 
   // ui::mojom::AcceleratorHandler:
diff --git a/mash/browser/browser.cc b/mash/browser/browser.cc
index bf2c4a6a..1f74ce8 100644
--- a/mash/browser/browser.cc
+++ b/mash/browser/browser.cc
@@ -874,8 +874,9 @@
       views::WindowManagerConnection::Create(connector(), identity);
 }
 
-bool Browser::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Launchable>(this);
+bool Browser::OnConnect(const shell::Identity& remote_identity,
+                        shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Launchable>(this);
   return true;
 }
 
diff --git a/mash/browser/browser.h b/mash/browser/browser.h
index 4995fce..a0b945d9 100644
--- a/mash/browser/browser.h
+++ b/mash/browser/browser.h
@@ -44,7 +44,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mojom::Launchable:
   void Launch(uint32_t what, mojom::LaunchMode how) override;
diff --git a/mash/catalog_viewer/catalog_viewer.cc b/mash/catalog_viewer/catalog_viewer.cc
index e86c5ef..7af4a71d 100644
--- a/mash/catalog_viewer/catalog_viewer.cc
+++ b/mash/catalog_viewer/catalog_viewer.cc
@@ -175,8 +175,9 @@
       views::WindowManagerConnection::Create(connector(), identity);
 }
 
-bool CatalogViewer::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Launchable>(this);
+bool CatalogViewer::OnConnect(const shell::Identity& remote_identity,
+                              shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Launchable>(this);
   return true;
 }
 
diff --git a/mash/catalog_viewer/catalog_viewer.h b/mash/catalog_viewer/catalog_viewer.h
index 78b659e9..8d66a269 100644
--- a/mash/catalog_viewer/catalog_viewer.h
+++ b/mash/catalog_viewer/catalog_viewer.h
@@ -36,7 +36,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mojom::Launchable:
   void Launch(uint32_t what, mojom::LaunchMode how) override;
diff --git a/mash/example/views_examples/views_examples.cc b/mash/example/views_examples/views_examples.cc
index 49b4fe1..9585f723 100644
--- a/mash/example/views_examples/views_examples.cc
+++ b/mash/example/views_examples/views_examples.cc
@@ -40,8 +40,9 @@
     window_manager_connection_ =
         views::WindowManagerConnection::Create(connector(), identity);
   }
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<mash::mojom::Launchable>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<mash::mojom::Launchable>(this);
     return true;
   }
 
diff --git a/mash/example/window_type_launcher/window_type_launcher.cc b/mash/example/window_type_launcher/window_type_launcher.cc
index c428456..9372c8c 100644
--- a/mash/example/window_type_launcher/window_type_launcher.cc
+++ b/mash/example/window_type_launcher/window_type_launcher.cc
@@ -496,8 +496,9 @@
       views::WindowManagerConnection::Create(connector(), identity);
 }
 
-bool WindowTypeLauncher::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mash::mojom::Launchable>(this);
+bool WindowTypeLauncher::OnConnect(const shell::Identity& remote_identity,
+                                   shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mash::mojom::Launchable>(this);
   return true;
 }
 
diff --git a/mash/example/window_type_launcher/window_type_launcher.h b/mash/example/window_type_launcher/window_type_launcher.h
index 7d74eaf4..53f13d1 100644
--- a/mash/example/window_type_launcher/window_type_launcher.h
+++ b/mash/example/window_type_launcher/window_type_launcher.h
@@ -31,7 +31,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mash::mojom::Launchable:
   void Launch(uint32_t what, mash::mojom::LaunchMode how) override;
diff --git a/mash/init/init.cc b/mash/init/init.cc
index eb63322..0a5506da 100644
--- a/mash/init/init.cc
+++ b/mash/init/init.cc
@@ -23,8 +23,9 @@
   StartLogin();
 }
 
-bool Init::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Init>(this);
+bool Init::OnConnect(const shell::Identity& remote_identity,
+                     shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Init>(this);
   return true;
 }
 
diff --git a/mash/init/init.h b/mash/init/init.h
index e54a1681..7350a557 100644
--- a/mash/init/init.h
+++ b/mash/init/init.h
@@ -32,7 +32,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // shell::InterfaceFactory<mojom::Login>:
   void Create(const shell::Identity& remote_identity,
diff --git a/mash/login/login.cc b/mash/login/login.cc
index f6fd46cc..c9297fc 100644
--- a/mash/login/login.cc
+++ b/mash/login/login.cc
@@ -158,8 +158,9 @@
     connector()->ConnectToInterface("mojo:ui", &user_access_manager_);
     user_access_manager_->SetActiveUser(identity.user_id());
   }
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<mojom::Login>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<mojom::Login>(this);
     return true;
   }
 
diff --git a/mash/quick_launch/quick_launch.cc b/mash/quick_launch/quick_launch.cc
index 1128266..0c19334 100644
--- a/mash/quick_launch/quick_launch.cc
+++ b/mash/quick_launch/quick_launch.cc
@@ -174,8 +174,9 @@
   Launch(mojom::kWindow, mojom::LaunchMode::MAKE_NEW);
 }
 
-bool QuickLaunch::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Launchable>(this);
+bool QuickLaunch::OnConnect(const shell::Identity& remote_identity,
+                            shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Launchable>(this);
   return true;
 }
 
diff --git a/mash/quick_launch/quick_launch.h b/mash/quick_launch/quick_launch.h
index 54b0dc3..dc6b4957 100644
--- a/mash/quick_launch/quick_launch.h
+++ b/mash/quick_launch/quick_launch.h
@@ -34,7 +34,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mojom::Launchable:
   void Launch(uint32_t what, mojom::LaunchMode how) override;
diff --git a/mash/session/session.cc b/mash/session/session.cc
index c53e02af..8b137576 100644
--- a/mash/session/session.cc
+++ b/mash/session/session.cc
@@ -34,8 +34,9 @@
   StartQuickLaunch();
 }
 
-bool Session::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Session>(this);
+bool Session::OnConnect(const shell::Identity& remote_identity,
+                        shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Session>(this);
   return true;
 }
 
diff --git a/mash/session/session.h b/mash/session/session.h
index a48e889..b71f613 100644
--- a/mash/session/session.h
+++ b/mash/session/session.h
@@ -33,7 +33,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mojom::Session:
   void Logout() override;
diff --git a/mash/task_viewer/task_viewer.cc b/mash/task_viewer/task_viewer.cc
index 1942dd6..68a04987 100644
--- a/mash/task_viewer/task_viewer.cc
+++ b/mash/task_viewer/task_viewer.cc
@@ -294,8 +294,9 @@
       views::WindowManagerConnection::Create(connector(), identity);
 }
 
-bool TaskViewer::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Launchable>(this);
+bool TaskViewer::OnConnect(const shell::Identity& remote_identity,
+                           shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Launchable>(this);
   return true;
 }
 
diff --git a/mash/task_viewer/task_viewer.h b/mash/task_viewer/task_viewer.h
index 378262b..8e9866f7 100644
--- a/mash/task_viewer/task_viewer.h
+++ b/mash/task_viewer/task_viewer.h
@@ -36,7 +36,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mojom::Launchable:
   void Launch(uint32_t what, mojom::LaunchMode how) override;
diff --git a/mash/webtest/webtest.cc b/mash/webtest/webtest.cc
index 87f5787..57bf47c1 100644
--- a/mash/webtest/webtest.cc
+++ b/mash/webtest/webtest.cc
@@ -166,8 +166,9 @@
       views::WindowManagerConnection::Create(connector(), identity);
 }
 
-bool Webtest::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Launchable>(this);
+bool Webtest::OnConnect(const shell::Identity& remote_identity,
+                        shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Launchable>(this);
   return true;
 }
 
diff --git a/mash/webtest/webtest.h b/mash/webtest/webtest.h
index e3d88736..afd8d8d 100644
--- a/mash/webtest/webtest.h
+++ b/mash/webtest/webtest.h
@@ -36,7 +36,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // mojom::Launchable:
   void Launch(uint32_t what, mojom::LaunchMode how) override;
diff --git a/media/mojo/services/mojo_media_application.cc b/media/mojo/services/mojo_media_application.cc
index 0fc1825a..3e49190e 100644
--- a/media/mojo/services/mojo_media_application.cc
+++ b/media/mojo/services/mojo_media_application.cc
@@ -30,8 +30,9 @@
   mojo_media_client_->Initialize();
 }
 
-bool MojoMediaApplication::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::MediaService>(this);
+bool MojoMediaApplication::OnConnect(const shell::Identity& remote_identity,
+                                     shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::MediaService>(this);
   return true;
 }
 
diff --git a/media/mojo/services/mojo_media_application.h b/media/mojo/services/mojo_media_application.h
index 74a14ae9..e143e32 100644
--- a/media/mojo/services/mojo_media_application.h
+++ b/media/mojo/services/mojo_media_application.h
@@ -38,7 +38,8 @@
  private:
   // shell::Service implementation.
   void OnStart(const shell::Identity& identity) final;
-  bool OnConnect(shell::Connection* connection) final;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) final;
   bool OnStop() final;
 
   // shell::InterfaceFactory<mojom::MediaService> implementation.
diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc
index a3ef2cd..912ecee 100644
--- a/mojo/edk/system/node_controller.cc
+++ b/mojo/edk/system/node_controller.cc
@@ -652,19 +652,28 @@
 }
 
 void NodeController::AcceptIncomingMessages() {
-  {
-    base::AutoLock lock(messages_lock_);
-    if (!incoming_messages_.empty()) {
-      // libstdc++'s deque creates an internal buffer on construction, even when
-      // the size is 0. So avoid creating it until it is necessary.
-      std::queue<ports::ScopedMessage> messages;
-      std::swap(messages, incoming_messages_);
-      base::AutoUnlock unlock(messages_lock_);
+  while (incoming_messages_flag_) {
+    // TODO: We may need to be more careful to avoid starving the rest of the
+    // thread here. Revisit this if it turns out to be a problem. One
+    // alternative would be to schedule a task to continue pumping messages
+    // after flushing once.
 
-      while (!messages.empty()) {
-        node_->AcceptMessage(std::move(messages.front()));
-        messages.pop();
-      }
+    messages_lock_.Acquire();
+    if (incoming_messages_.empty()) {
+      messages_lock_.Release();
+      break;
+    }
+
+    // libstdc++'s deque creates an internal buffer on construction, even when
+    // the size is 0. So avoid creating it until it is necessary.
+    std::queue<ports::ScopedMessage> messages;
+    std::swap(messages, incoming_messages_);
+    incoming_messages_flag_.Set(false);
+    messages_lock_.Release();
+
+    while (!messages.empty()) {
+      node_->AcceptMessage(std::move(messages.front()));
+      messages.pop();
     }
   }
 
@@ -746,6 +755,7 @@
         !incoming_messages_task_posted_;
     incoming_messages_task_posted_ |= schedule_pump_task;
     incoming_messages_.emplace(std::move(message));
+    incoming_messages_flag_.Set(true);
   } else {
     SendPeerMessage(node, std::move(message));
   }
@@ -1261,7 +1271,8 @@
     base::AutoLock lock(shutdown_lock_);
     if (shutdown_callback_.is_null())
       return;
-    if (!node_->CanShutdownCleanly(true /* allow_local_ports */)) {
+    if (!node_->CanShutdownCleanly(
+          ports::Node::ShutdownPolicy::ALLOW_LOCAL_PORTS)) {
       DVLOG(2) << "Unable to cleanly shut down node " << name_;
       return;
     }
diff --git a/mojo/edk/system/node_controller.h b/mojo/edk/system/node_controller.h
index 11d5f19..2cdcd90 100644
--- a/mojo/edk/system/node_controller.h
+++ b/mojo/edk/system/node_controller.h
@@ -286,6 +286,8 @@
   // Ensures that there is only one incoming messages task posted to the IO
   // thread.
   bool incoming_messages_task_posted_ = false;
+  // Flag to fast-path checking |incoming_messages_|.
+  AtomicFlag incoming_messages_flag_;
 
   // Guards |shutdown_callback_|.
   base::Lock shutdown_lock_;
diff --git a/mojo/edk/system/ports/node.cc b/mojo/edk/system/ports/node.cc
index 128ecdf..c7f42f6 100644
--- a/mojo/edk/system/ports/node.cc
+++ b/mojo/edk/system/ports/node.cc
@@ -64,10 +64,10 @@
     DLOG(WARNING) << "Unclean shutdown for node " << name_;
 }
 
-bool Node::CanShutdownCleanly(bool allow_local_ports) {
+bool Node::CanShutdownCleanly(ShutdownPolicy policy) {
   base::AutoLock ports_lock(ports_lock_);
 
-  if (!allow_local_ports) {
+  if (policy == ShutdownPolicy::DONT_ALLOW_LOCAL_PORTS) {
 #if DCHECK_IS_ON()
     for (auto entry : ports_) {
       DVLOG(2) << "Port " << entry.first << " referencing node "
@@ -78,6 +78,8 @@
     return ports_.empty();
   }
 
+  DCHECK_EQ(policy, ShutdownPolicy::ALLOW_LOCAL_PORTS);
+
   // NOTE: This is not efficient, though it probably doesn't need to be since
   // relatively few ports should be open during shutdown and shutdown doesn't
   // need to be blazingly fast.
@@ -531,17 +533,6 @@
   scoped_refptr<Port> port = GetPort(port_name);
   if (!port) {
     DVLOG(1) << "ObserveProxy: " << port_name << "@" << name_ << " not found";
-
-    if (port_name != event.proxy_port_name &&
-        port_name != event.proxy_to_port_name) {
-      // The receiving port may have been removed while this message was in
-      // transit.  In this case, we restart the ObserveProxy circulation from
-      // the referenced proxy port to avoid leaking the proxy.
-      delegate_->ForwardMessage(
-          event.proxy_node_name,
-          NewInternalMessage(
-              event.proxy_port_name, EventType::kObserveProxy, event));
-    }
     return OK;
   }
 
diff --git a/mojo/edk/system/ports/node.h b/mojo/edk/system/ports/node.h
index 3aeadca..65252a3 100644
--- a/mojo/edk/system/ports/node.h
+++ b/mojo/edk/system/ports/node.h
@@ -48,6 +48,11 @@
 
 class Node {
  public:
+  enum class ShutdownPolicy {
+    DONT_ALLOW_LOCAL_PORTS,
+    ALLOW_LOCAL_PORTS,
+  };
+
   // Does not take ownership of the delegate.
   Node(const NodeName& name, NodeDelegate* delegate);
   ~Node();
@@ -59,9 +64,11 @@
   // method may be called again after AcceptMessage to check if the Node is now
   // ready to be destroyed.
   //
-  // If |allow_local_ports| is |true|, this will only return |false| when there
-  // are transient ports referring to other nodes.
-  bool CanShutdownCleanly(bool allow_local_ports);
+  // If |policy| is set to |ShutdownPolicy::ALLOW_LOCAL_PORTS|, this will return
+  // |true| even if some ports remain alive, as long as none of them are proxies
+  // to another node.
+  bool CanShutdownCleanly(
+      ShutdownPolicy policy = ShutdownPolicy::DONT_ALLOW_LOCAL_PORTS);
 
   // Lookup the named port.
   int GetPort(const PortName& port_name, PortRef* port_ref);
diff --git a/mojo/edk/system/ports/ports_unittest.cc b/mojo/edk/system/ports/ports_unittest.cc
index 200e72bb..b76fa10d 100644
--- a/mojo/edk/system/ports/ports_unittest.cc
+++ b/mojo/edk/system/ports/ports_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -9,9 +10,18 @@
 #include <map>
 #include <queue>
 #include <sstream>
+#include <utility>
 
+#include "base/bind.h"
+#include "base/callback.h"
 #include "base/logging.h"
+#include "base/memory/ref_counted.h"
 #include "base/rand_util.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
 #include "mojo/edk/system/ports/event.h"
 #include "mojo/edk/system/ports/node.h"
 #include "mojo/edk/system/ports/node_delegate.h"
@@ -24,24 +34,8 @@
 
 namespace {
 
-void LogMessage(const Message* message) {
-  std::stringstream ports;
-  for (size_t i = 0; i < message->num_ports(); ++i) {
-    if (i > 0)
-      ports << ",";
-    ports << message->ports()[i];
-  }
-  DVLOG(1) << "message: \""
-           << static_cast<const char*>(message->payload_bytes())
-           << "\" ports=[" << ports.str() << "]";
-}
-
-void ClosePortsInMessage(Node* node, Message* message) {
-  for (size_t i = 0; i < message->num_ports(); ++i) {
-    PortRef port;
-    ASSERT_EQ(OK, node->GetPort(message->ports()[i], &port));
-    EXPECT_EQ(OK, node->ClosePort(port));
-  }
+bool MessageEquals(const ScopedMessage& message, const base::StringPiece& s) {
+  return !strcmp(static_cast<const char*>(message->payload_bytes()), s.data());
 }
 
 class TestMessage : public Message {
@@ -71,132 +65,140 @@
   }
 };
 
-struct Task {
-  Task(NodeName node_name, ScopedMessage message)
-      : node_name(node_name),
-        message(std::move(message)),
-        priority(base::RandUint64()) {
-  }
+class TestNode;
 
-  NodeName node_name;
-  ScopedMessage message;
-  uint64_t priority;
-};
-
-struct TaskComparator {
-  bool operator()(const Task* a, const Task* b) {
-    return a->priority < b->priority;
-  }
-};
-
-const size_t kMaxNodes = 3;
-
-std::priority_queue<Task*, std::vector<Task*>, TaskComparator> task_queue;
-Node* node_map[kMaxNodes];
-
-Node* GetNode(const NodeName& name) {
-  return node_map[name.v1];
-}
-
-void SetNode(const NodeName& name, Node* node) {
-  node_map[name.v1] = node;
-}
-
-void PumpTasks() {
-  while (!task_queue.empty()) {
-    Task* task = task_queue.top();
-    task_queue.pop();
-
-    Node* node = GetNode(task->node_name);
-    if (node)
-      node->AcceptMessage(std::move(task->message));
-
-    delete task;
-  }
-}
-
-void PumpUntilTask(EventType type) {
-  while (!task_queue.empty()) {
-    Task* task = task_queue.top();
-
-    const EventHeader* header = GetEventHeader(*task->message);
-    if (header->type == type)
-      return;
-
-    task_queue.pop();
-
-    Node* node = GetNode(task->node_name);
-    if (node)
-      node->AcceptMessage(std::move(task->message));
-
-    delete task;
-  }
-}
-
-void DiscardPendingTasks() {
-  while (!task_queue.empty()) {
-    Task* task = task_queue.top();
-    task_queue.pop();
-    delete task;
-  }
-}
-
-int SendStringMessage(Node* node, const PortRef& port, const std::string& s) {
-  size_t size = s.size() + 1;
-  ScopedMessage message = TestMessage::NewUserMessage(size, 0);
-  memcpy(message->mutable_payload_bytes(), s.data(), size);
-  return node->SendMessage(port, std::move(message));
-}
-
-int SendStringMessageWithPort(Node* node,
-                              const PortRef& port,
-                              const std::string& s,
-                              const PortName& sent_port_name) {
-  size_t size = s.size() + 1;
-  ScopedMessage message = TestMessage::NewUserMessage(size, 1);
-  memcpy(message->mutable_payload_bytes(), s.data(), size);
-  message->mutable_ports()[0] = sent_port_name;
-  return node->SendMessage(port, std::move(message));
-}
-
-int SendStringMessageWithPort(Node* node,
-                              const PortRef& port,
-                              const std::string& s,
-                              const PortRef& sent_port) {
-  return SendStringMessageWithPort(node, port, s, sent_port.name());
-}
-
-const char* ToString(const ScopedMessage& message) {
-  return static_cast<const char*>(message->payload_bytes());
-}
-
-class TestNodeDelegate : public NodeDelegate {
+class MessageRouter {
  public:
-  explicit TestNodeDelegate(const NodeName& node_name)
-      : node_name_(node_name),
-        drop_messages_(false),
-        read_messages_(true),
-        save_messages_(false) {
+  virtual ~MessageRouter() {}
+
+  virtual void GeneratePortName(PortName* name) = 0;
+  virtual void ForwardMessage(TestNode* from_node,
+                              const NodeName& node_name,
+                              ScopedMessage message) = 0;
+  virtual void BroadcastMessage(TestNode* from_node, ScopedMessage message) = 0;
+};
+
+class TestNode : public NodeDelegate {
+ public:
+  explicit TestNode(uint64_t id)
+      : node_name_(id, 1),
+        node_(node_name_, this),
+        node_thread_(base::StringPrintf("Node %" PRIu64 " thread", id)),
+        messages_available_event_(
+            base::WaitableEvent::ResetPolicy::AUTOMATIC,
+            base::WaitableEvent::InitialState::NOT_SIGNALED),
+        idle_event_(
+            base::WaitableEvent::ResetPolicy::MANUAL,
+            base::WaitableEvent::InitialState::SIGNALED) {
   }
 
-  void set_drop_messages(bool value) { drop_messages_ = value; }
-  void set_read_messages(bool value) { read_messages_ = value; }
-  void set_save_messages(bool value) { save_messages_ = value; }
+  ~TestNode() override {
+    StopWhenIdle();
+    node_thread_.Stop();
+  }
+
+  const NodeName& name() const { return node_name_; }
+
+  // NOTE: Node is thread-safe.
+  Node& node() { return node_; }
+
+  base::WaitableEvent& idle_event() { return idle_event_; }
+
+  bool IsIdle() {
+    base::AutoLock lock(lock_);
+    return started_ && !dispatching_ &&
+        (incoming_messages_.empty() || (block_on_event_ && blocked_));
+  }
+
+  void BlockOnEvent(EventType type) {
+    base::AutoLock lock(lock_);
+    blocked_event_type_ = type;
+    block_on_event_ = true;
+  }
+
+  void Unblock() {
+    base::AutoLock lock(lock_);
+    block_on_event_ = false;
+    messages_available_event_.Signal();
+  }
+
+  void Start(MessageRouter* router) {
+    router_ = router;
+    node_thread_.Start();
+    node_thread_.task_runner()->PostTask(
+        FROM_HERE,
+        base::Bind(&TestNode::ProcessMessages, base::Unretained(this)));
+  }
+
+  void StopWhenIdle() {
+    base::AutoLock lock(lock_);
+    should_quit_ = true;
+    messages_available_event_.Signal();
+  }
+
+  void WakeUp() { messages_available_event_.Signal(); }
+
+  int SendStringMessage(const PortRef& port, const std::string& s) {
+    size_t size = s.size() + 1;
+    ScopedMessage message = TestMessage::NewUserMessage(size, 0);
+    memcpy(message->mutable_payload_bytes(), s.data(), size);
+    return node_.SendMessage(port, std::move(message));
+  }
+
+  int SendStringMessageWithPort(const PortRef& port,
+                                const std::string& s,
+                                const PortName& sent_port_name) {
+    size_t size = s.size() + 1;
+    ScopedMessage message = TestMessage::NewUserMessage(size, 1);
+    memcpy(message->mutable_payload_bytes(), s.data(), size);
+    message->mutable_ports()[0] = sent_port_name;
+    return node_.SendMessage(port, std::move(message));
+  }
+
+  int SendStringMessageWithPort(const PortRef& port,
+                                const std::string& s,
+                                const PortRef& sent_port) {
+    return SendStringMessageWithPort(port, s, sent_port.name());
+  }
+
+  void set_drop_messages(bool value) {
+    base::AutoLock lock(lock_);
+    drop_messages_ = value;
+  }
+
+  void set_save_messages(bool value) {
+    base::AutoLock lock(lock_);
+    save_messages_ = value;
+  }
+
+  bool ReadMessage(const PortRef& port, ScopedMessage* message) {
+    return node_.GetMessage(port, message) == OK && *message;
+  }
 
   bool GetSavedMessage(ScopedMessage* message) {
+    base::AutoLock lock(lock_);
     if (saved_messages_.empty()) {
       message->reset();
       return false;
     }
-    *message = std::move(saved_messages_.front());
+    std::swap(*message, saved_messages_.front());
     saved_messages_.pop();
     return true;
   }
 
+  void EnqueueMessage(ScopedMessage message) {
+    idle_event_.Reset();
+
+    // NOTE: This may be called from ForwardMessage and thus must not reenter
+    // |node_|.
+    base::AutoLock lock(lock_);
+    incoming_messages_.emplace(std::move(message));
+    messages_available_event_.Signal();
+  }
+
   void GenerateRandomPortName(PortName* port_name) override {
-    static uint64_t next_port_name = 1;
-    port_name->v1 = next_port_name++;
-    port_name->v2 = 0;
+    DCHECK(router_);
+    router_->GeneratePortName(port_name);
   }
 
   void AllocMessage(size_t num_header_bytes, ScopedMessage* message) override {
@@ -205,489 +207,568 @@
 
   void ForwardMessage(const NodeName& node_name,
                       ScopedMessage message) override {
-    if (drop_messages_) {
-      DVLOG(1) << "Dropping ForwardMessage from node "
-               << node_name_ << " to " << node_name;
-      ClosePortsInMessage(GetNode(node_name), message.get());
-      return;
+    {
+      base::AutoLock lock(lock_);
+      if (drop_messages_) {
+        DVLOG(1) << "Dropping ForwardMessage from node "
+                 << node_name_ << " to " << node_name;
+
+        base::AutoUnlock unlock(lock_);
+        ClosePortsInMessage(message.get());
+        return;
+      }
     }
+
+    DCHECK(router_);
     DVLOG(1) << "ForwardMessage from node "
              << node_name_ << " to " << node_name;
-    task_queue.push(new Task(node_name, std::move(message)));
+    router_->ForwardMessage(this, node_name, std::move(message));
   }
 
   void BroadcastMessage(ScopedMessage message) override {
-    for (size_t i = 0; i < kMaxNodes; ++i) {
-      Node* node = node_map[i];
-      // Broadcast doesn't deliver to the local node.
-      if (node && node != GetNode(node_name_)) {
-        // NOTE: We only need to support broadcast of events, which have no
-        // payload or ports bytes.
-        ScopedMessage new_message(
-            new TestMessage(message->num_header_bytes(), 0, 0));
-        memcpy(new_message->mutable_header_bytes(), message->header_bytes(),
-               message->num_header_bytes());
-        node->AcceptMessage(std::move(new_message));
-      }
-    }
+    router_->BroadcastMessage(this, std::move(message));
   }
 
   void PortStatusChanged(const PortRef& port) override {
-    DVLOG(1) << "PortStatusChanged for " << port.name() << "@" << node_name_;
-    if (!read_messages_)
+    // The port may be closed, in which case we ignore the notification.
+    base::AutoLock lock(lock_);
+    if (!save_messages_)
       return;
-    Node* node = GetNode(node_name_);
+
     for (;;) {
       ScopedMessage message;
-      int rv = node->GetMessage(port, &message);
-      EXPECT_TRUE(rv == OK || rv == ERROR_PORT_PEER_CLOSED);
-      if (rv == ERROR_PORT_PEER_CLOSED || !message)
-        break;
-      if (save_messages_) {
-        SaveMessage(std::move(message));
-      } else {
-        LogMessage(message.get());
-        for (size_t i = 0; i < message->num_ports(); ++i) {
-          std::stringstream buf;
-          buf << "got port: " << message->ports()[i];
-
-          PortRef received_port;
-          node->GetPort(message->ports()[i], &received_port);
-
-          SendStringMessage(node, received_port, buf.str());
-
-          // Avoid leaking these ports.
-          node->ClosePort(received_port);
-        }
+      {
+        base::AutoUnlock unlock(lock_);
+        if (!ReadMessage(port, &message))
+          break;
       }
+
+      saved_messages_.emplace(std::move(message));
+    }
+  }
+
+  void ClosePortsInMessage(Message* message) {
+    for (size_t i = 0; i < message->num_ports(); ++i) {
+      PortRef port;
+      ASSERT_EQ(OK, node_.GetPort(message->ports()[i], &port));
+      EXPECT_EQ(OK, node_.ClosePort(port));
     }
   }
 
  private:
-  void SaveMessage(ScopedMessage message) {
-    saved_messages_.emplace(std::move(message));
+  void ProcessMessages() {
+    for (;;) {
+      messages_available_event_.Wait();
+
+      base::AutoLock lock(lock_);
+
+      if (should_quit_)
+        return;
+
+      dispatching_ = true;
+      while (!incoming_messages_.empty()) {
+        if (block_on_event_ &&
+            GetEventHeader(*incoming_messages_.front())->type ==
+                blocked_event_type_) {
+          blocked_ = true;
+          // Go idle if we hit a blocked event type.
+          break;
+        } else {
+          blocked_ = false;
+        }
+        ScopedMessage message = std::move(incoming_messages_.front());
+        incoming_messages_.pop();
+
+        // NOTE: AcceptMessage() can re-enter this object to call any of the
+        // NodeDelegate interface methods.
+        base::AutoUnlock unlock(lock_);
+        node_.AcceptMessage(std::move(message));
+      }
+
+      dispatching_ = false;
+      started_ = true;
+      idle_event_.Signal();
+    };
   }
 
+  const NodeName node_name_;
+  Node node_;
+  MessageRouter* router_ = nullptr;
+
+  base::Thread node_thread_;
+  base::WaitableEvent messages_available_event_;
+  base::WaitableEvent idle_event_;
+
+  // Guards fields below.
+  base::Lock lock_;
+  bool started_ = false;
+  bool dispatching_ = false;
+  bool should_quit_ = false;
+  bool drop_messages_ = false;
+  bool save_messages_ = false;
+  bool blocked_ = false;
+  bool block_on_event_ = false;
+  EventType blocked_event_type_;
+  std::queue<ScopedMessage> incoming_messages_;
   std::queue<ScopedMessage> saved_messages_;
-  NodeName node_name_;
-  bool drop_messages_;
-  bool read_messages_;
-  bool save_messages_;
 };
 
-class PortsTest : public testing::Test {
+class PortsTest : public testing::Test, public MessageRouter {
  public:
-  void SetUp() override {
-    DiscardPendingTasks();
-    SetNode(NodeName(0, 1), nullptr);
-    SetNode(NodeName(1, 1), nullptr);
-    SetNode(NodeName(2, 1), nullptr);
+  void AddNode(TestNode* node) {
+    {
+      base::AutoLock lock(lock_);
+      nodes_[node->name()] = node;
+    }
+    node->Start(this);
   }
+
+  void RemoveNode(TestNode* node) {
+    {
+      base::AutoLock lock(lock_);
+      nodes_.erase(node->name());
+    }
+
+    for (const auto& entry : nodes_)
+      entry.second->node().LostConnectionToNode(node->name());
+  }
+
+  // Waits until all known Nodes are idle. Message forwarding and processing
+  // is handled in such a way that idleness is a stable state: once all nodes in
+  // the system are idle, they will remain idle until the test explicitly
+  // initiates some further event (e.g. sending a message, closing a port, or
+  // removing a Node).
+  void WaitForIdle() {
+    for (;;) {
+      base::AutoLock global_lock(global_lock_);
+      bool all_nodes_idle = true;
+      for (const auto& entry : nodes_) {
+        if (!entry.second->IsIdle())
+          all_nodes_idle = false;
+        entry.second->WakeUp();
+      }
+      if (all_nodes_idle)
+        return;
+
+      // Wait for any Node to signal that it's idle.
+      base::AutoUnlock global_unlock(global_lock_);
+      std::vector<base::WaitableEvent*> events;
+      for (const auto& entry : nodes_)
+        events.push_back(&entry.second->idle_event());
+      base::WaitableEvent::WaitMany(events.data(), events.size());
+    }
+  }
+
+  void CreatePortPair(TestNode* node0,
+                      PortRef* port0,
+                      TestNode* node1,
+                      PortRef* port1) {
+    if (node0 == node1) {
+      EXPECT_EQ(OK, node0->node().CreatePortPair(port0, port1));
+    } else {
+      EXPECT_EQ(OK, node0->node().CreateUninitializedPort(port0));
+      EXPECT_EQ(OK, node1->node().CreateUninitializedPort(port1));
+      EXPECT_EQ(OK, node0->node().InitializePort(*port0, node1->name(),
+                                                 port1->name()));
+      EXPECT_EQ(OK, node1->node().InitializePort(*port1, node0->name(),
+                                                 port0->name()));
+    }
+  }
+
+ private:
+  // MessageRouter:
+  void GeneratePortName(PortName* name) override {
+    base::AutoLock lock(lock_);
+    name->v1 = next_port_id_++;
+    name->v2 = 0;
+  }
+
+  void ForwardMessage(TestNode* from_node,
+                      const NodeName& node_name,
+                      ScopedMessage message) override {
+    base::AutoLock global_lock(global_lock_);
+    base::AutoLock lock(lock_);
+    // Drop messages from nodes that have been removed.
+    if (nodes_.find(from_node->name()) == nodes_.end()) {
+      from_node->ClosePortsInMessage(message.get());
+      return;
+    }
+
+    auto it = nodes_.find(node_name);
+    if (it == nodes_.end()) {
+      DVLOG(1) << "Node not found: " << node_name;
+      return;
+    }
+
+    it->second->EnqueueMessage(std::move(message));
+  }
+
+  void BroadcastMessage(TestNode* from_node, ScopedMessage message) override {
+    base::AutoLock global_lock(global_lock_);
+    base::AutoLock lock(lock_);
+
+    // Drop messages from nodes that have been removed.
+    if (nodes_.find(from_node->name()) == nodes_.end())
+      return;
+
+    for (const auto& entry : nodes_) {
+      TestNode* node = entry.second;
+      // Broadcast doesn't deliver to the local node.
+      if (node == from_node)
+        continue;
+
+      // NOTE: We only need to support broadcast of events. Events have no
+      // payload or ports bytes.
+      ScopedMessage new_message(
+          new TestMessage(message->num_header_bytes(), 0, 0));
+      memcpy(new_message->mutable_header_bytes(), message->header_bytes(),
+             message->num_header_bytes());
+      node->EnqueueMessage(std::move(new_message));
+    }
+  }
+
+  base::MessageLoop message_loop_;
+
+  // Acquired before any operation which makes a Node busy, and before testing
+  // if all nodes are idle.
+  base::Lock global_lock_;
+
+  base::Lock lock_;
+  uint64_t next_port_id_ = 1;
+  std::map<NodeName, TestNode*> nodes_;
 };
 
 }  // namespace
 
 TEST_F(PortsTest, Basic1) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  SetNode(node0_name, &node0);
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  SetNode(node1_name, &node1);
+  TestNode node1(1);
+  AddNode(&node1);
 
-  // Setup pipe between node0 and node1.
   PortRef x0, x1;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&x0));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&x1));
-  EXPECT_EQ(OK, node0.InitializePort(x0, node1_name, x1.name()));
-  EXPECT_EQ(OK, node1.InitializePort(x1, node0_name, x0.name()));
+  CreatePortPair(&node0, &x0, &node1, &x1);
 
-  // Transfer a port from node0 to node1.
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "hello", a1));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "hello", a1));
+  EXPECT_EQ(OK, node0.node().ClosePort(a0));
 
-  EXPECT_EQ(OK, node0.ClosePort(a0));
+  EXPECT_EQ(OK, node0.node().ClosePort(x0));
+  EXPECT_EQ(OK, node1.node().ClosePort(x1));
 
-  EXPECT_EQ(OK, node0.ClosePort(x0));
-  EXPECT_EQ(OK, node1.ClosePort(x1));
+  WaitForIdle();
 
-  PumpTasks();
-
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, Basic2) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  SetNode(node0_name, &node0);
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  SetNode(node1_name, &node1);
+  TestNode node1(1);
+  AddNode(&node1);
 
-  // Setup pipe between node0 and node1.
   PortRef x0, x1;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&x0));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&x1));
-  EXPECT_EQ(OK, node0.InitializePort(x0, node1_name, x1.name()));
-  EXPECT_EQ(OK, node1.InitializePort(x1, node0_name, x0.name()));
+  CreatePortPair(&node0, &x0, &node1, &x1);
 
   PortRef b0, b1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&b0, &b1));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "hello", b1));
-  EXPECT_EQ(OK, SendStringMessage(&node0, b0, "hello again"));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&b0, &b1));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "hello", b1));
+  EXPECT_EQ(OK, node0.SendStringMessage(b0, "hello again"));
 
-  // This may cause a SendMessage(b1) failure.
-  EXPECT_EQ(OK, node0.ClosePort(b0));
+  EXPECT_EQ(OK, node0.node().ClosePort(b0));
 
-  EXPECT_EQ(OK, node0.ClosePort(x0));
-  EXPECT_EQ(OK, node1.ClosePort(x1));
+  EXPECT_EQ(OK, node0.node().ClosePort(x0));
+  EXPECT_EQ(OK, node1.node().ClosePort(x1));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, Basic3) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  SetNode(node0_name, &node0);
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  SetNode(node1_name, &node1);
+  TestNode node1(1);
+  AddNode(&node1);
 
-  // Setup pipe between node0 and node1.
   PortRef x0, x1;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&x0));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&x1));
-  EXPECT_EQ(OK, node0.InitializePort(x0, node1_name, x1.name()));
-  EXPECT_EQ(OK, node1.InitializePort(x1, node0_name, x0.name()));
+  CreatePortPair(&node0, &x0, &node1, &x1);
 
-  // Transfer a port from node0 to node1.
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "hello", a1));
-  EXPECT_EQ(OK, SendStringMessage(&node0, a0, "hello again"));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1));
 
-  // Transfer a0 as well.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "foo", a0));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "hello", a1));
+  EXPECT_EQ(OK, node0.SendStringMessage(a0, "hello again"));
+
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "foo", a0));
 
   PortRef b0, b1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&b0, &b1));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "bar", b1));
-  EXPECT_EQ(OK, SendStringMessage(&node0, b0, "baz"));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&b0, &b1));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "bar", b1));
+  EXPECT_EQ(OK, node0.SendStringMessage(b0, "baz"));
 
-  // This may cause a SendMessage(b1) failure.
-  EXPECT_EQ(OK, node0.ClosePort(b0));
+  EXPECT_EQ(OK, node0.node().ClosePort(b0));
 
-  EXPECT_EQ(OK, node0.ClosePort(x0));
-  EXPECT_EQ(OK, node1.ClosePort(x1));
+  EXPECT_EQ(OK, node0.node().ClosePort(x0));
+  EXPECT_EQ(OK, node1.node().ClosePort(x1));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, LostConnectionToNode1) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  SetNode(node0_name, &node0);
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  SetNode(node1_name, &node1);
+  TestNode node1(1);
+  AddNode(&node1);
+  node1.set_drop_messages(true);
 
-  // Setup pipe between node0 and node1.
   PortRef x0, x1;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&x0));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&x1));
-  EXPECT_EQ(OK, node0.InitializePort(x0, node1_name, x1.name()));
-  EXPECT_EQ(OK, node1.InitializePort(x1, node0_name, x0.name()));
+  CreatePortPair(&node0, &x0, &node1, &x1);
 
-  // Transfer port to node1 and simulate a lost connection to node1. Dropping
-  // events from node1 is how we simulate the lost connection.
-
-  node1_delegate.set_drop_messages(true);
+  // Transfer a port to node1 and simulate a lost connection to node1.
 
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "foo", a1));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "foo", a1));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_EQ(OK, node0.LostConnectionToNode(node1_name));
+  RemoveNode(&node1);
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_EQ(OK, node0.ClosePort(a0));
-  EXPECT_EQ(OK, node0.ClosePort(x0));
-  EXPECT_EQ(OK, node1.ClosePort(x1));
+  EXPECT_EQ(OK, node0.node().ClosePort(a0));
+  EXPECT_EQ(OK, node0.node().ClosePort(x0));
+  EXPECT_EQ(OK, node1.node().ClosePort(x1));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, LostConnectionToNode2) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
-  // Setup pipe between node0 and node1.
   PortRef x0, x1;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&x0));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&x1));
-  EXPECT_EQ(OK, node0.InitializePort(x0, node1_name, x1.name()));
-  EXPECT_EQ(OK, node1.InitializePort(x1, node0_name, x0.name()));
-
-  node1_delegate.set_read_messages(false);
+  CreatePortPair(&node0, &x0, &node1, &x1);
 
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "take a1", a1));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "take a1", a1));
 
-  PumpTasks();
+  WaitForIdle();
 
-  node1_delegate.set_drop_messages(true);
+  node1.set_drop_messages(true);
 
-  EXPECT_EQ(OK, node0.LostConnectionToNode(node1_name));
+  RemoveNode(&node1);
 
-  PumpTasks();
+  WaitForIdle();
 
+  // a0 should have eventually detected peer closure after node loss.
   ScopedMessage message;
-  EXPECT_EQ(ERROR_PORT_PEER_CLOSED, node0.GetMessage(a0, &message));
+  EXPECT_EQ(ERROR_PORT_PEER_CLOSED, node0.node().GetMessage(a0, &message));
   EXPECT_FALSE(message);
 
-  EXPECT_EQ(OK, node0.ClosePort(a0));
+  EXPECT_EQ(OK, node0.node().ClosePort(a0));
 
-  EXPECT_EQ(OK, node0.ClosePort(x0));
+  EXPECT_EQ(OK, node0.node().ClosePort(x0));
 
-  EXPECT_EQ(OK, node1.GetMessage(x1, &message));
+  EXPECT_EQ(OK, node1.node().GetMessage(x1, &message));
   EXPECT_TRUE(message);
-  ClosePortsInMessage(&node1, message.get());
+  node1.ClosePortsInMessage(message.get());
 
-  EXPECT_EQ(OK, node1.ClosePort(x1));
+  EXPECT_EQ(OK, node1.node().ClosePort(x1));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, LostConnectionToNodeWithSecondaryProxy) {
   // Tests that a proxy gets cleaned up when its indirect peer lives on a lost
   // node.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
-  NodeName node2_name(2, 1);
-  TestNodeDelegate node2_delegate(node2_name);
-  Node node2(node2_name, &node2_delegate);
-  node_map[2] = &node2;
-
-  node1_delegate.set_save_messages(true);
+  TestNode node2(2);
+  AddNode(&node2);
 
   // Create A-B spanning nodes 0 and 1 and C-D spanning 1 and 2.
   PortRef A, B, C, D;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&A));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&B));
-  EXPECT_EQ(OK, node0.InitializePort(A, node1_name, B.name()));
-  EXPECT_EQ(OK, node1.InitializePort(B, node0_name, A.name()));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&C));
-  EXPECT_EQ(OK, node2.CreateUninitializedPort(&D));
-  EXPECT_EQ(OK, node1.InitializePort(C, node2_name, D.name()));
-  EXPECT_EQ(OK, node2.InitializePort(D, node1_name, C.name()));
+  CreatePortPair(&node0, &A, &node1, &B);
+  CreatePortPair(&node1, &C, &node2, &D);
 
   // Create E-F and send F over A to node 1.
   PortRef E, F;
-  EXPECT_EQ(OK, node0.CreatePortPair(&E, &F));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, A, ".", F));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&E, &F));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(A, ".", F));
 
-  PumpTasks();
+  WaitForIdle();
 
   ScopedMessage message;
-  ASSERT_TRUE(node1_delegate.GetSavedMessage(&message));
+  ASSERT_TRUE(node1.ReadMessage(B, &message));
   ASSERT_EQ(1u, message->num_ports());
 
-  EXPECT_EQ(OK, node1.GetPort(message->ports()[0], &F));
+  EXPECT_EQ(OK, node1.node().GetPort(message->ports()[0], &F));
 
   // Send F over C to node 2 and then simulate node 2 loss from node 1. Node 1
   // will trivially become aware of the loss, and this test verifies that the
   // port A on node 0 will eventually also become aware of it.
 
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node1, C, ".", F));
+  // Make sure node2 stops processing events when it encounters an ObserveProxy.
+  node2.BlockOnEvent(EventType::kObserveProxy);
 
-  node_map[2] = nullptr;
-  EXPECT_EQ(OK, node1.LostConnectionToNode(node2_name));
+  EXPECT_EQ(OK, node1.SendStringMessageWithPort(C, ".", F));
+  WaitForIdle();
 
-  PumpTasks();
+  // Simulate node 1 and 2 disconnecting.
+  EXPECT_EQ(OK, node1.node().LostConnectionToNode(node2.name()));
+
+  // Let node2 continue processing events and wait for everyone to go idle.
+  node2.Unblock();
+  WaitForIdle();
 
   // Port F should be gone.
-  EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.GetPort(F.name(), &F));
+  EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.node().GetPort(F.name(), &F));
 
   // Port E should have detected peer closure despite the fact that there is
   // no longer a continuous route from F to E over which the event could travel.
   PortStatus status;
-  EXPECT_EQ(OK, node0.GetStatus(E, &status));
+  EXPECT_EQ(OK, node0.node().GetStatus(E, &status));
   EXPECT_TRUE(status.peer_closed);
 
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node1.ClosePort(B));
-  EXPECT_EQ(OK, node1.ClosePort(C));
-  EXPECT_EQ(OK, node0.ClosePort(E));
+  EXPECT_EQ(OK, node0.node().ClosePort(A));
+  EXPECT_EQ(OK, node1.node().ClosePort(B));
+  EXPECT_EQ(OK, node1.node().ClosePort(C));
+  EXPECT_EQ(OK, node0.node().ClosePort(E));
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  WaitForIdle();
+
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, LostConnectionToNodeWithLocalProxy) {
   // Tests that a proxy gets cleaned up when its direct peer lives on a lost
   // node and it's predecessor lives on the same node.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
-  node1_delegate.set_save_messages(true);
-
-  // Create A-B spanning nodes 0 and 1.
   PortRef A, B;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&A));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&B));
-  EXPECT_EQ(OK, node0.InitializePort(A, node1_name, B.name()));
-  EXPECT_EQ(OK, node1.InitializePort(B, node0_name, A.name()));
+  CreatePortPair(&node0, &A, &node1, &B);
 
-  // Create C-D and send D over A to node 1.
   PortRef C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&C, &D));
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, A, ".", D));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&C, &D));
 
-  // Pump tasks until the start of port collapse for port D, which should become
-  // a proxy.
-  PumpUntilTask(EventType::kObserveProxy);
+  // Send D but block node0 on an ObserveProxy event.
+  node0.BlockOnEvent(EventType::kObserveProxy);
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(A, ".", D));
+
+  // node0 won't collapse the proxy but node1 will receive the message before
+  // going idle.
+  WaitForIdle();
 
   ScopedMessage message;
-  ASSERT_TRUE(node1_delegate.GetSavedMessage(&message));
+  ASSERT_TRUE(node1.ReadMessage(B, &message));
   ASSERT_EQ(1u, message->num_ports());
-
   PortRef E;
-  EXPECT_EQ(OK, node1.GetPort(message->ports()[0], &E));
+  EXPECT_EQ(OK, node1.node().GetPort(message->ports()[0], &E));
 
-  EXPECT_EQ(OK, node0.LostConnectionToNode(node1_name));
-  PumpTasks();
+  RemoveNode(&node1);
+
+  node0.Unblock();
+  WaitForIdle();
 
   // Port C should have detected peer closure.
   PortStatus status;
-  EXPECT_EQ(OK, node0.GetStatus(C, &status));
+  EXPECT_EQ(OK, node0.node().GetStatus(C, &status));
   EXPECT_TRUE(status.peer_closed);
 
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node1.ClosePort(B));
-  EXPECT_EQ(OK, node0.ClosePort(C));
-  EXPECT_EQ(OK, node1.ClosePort(E));
+  EXPECT_EQ(OK, node0.node().ClosePort(A));
+  EXPECT_EQ(OK, node1.node().ClosePort(B));
+  EXPECT_EQ(OK, node0.node().ClosePort(C));
+  EXPECT_EQ(OK, node1.node().ClosePort(E));
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, GetMessage1) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node(0);
+  AddNode(&node);
 
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&a0, &a1));
 
   ScopedMessage message;
-  EXPECT_EQ(OK, node0.GetMessage(a0, &message));
+  EXPECT_EQ(OK, node.node().GetMessage(a0, &message));
   EXPECT_FALSE(message);
 
-  EXPECT_EQ(OK, node0.ClosePort(a1));
+  EXPECT_EQ(OK, node.node().ClosePort(a1));
 
-  EXPECT_EQ(OK, node0.GetMessage(a0, &message));
+  WaitForIdle();
+
+  EXPECT_EQ(ERROR_PORT_PEER_CLOSED, node.node().GetMessage(a0, &message));
   EXPECT_FALSE(message);
 
-  PumpTasks();
+  EXPECT_EQ(OK, node.node().ClosePort(a0));
 
-  EXPECT_EQ(ERROR_PORT_PEER_CLOSED, node0.GetMessage(a0, &message));
-  EXPECT_FALSE(message);
+  WaitForIdle();
 
-  EXPECT_EQ(OK, node0.ClosePort(a0));
-
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, GetMessage2) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
-
-  node0_delegate.set_read_messages(false);
+  TestNode node(0);
+  AddNode(&node);
 
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&a0, &a1));
 
-  EXPECT_EQ(OK, SendStringMessage(&node0, a1, "1"));
+  EXPECT_EQ(OK, node.SendStringMessage(a1, "1"));
 
   ScopedMessage message;
-  EXPECT_EQ(OK, node0.GetMessage(a0, &message));
+  EXPECT_EQ(OK, node.node().GetMessage(a0, &message));
 
   ASSERT_TRUE(message);
-  EXPECT_EQ(0, strcmp("1", ToString(message)));
+  EXPECT_TRUE(MessageEquals(message, "1"));
 
-  EXPECT_EQ(OK, node0.ClosePort(a0));
-  EXPECT_EQ(OK, node0.ClosePort(a1));
+  EXPECT_EQ(OK, node.node().ClosePort(a0));
+  EXPECT_EQ(OK, node.node().ClosePort(a1));
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, GetMessage3) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
-
-  node0_delegate.set_read_messages(false);
+  TestNode node(0);
+  AddNode(&node);
 
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&a0, &a1));
 
   const char* kStrings[] = {
     "1",
@@ -696,371 +777,305 @@
   };
 
   for (size_t i = 0; i < sizeof(kStrings)/sizeof(kStrings[0]); ++i)
-    EXPECT_EQ(OK, SendStringMessage(&node0, a1, kStrings[i]));
+    EXPECT_EQ(OK, node.SendStringMessage(a1, kStrings[i]));
 
   ScopedMessage message;
   for (size_t i = 0; i < sizeof(kStrings)/sizeof(kStrings[0]); ++i) {
-    EXPECT_EQ(OK, node0.GetMessage(a0, &message));
+    EXPECT_EQ(OK, node.node().GetMessage(a0, &message));
     ASSERT_TRUE(message);
-    EXPECT_EQ(0, strcmp(kStrings[i], ToString(message)));
-    DVLOG(1) << "got " << kStrings[i];
+    EXPECT_TRUE(MessageEquals(message, kStrings[i]));
   }
 
-  EXPECT_EQ(OK, node0.ClosePort(a0));
-  EXPECT_EQ(OK, node0.ClosePort(a1));
+  EXPECT_EQ(OK, node.node().ClosePort(a0));
+  EXPECT_EQ(OK, node.node().ClosePort(a1));
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, Delegation1) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  SetNode(node0_name, &node0);
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
-  node0_delegate.set_save_messages(true);
-  node1_delegate.set_save_messages(true);
-
-  // Setup pipe between node0 and node1.
   PortRef x0, x1;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&x0));
-  EXPECT_EQ(OK, node1.CreateUninitializedPort(&x1));
-  EXPECT_EQ(OK, node0.InitializePort(x0, node1_name, x1.name()));
-  EXPECT_EQ(OK, node1.InitializePort(x1, node0_name, x0.name()));
+  CreatePortPair(&node0, &x0, &node1, &x1);
 
   // In this test, we send a message to a port that has been moved.
 
   PortRef a0, a1;
-  EXPECT_EQ(OK, node0.CreatePortPair(&a0, &a1));
-
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, x0, "a1", a1));
-
-  PumpTasks();
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&a0, &a1));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(x0, "a1", a1));
+  WaitForIdle();
 
   ScopedMessage message;
-  ASSERT_TRUE(node1_delegate.GetSavedMessage(&message));
-
+  ASSERT_TRUE(node1.ReadMessage(x1, &message));
   ASSERT_EQ(1u, message->num_ports());
+  EXPECT_TRUE(MessageEquals(message, "a1"));
 
   // This is "a1" from the point of view of node1.
   PortName a2_name = message->ports()[0];
+  EXPECT_EQ(OK, node1.SendStringMessageWithPort(x1, "a2", a2_name));
+  EXPECT_EQ(OK, node0.SendStringMessage(a0, "hello"));
 
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node1, x1, "a2", a2_name));
+  WaitForIdle();
 
-  PumpTasks();
-
-  EXPECT_EQ(OK, SendStringMessage(&node0, a0, "hello"));
-
-  PumpTasks();
-
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-
+  ASSERT_TRUE(node0.ReadMessage(x0, &message));
   ASSERT_EQ(1u, message->num_ports());
+  EXPECT_TRUE(MessageEquals(message, "a2"));
 
   // This is "a2" from the point of view of node1.
   PortName a3_name = message->ports()[0];
 
   PortRef a3;
-  EXPECT_EQ(OK, node0.GetPort(a3_name, &a3));
+  EXPECT_EQ(OK, node0.node().GetPort(a3_name, &a3));
 
-  EXPECT_EQ(0, strcmp("a2", ToString(message)));
-
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-
+  ASSERT_TRUE(node0.ReadMessage(a3, &message));
   EXPECT_EQ(0u, message->num_ports());
-  EXPECT_EQ(0, strcmp("hello", ToString(message)));
+  EXPECT_TRUE(MessageEquals(message, "hello"));
 
-  EXPECT_EQ(OK, node0.ClosePort(a0));
-  EXPECT_EQ(OK, node0.ClosePort(a3));
+  EXPECT_EQ(OK, node0.node().ClosePort(a0));
+  EXPECT_EQ(OK, node0.node().ClosePort(a3));
 
-  EXPECT_EQ(OK, node0.ClosePort(x0));
-  EXPECT_EQ(OK, node1.ClosePort(x1));
+  EXPECT_EQ(OK, node0.node().ClosePort(x0));
+  EXPECT_EQ(OK, node1.node().ClosePort(x1));
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, Delegation2) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  SetNode(node0_name, &node0);
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
-  node0_delegate.set_save_messages(true);
-  node1_delegate.set_save_messages(true);
-
-  for (int i = 0; i < 10; ++i) {
+  for (int i = 0; i < 100; ++i) {
     // Setup pipe a<->b between node0 and node1.
     PortRef A, B;
-    EXPECT_EQ(OK, node0.CreateUninitializedPort(&A));
-    EXPECT_EQ(OK, node1.CreateUninitializedPort(&B));
-    EXPECT_EQ(OK, node0.InitializePort(A, node1_name, B.name()));
-    EXPECT_EQ(OK, node1.InitializePort(B, node0_name, A.name()));
+    CreatePortPair(&node0, &A, &node1, &B);
 
     PortRef C, D;
-    EXPECT_EQ(OK, node0.CreatePortPair(&C, &D));
+    EXPECT_EQ(OK, node0.node().CreatePortPair(&C, &D));
 
     PortRef E, F;
-    EXPECT_EQ(OK, node0.CreatePortPair(&E, &F));
+    EXPECT_EQ(OK, node0.node().CreatePortPair(&E, &F));
+
+    node1.set_save_messages(true);
 
     // Pass D over A to B.
-    EXPECT_EQ(OK, SendStringMessageWithPort(&node0, A, "1", D));
+    EXPECT_EQ(OK, node0.SendStringMessageWithPort(A, "1", D));
 
     // Pass F over C to D.
-    EXPECT_EQ(OK, SendStringMessageWithPort(&node0, C, "1", F));
+    EXPECT_EQ(OK, node0.SendStringMessageWithPort(C, "1", F));
 
     // This message should find its way to node1.
-    EXPECT_EQ(OK, SendStringMessage(&node0, E, "hello"));
+    EXPECT_EQ(OK, node0.SendStringMessage(E, "hello"));
 
-    PumpTasks();
+    WaitForIdle();
 
-    EXPECT_EQ(OK, node0.ClosePort(C));
-    EXPECT_EQ(OK, node0.ClosePort(E));
+    EXPECT_EQ(OK, node0.node().ClosePort(C));
+    EXPECT_EQ(OK, node0.node().ClosePort(E));
 
-    EXPECT_EQ(OK, node0.ClosePort(A));
-    EXPECT_EQ(OK, node1.ClosePort(B));
+    EXPECT_EQ(OK, node0.node().ClosePort(A));
+    EXPECT_EQ(OK, node1.node().ClosePort(B));
 
-    for (;;) {
-      ScopedMessage message;
-      if (node1_delegate.GetSavedMessage(&message)) {
-        ClosePortsInMessage(&node1, message.get());
-        if (strcmp("hello", ToString(message)) == 0)
-          break;
-      } else {
-        ASSERT_TRUE(false);  // "hello" message not delivered!
+    bool got_hello = false;
+    ScopedMessage message;
+    while (node1.GetSavedMessage(&message)) {
+      node1.ClosePortsInMessage(message.get());
+      if (MessageEquals(message, "hello")) {
+        got_hello = true;
         break;
       }
     }
 
-    PumpTasks();  // Because ClosePort may have generated tasks.
+    EXPECT_TRUE(got_hello);
+
+    WaitForIdle();  // Because closing ports may have generated tasks.
   }
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, SendUninitialized) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node(0);
+  AddNode(&node);
 
   PortRef x0;
-  EXPECT_EQ(OK, node0.CreateUninitializedPort(&x0));
-  EXPECT_EQ(ERROR_PORT_STATE_UNEXPECTED,
-            SendStringMessage(&node0, x0, "oops"));
-  EXPECT_EQ(OK, node0.ClosePort(x0));
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_EQ(OK, node.node().CreateUninitializedPort(&x0));
+  EXPECT_EQ(ERROR_PORT_STATE_UNEXPECTED, node.SendStringMessage(x0, "oops"));
+  EXPECT_EQ(OK, node.node().ClosePort(x0));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, SendFailure) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node(0);
+  AddNode(&node);
 
-  node0_delegate.set_save_messages(true);
+  node.set_save_messages(true);
 
   PortRef A, B;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B));
 
   // Try to send A over itself.
 
   EXPECT_EQ(ERROR_PORT_CANNOT_SEND_SELF,
-            SendStringMessageWithPort(&node0, A, "oops", A));
+            node.SendStringMessageWithPort(A, "oops", A));
 
   // Try to send B over A.
 
   EXPECT_EQ(ERROR_PORT_CANNOT_SEND_PEER,
-            SendStringMessageWithPort(&node0, A, "nope", B));
+            node.SendStringMessageWithPort(A, "nope", B));
 
   // B should be closed immediately.
-  EXPECT_EQ(ERROR_PORT_UNKNOWN, node0.GetPort(B.name(), &B));
+  EXPECT_EQ(ERROR_PORT_UNKNOWN, node.node().GetPort(B.name(), &B));
 
-  PumpTasks();
+  WaitForIdle();
 
   // There should have been no messages accepted.
   ScopedMessage message;
-  EXPECT_FALSE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_FALSE(node.GetSavedMessage(&message));
 
-  EXPECT_EQ(OK, node0.ClosePort(A));
+  EXPECT_EQ(OK, node.node().ClosePort(A));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, DontLeakUnreceivedPorts) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node(0);
+  AddNode(&node);
 
-  node0_delegate.set_read_messages(false);
+  PortRef A, B, C, D;
+  EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&C, &D));
 
-  PortRef A, B;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(A, "foo", D));
 
-  PortRef C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&C, &D));
+  EXPECT_EQ(OK, node.node().ClosePort(C));
+  EXPECT_EQ(OK, node.node().ClosePort(A));
+  EXPECT_EQ(OK, node.node().ClosePort(B));
 
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, A, "foo", D));
+  WaitForIdle();
 
-  PumpTasks();
-
-  EXPECT_EQ(OK, node0.ClosePort(C));
-
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node0.ClosePort(B));
-
-  PumpTasks();
-
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, AllowShutdownWithLocalPortsOpen) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node(0);
+  AddNode(&node);
 
-  node0_delegate.set_save_messages(true);
+  PortRef A, B, C, D;
+  EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&C, &D));
 
-  PortRef A, B;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-
-  PortRef C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&C, &D));
-
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, A, "foo", D));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(A, "foo", D));
 
   ScopedMessage message;
-  EXPECT_TRUE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_TRUE(node.ReadMessage(B, &message));
   ASSERT_EQ(1u, message->num_ports());
-
+  EXPECT_TRUE(MessageEquals(message, "foo"));
   PortRef E;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &E));
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &E));
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(true));
+  EXPECT_TRUE(
+      node.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(true));
-  EXPECT_FALSE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(
+      node.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS));
+  EXPECT_FALSE(node.node().CanShutdownCleanly());
 
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node0.ClosePort(B));
-  EXPECT_EQ(OK, node0.ClosePort(C));
-  EXPECT_EQ(OK, node0.ClosePort(E));
+  EXPECT_EQ(OK, node.node().ClosePort(A));
+  EXPECT_EQ(OK, node.node().ClosePort(B));
+  EXPECT_EQ(OK, node.node().ClosePort(C));
+  EXPECT_EQ(OK, node.node().ClosePort(E));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, ProxyCollapse1) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
-
-  node0_delegate.set_save_messages(true);
+  TestNode node(0);
+  AddNode(&node);
 
   PortRef A, B;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B));
 
   PortRef X, Y;
-  EXPECT_EQ(OK, node0.CreatePortPair(&X, &Y));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y));
 
   ScopedMessage message;
 
   // Send B and receive it as C.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", B));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B));
+  ASSERT_TRUE(node.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
   PortRef C;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &C));
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &C));
 
   // Send C and receive it as D.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", C));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", C));
+  ASSERT_TRUE(node.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
   PortRef D;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &D));
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &D));
 
   // Send D and receive it as E.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", D));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", D));
+  ASSERT_TRUE(node.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
   PortRef E;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &E));
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &E));
 
-  EXPECT_EQ(OK, node0.ClosePort(X));
-  EXPECT_EQ(OK, node0.ClosePort(Y));
+  EXPECT_EQ(OK, node.node().ClosePort(X));
+  EXPECT_EQ(OK, node.node().ClosePort(Y));
 
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node0.ClosePort(E));
+  EXPECT_EQ(OK, node.node().ClosePort(A));
+  EXPECT_EQ(OK, node.node().ClosePort(E));
 
-  PumpTasks();
+  // The node should not idle until all proxies are collapsed.
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, ProxyCollapse2) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
-
-  node0_delegate.set_save_messages(true);
+  TestNode node(0);
+  AddNode(&node);
 
   PortRef A, B;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B));
 
   PortRef X, Y;
-  EXPECT_EQ(OK, node0.CreatePortPair(&X, &Y));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y));
 
   ScopedMessage message;
 
-  // Send B and receive it as C.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", B));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-  ASSERT_EQ(1u, message->num_ports());
-  PortRef C;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &C));
+  // Send B and A to create proxies in each direction.
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", A));
 
-  // Send A and receive it as D.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", A));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-  ASSERT_EQ(1u, message->num_ports());
-  PortRef D;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &D));
+  EXPECT_EQ(OK, node.node().ClosePort(X));
+  EXPECT_EQ(OK, node.node().ClosePort(Y));
 
   // At this point we have a scenario with:
   //
   // D -> [B] -> C -> [A]
   //
-  // Ensure that the proxies can collapse.
+  // Ensure that the proxies can collapse. The sent ports will be closed
+  // eventually as a result of Y's closure.
 
-  EXPECT_EQ(OK, node0.ClosePort(X));
-  EXPECT_EQ(OK, node0.ClosePort(Y));
+  WaitForIdle();
 
-  EXPECT_EQ(OK, node0.ClosePort(C));
-  EXPECT_EQ(OK, node0.ClosePort(D));
-
-  PumpTasks();
-
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, SendWithClosedPeer) {
@@ -1068,56 +1083,47 @@
   // closed, the newly created port will be aware of that peer closure, and the
   // proxy will eventually collapse.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
-
-  node0_delegate.set_read_messages(false);
+  TestNode node(0);
+  AddNode(&node);
 
   // Send a message from A to B, then close A.
   PortRef A, B;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-  EXPECT_EQ(OK, SendStringMessage(&node0, A, "hey"));
-  EXPECT_EQ(OK, node0.ClosePort(A));
-
-  PumpTasks();
+  EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.SendStringMessage(A, "hey"));
+  EXPECT_EQ(OK, node.node().ClosePort(A));
 
   // Now send B over X-Y as new port C.
   PortRef X, Y;
-  EXPECT_EQ(OK, node0.CreatePortPair(&X, &Y));
-
-  node0_delegate.set_read_messages(true);
-  node0_delegate.set_save_messages(true);
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", B));
-
-  EXPECT_EQ(OK, node0.ClosePort(X));
-  EXPECT_EQ(OK, node0.ClosePort(Y));
-
+  EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B));
   ScopedMessage message;
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  ASSERT_TRUE(node.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
-
   PortRef C;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &C));
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &C));
 
-  PumpTasks();
+  EXPECT_EQ(OK, node.node().ClosePort(X));
+  EXPECT_EQ(OK, node.node().ClosePort(Y));
 
-  // C should receive the message originally sent to B, and it should also be
-  // aware of A's closure.
+  WaitForIdle();
 
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-  EXPECT_EQ(0, strcmp("hey", ToString(message)));
+  // C should have received the message originally sent to B, and it should also
+  // be aware of A's closure.
+
+  ASSERT_TRUE(node.ReadMessage(C, &message));
+  EXPECT_TRUE(MessageEquals(message, "hey"));
 
   PortStatus status;
-  EXPECT_EQ(OK, node0.GetStatus(C, &status));
+  EXPECT_EQ(OK, node.node().GetStatus(C, &status));
   EXPECT_FALSE(status.receiving_messages);
   EXPECT_FALSE(status.has_messages);
   EXPECT_TRUE(status.peer_closed);
 
-  node0.ClosePort(C);
+  node.node().ClosePort(C);
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  WaitForIdle();
+
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, SendWithClosedPeerSent) {
@@ -1126,391 +1132,342 @@
   // eventually notified of the closure, and the dead-end proxies will
   // eventually be removed.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
-
-  node0_delegate.set_save_messages(true);
+  TestNode node(0);
+  AddNode(&node);
 
   PortRef X, Y;
-  EXPECT_EQ(OK, node0.CreatePortPair(&X, &Y));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&X, &Y));
 
   PortRef A, B;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node.node().CreatePortPair(&A, &B));
 
   ScopedMessage message;
 
   // Send A as new port C.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", A));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", A));
+
+  ASSERT_TRUE(node.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
   PortRef C;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &C));
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &C));
 
   // Send C as new port D.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", C));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", C));
+
+  ASSERT_TRUE(node.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
   PortRef D;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &D));
-
-  node0_delegate.set_read_messages(false);
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &D));
 
   // Send a message to B through D, then close D.
-  EXPECT_EQ(OK, SendStringMessage(&node0, D, "hey"));
-  EXPECT_EQ(OK, node0.ClosePort(D));
-
-  PumpTasks();
+  EXPECT_EQ(OK, node.SendStringMessage(D, "hey"));
+  EXPECT_EQ(OK, node.node().ClosePort(D));
 
   // Now send B as new port E.
 
-  node0_delegate.set_read_messages(true);
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", B));
+  EXPECT_EQ(OK, node.SendStringMessageWithPort(X, "foo", B));
+  EXPECT_EQ(OK, node.node().ClosePort(X));
 
-  EXPECT_EQ(OK, node0.ClosePort(X));
-  EXPECT_EQ(OK, node0.ClosePort(Y));
-
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  ASSERT_TRUE(node.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
-
   PortRef E;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &E));
+  ASSERT_EQ(OK, node.node().GetPort(message->ports()[0], &E));
 
-  PumpTasks();
+  EXPECT_EQ(OK, node.node().ClosePort(Y));
+
+  WaitForIdle();
 
   // E should receive the message originally sent to B, and it should also be
   // aware of D's closure.
 
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-  EXPECT_EQ(0, strcmp("hey", ToString(message)));
+  ASSERT_TRUE(node.ReadMessage(E, &message));
+  EXPECT_TRUE(MessageEquals(message, "hey"));
 
   PortStatus status;
-  EXPECT_EQ(OK, node0.GetStatus(E, &status));
+  EXPECT_EQ(OK, node.node().GetStatus(E, &status));
   EXPECT_FALSE(status.receiving_messages);
   EXPECT_FALSE(status.has_messages);
   EXPECT_TRUE(status.peer_closed);
 
-  node0.ClosePort(E);
+  EXPECT_EQ(OK, node.node().ClosePort(E));
 
-  PumpTasks();
+  WaitForIdle();
 
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
+  EXPECT_TRUE(node.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, MergePorts) {
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
   // Setup two independent port pairs, A-B on node0 and C-D on node1.
   PortRef A, B, C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-  EXPECT_EQ(OK, node1.CreatePortPair(&C, &D));
-
-  node0_delegate.set_read_messages(false);
-  node1_delegate.set_save_messages(true);
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D));
 
   // Write a message on A.
-  EXPECT_EQ(OK, SendStringMessage(&node0, A, "hey"));
-
-  PumpTasks();
+  EXPECT_EQ(OK, node0.SendStringMessage(A, "hey"));
 
   // Initiate a merge between B and C.
-  EXPECT_EQ(OK, node0.MergePorts(B, node1_name, C.name()));
+  EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name()));
 
-  PumpTasks();
+  WaitForIdle();
 
-  // Expect only two receiving ports to be left after pumping tasks.
-  EXPECT_TRUE(node0.CanShutdownCleanly(true));
-  EXPECT_TRUE(node1.CanShutdownCleanly(true));
+  // Expect all proxies to be gone once idle.
+  EXPECT_TRUE(
+      node0.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS));
+  EXPECT_TRUE(
+      node1.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS));
 
   // Expect D to have received the message sent on A.
   ScopedMessage message;
-  ASSERT_TRUE(node1_delegate.GetSavedMessage(&message));
-  EXPECT_EQ(0, strcmp("hey", ToString(message)));
+  ASSERT_TRUE(node1.ReadMessage(D, &message));
+  EXPECT_TRUE(MessageEquals(message, "hey"));
 
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node1.ClosePort(D));
+  EXPECT_EQ(OK, node0.node().ClosePort(A));
+  EXPECT_EQ(OK, node1.node().ClosePort(D));
 
   // No more ports should be open.
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, MergePortWithClosedPeer1) {
   // This tests that the right thing happens when initiating a merge on a port
   // whose peer has already been closed.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
   // Setup two independent port pairs, A-B on node0 and C-D on node1.
   PortRef A, B, C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-  EXPECT_EQ(OK, node1.CreatePortPair(&C, &D));
-
-  node0_delegate.set_read_messages(false);
-  node1_delegate.set_save_messages(true);
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D));
 
   // Write a message on A.
-  EXPECT_EQ(OK, SendStringMessage(&node0, A, "hey"));
-
-  PumpTasks();
+  EXPECT_EQ(OK, node0.SendStringMessage(A, "hey"));
 
   // Close A.
-  EXPECT_EQ(OK, node0.ClosePort(A));
+  EXPECT_EQ(OK, node0.node().ClosePort(A));
 
   // Initiate a merge between B and C.
-  EXPECT_EQ(OK, node0.MergePorts(B, node1_name, C.name()));
+  EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name()));
 
-  PumpTasks();
+  WaitForIdle();
 
-  // Expect only one receiving port to be left after pumping tasks.
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(true));
+  // Expect all proxies to be gone once idle. node0 should have no ports since
+  // A was explicitly closed.
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(
+      node1.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS));
 
   // Expect D to have received the message sent on A.
   ScopedMessage message;
-  ASSERT_TRUE(node1_delegate.GetSavedMessage(&message));
-  EXPECT_EQ(0, strcmp("hey", ToString(message)));
+  ASSERT_TRUE(node1.ReadMessage(D, &message));
+  EXPECT_TRUE(MessageEquals(message, "hey"));
 
-  EXPECT_EQ(OK, node1.ClosePort(D));
+  EXPECT_EQ(OK, node1.node().ClosePort(D));
 
   // No more ports should be open.
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, MergePortWithClosedPeer2) {
   // This tests that the right thing happens when merging into a port whose peer
   // has already been closed.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
   // Setup two independent port pairs, A-B on node0 and C-D on node1.
   PortRef A, B, C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-  EXPECT_EQ(OK, node1.CreatePortPair(&C, &D));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D));
 
-  node0_delegate.set_save_messages(true);
-  node1_delegate.set_read_messages(false);
-
-  // Write a message on D.
-  EXPECT_EQ(OK, SendStringMessage(&node0, D, "hey"));
-
-  PumpTasks();
-
-  // Close D.
-  EXPECT_EQ(OK, node1.ClosePort(D));
+  // Write a message on D and close it.
+  EXPECT_EQ(OK, node0.SendStringMessage(D, "hey"));
+  EXPECT_EQ(OK, node1.node().ClosePort(D));
 
   // Initiate a merge between B and C.
-  EXPECT_EQ(OK, node0.MergePorts(B, node1_name, C.name()));
+  EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name()));
 
-  PumpTasks();
+  WaitForIdle();
 
-  // Expect only one receiving port to be left after pumping tasks.
-  EXPECT_TRUE(node0.CanShutdownCleanly(true));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  // Expect all proxies to be gone once idle. node1 should have no ports since
+  // D was explicitly closed.
+  EXPECT_TRUE(
+      node0.node().CanShutdownCleanly(Node::ShutdownPolicy::ALLOW_LOCAL_PORTS));
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 
   // Expect A to have received the message sent on D.
   ScopedMessage message;
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-  EXPECT_EQ(0, strcmp("hey", ToString(message)));
+  ASSERT_TRUE(node0.ReadMessage(A, &message));
+  EXPECT_TRUE(MessageEquals(message, "hey"));
 
-  EXPECT_EQ(OK, node0.ClosePort(A));
+  EXPECT_EQ(OK, node0.node().ClosePort(A));
 
   // No more ports should be open.
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, MergePortsWithClosedPeers) {
   // This tests that no residual ports are left behind if two ports are merged
   // when both of their peers have been closed.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
   // Setup two independent port pairs, A-B on node0 and C-D on node1.
   PortRef A, B, C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-  EXPECT_EQ(OK, node1.CreatePortPair(&C, &D));
-
-  node0_delegate.set_save_messages(true);
-  node1_delegate.set_read_messages(false);
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D));
 
   // Close A and D.
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node1.ClosePort(D));
+  EXPECT_EQ(OK, node0.node().ClosePort(A));
+  EXPECT_EQ(OK, node1.node().ClosePort(D));
 
-  PumpTasks();
+  WaitForIdle();
 
   // Initiate a merge between B and C.
-  EXPECT_EQ(OK, node0.MergePorts(B, node1_name, C.name()));
+  EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name()));
 
-  PumpTasks();
+  WaitForIdle();
 
   // Expect everything to have gone away.
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, MergePortsWithMovedPeers) {
-  // This tests that no ports can be merged successfully even if their peers
-  // are moved around.
+  // This tests that ports can be merged successfully even if their peers are
+  // moved around.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
-
-  node0_delegate.set_save_messages(true);
-  node1_delegate.set_read_messages(false);
+  TestNode node1(1);
+  AddNode(&node1);
 
   // Setup two independent port pairs, A-B on node0 and C-D on node1.
   PortRef A, B, C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-  EXPECT_EQ(OK, node1.CreatePortPair(&C, &D));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D));
 
   // Set up another pair X-Y for moving ports on node0.
   PortRef X, Y;
-  EXPECT_EQ(OK, node0.CreatePortPair(&X, &Y));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&X, &Y));
 
   ScopedMessage message;
 
   // Move A to new port E.
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node0, X, "foo", A));
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
+  EXPECT_EQ(OK, node0.SendStringMessageWithPort(X, "foo", A));
+  ASSERT_TRUE(node0.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
   PortRef E;
-  ASSERT_EQ(OK, node0.GetPort(message->ports()[0], &E));
+  ASSERT_EQ(OK, node0.node().GetPort(message->ports()[0], &E));
 
-  EXPECT_EQ(OK, node0.ClosePort(X));
-  EXPECT_EQ(OK, node0.ClosePort(Y));
-
-  node0_delegate.set_read_messages(false);
+  EXPECT_EQ(OK, node0.node().ClosePort(X));
+  EXPECT_EQ(OK, node0.node().ClosePort(Y));
 
   // Write messages on E and D.
-  EXPECT_EQ(OK, SendStringMessage(&node0, E, "hey"));
-  EXPECT_EQ(OK, SendStringMessage(&node1, D, "hi"));
+  EXPECT_EQ(OK, node0.SendStringMessage(E, "hey"));
+  EXPECT_EQ(OK, node1.SendStringMessage(D, "hi"));
 
   // Initiate a merge between B and C.
-  EXPECT_EQ(OK, node0.MergePorts(B, node1_name, C.name()));
+  EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name()));
 
-  node0_delegate.set_read_messages(true);
-  node1_delegate.set_read_messages(true);
-  node1_delegate.set_save_messages(true);
-
-  PumpTasks();
+  WaitForIdle();
 
   // Expect to receive D's message on E and E's message on D.
-  ASSERT_TRUE(node0_delegate.GetSavedMessage(&message));
-  EXPECT_EQ(0, strcmp("hi", ToString(message)));
-  ASSERT_TRUE(node1_delegate.GetSavedMessage(&message));
-  EXPECT_EQ(0, strcmp("hey", ToString(message)));
+  ASSERT_TRUE(node0.ReadMessage(E, &message));
+  EXPECT_TRUE(MessageEquals(message, "hi"));
+  ASSERT_TRUE(node1.ReadMessage(D, &message));
+  EXPECT_TRUE(MessageEquals(message, "hey"));
 
   // Close E and D.
-  EXPECT_EQ(OK, node0.ClosePort(E));
-  EXPECT_EQ(OK, node1.ClosePort(D));
+  EXPECT_EQ(OK, node0.node().ClosePort(E));
+  EXPECT_EQ(OK, node1.node().ClosePort(D));
 
-  PumpTasks();
+  WaitForIdle();
 
   // Expect everything to have gone away.
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 TEST_F(PortsTest, MergePortsFailsGracefully) {
   // This tests that the system remains in a well-defined state if something
   // goes wrong during port merge.
 
-  NodeName node0_name(0, 1);
-  TestNodeDelegate node0_delegate(node0_name);
-  Node node0(node0_name, &node0_delegate);
-  node_map[0] = &node0;
+  TestNode node0(0);
+  AddNode(&node0);
 
-  NodeName node1_name(1, 1);
-  TestNodeDelegate node1_delegate(node1_name);
-  Node node1(node1_name, &node1_delegate);
-  node_map[1] = &node1;
+  TestNode node1(1);
+  AddNode(&node1);
 
   // Setup two independent port pairs, A-B on node0 and C-D on node1.
   PortRef A, B, C, D;
-  EXPECT_EQ(OK, node0.CreatePortPair(&A, &B));
-  EXPECT_EQ(OK, node1.CreatePortPair(&C, &D));
+  EXPECT_EQ(OK, node0.node().CreatePortPair(&A, &B));
+  EXPECT_EQ(OK, node1.node().CreatePortPair(&C, &D));
 
-  PumpTasks();
-
-  // Initiate a merge between B and C.
-  EXPECT_EQ(OK, node0.MergePorts(B, node1_name, C.name()));
-
-  // Move C to a new port E. This is dumb and nobody should do it, but it's
-  // possible. MergePorts will fail as a result because C won't be in a
-  // receiving state when the event arrives at node1, so B should be closed.
   ScopedMessage message;
   PortRef X, Y;
-  EXPECT_EQ(OK, node1.CreatePortPair(&X, &Y));
-  node1_delegate.set_save_messages(true);
-  EXPECT_EQ(OK, SendStringMessageWithPort(&node1, X, "foo", C));
-  ASSERT_TRUE(node1_delegate.GetSavedMessage(&message));
+  EXPECT_EQ(OK, node1.node().CreatePortPair(&X, &Y));
+
+  // Block the merge from proceeding until we can do something stupid with port
+  // C. This avoids the test logic racing with async merge logic.
+  node1.BlockOnEvent(EventType::kMergePort);
+
+  // Initiate the merge between B and C.
+  EXPECT_EQ(OK, node0.node().MergePorts(B, node1.name(), C.name()));
+
+  // Move C to a new port E. This is not a sane use of Node's public API but
+  // is still hypothetically possible. It allows us to force a merge failure
+  // because C will be in an invalid state by the term the merge is processed.
+  // As a result, B should be closed.
+  EXPECT_EQ(OK, node1.SendStringMessageWithPort(X, "foo", C));
+
+  node1.Unblock();
+
+  ASSERT_TRUE(node1.ReadMessage(Y, &message));
   ASSERT_EQ(1u, message->num_ports());
   PortRef E;
-  ASSERT_EQ(OK, node1.GetPort(message->ports()[0], &E));
-  EXPECT_EQ(OK, node1.ClosePort(X));
-  EXPECT_EQ(OK, node1.ClosePort(Y));
+  ASSERT_EQ(OK, node1.node().GetPort(message->ports()[0], &E));
 
-  // C goes away as a result of normal proxy removal.
-  PumpTasks();
+  EXPECT_EQ(OK, node1.node().ClosePort(X));
+  EXPECT_EQ(OK, node1.node().ClosePort(Y));
 
-  EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.GetPort(C.name(), &C));
+  WaitForIdle();
 
-  // B should have been closed cleanly.
-  EXPECT_EQ(ERROR_PORT_UNKNOWN, node0.GetPort(B.name(), &B));
+  // C goes away as a result of normal proxy removal. B should have been closed
+  // cleanly by the failed MergePorts.
+  EXPECT_EQ(ERROR_PORT_UNKNOWN, node1.node().GetPort(C.name(), &C));
+  EXPECT_EQ(ERROR_PORT_UNKNOWN, node0.node().GetPort(B.name(), &B));
 
   // Close A, D, and E.
-  EXPECT_EQ(OK, node0.ClosePort(A));
-  EXPECT_EQ(OK, node1.ClosePort(D));
-  EXPECT_EQ(OK, node1.ClosePort(E));
+  EXPECT_EQ(OK, node0.node().ClosePort(A));
+  EXPECT_EQ(OK, node1.node().ClosePort(D));
+  EXPECT_EQ(OK, node1.node().ClosePort(E));
 
-  PumpTasks();
+  WaitForIdle();
 
   // Expect everything to have gone away.
-  EXPECT_TRUE(node0.CanShutdownCleanly(false));
-  EXPECT_TRUE(node1.CanShutdownCleanly(false));
+  EXPECT_TRUE(node0.node().CanShutdownCleanly());
+  EXPECT_TRUE(node1.node().CanShutdownCleanly());
 }
 
 }  // namespace test
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
index 27c734c..565e70c 100644
--- a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
+++ b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
@@ -23,6 +23,8 @@
 
     private static final String TOKEN_SCOPE = "oauth2:https://www.googleapis.com/auth/chromoting";
 
+    private static final String LIBRARY_NAME = "remoting_client_jni";
+
     // Used to fetch auth token for native client.
     private static OAuthTokenConsumer sLoggerTokenConsumer;
 
@@ -36,7 +38,12 @@
     public static void loadLibrary(Context context) {
         ContextUtils.initApplicationContext(context.getApplicationContext());
         sLoggerTokenConsumer = new OAuthTokenConsumer(context.getApplicationContext(), TOKEN_SCOPE);
-        System.loadLibrary("remoting_client_jni");
+        try {
+            System.loadLibrary(LIBRARY_NAME);
+        } catch (UnsatisfiedLinkError e) {
+            Log.w(TAG, "Couldn't load " + LIBRARY_NAME + ", trying " + LIBRARY_NAME + ".cr");
+            System.loadLibrary(LIBRARY_NAME + ".cr");
+        }
         ContextUtils.initApplicationContextForNative();
         nativeLoadNative();
     }
diff --git a/services/catalog/catalog.cc b/services/catalog/catalog.cc
index 53efd08..bcd03c5 100644
--- a/services/catalog/catalog.cc
+++ b/services/catalog/catalog.cc
@@ -104,10 +104,11 @@
                                   weak_factory_.GetWeakPtr()));
 }
 
-bool Catalog::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Catalog>(this);
-  connection->AddInterface<filesystem::mojom::Directory>(this);
-  connection->AddInterface<shell::mojom::Resolver>(this);
+bool Catalog::OnConnect(const shell::Identity& remote_identity,
+                        shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Catalog>(this);
+  registry->AddInterface<filesystem::mojom::Directory>(this);
+  registry->AddInterface<shell::mojom::Resolver>(this);
   return true;
 }
 
diff --git a/services/catalog/catalog.h b/services/catalog/catalog.h
index 4bd016dc..7afced34 100644
--- a/services/catalog/catalog.h
+++ b/services/catalog/catalog.h
@@ -64,7 +64,8 @@
   void ScanSystemPackageDir();
 
   // shell::Service:
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // shell::InterfaceFactory<shell::mojom::Resolver>:
   void Create(const shell::Identity& remote_identity,
diff --git a/services/navigation/navigation.cc b/services/navigation/navigation.cc
index 46a6236..4637586 100644
--- a/services/navigation/navigation.cc
+++ b/services/navigation/navigation.cc
@@ -35,9 +35,10 @@
 }
 Navigation::~Navigation() {}
 
-bool Navigation::OnConnect(shell::Connection* connection,
+bool Navigation::OnConnect(const shell::Identity& remote_identity,
+                           shell::InterfaceRegistry* registry,
                            shell::Connector* connector) {
-  std::string remote_user_id = connection->GetRemoteIdentity().user_id();
+  std::string remote_user_id = remote_identity.user_id();
   if (!client_user_id_.empty() && client_user_id_ != remote_user_id) {
     LOG(ERROR) << "Must have a separate Navigation service instance for "
                << "different BrowserContexts.";
@@ -45,7 +46,7 @@
   }
   client_user_id_ = remote_user_id;
 
-  connection->AddInterface<mojom::ViewFactory>(this);
+  registry->AddInterface<mojom::ViewFactory>(this);
   return true;
 }
 
diff --git a/services/navigation/navigation.h b/services/navigation/navigation.h
index dc214ad..3a40a7b 100644
--- a/services/navigation/navigation.h
+++ b/services/navigation/navigation.h
@@ -29,7 +29,8 @@
 
  private:
   // content::ConnectionFilter:
-  bool OnConnect(shell::Connection* connection,
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry,
                  shell::Connector* connector) override;
 
   // shell::InterfaceFactory<mojom::ViewFactory>:
diff --git a/services/shell/background/tests/test_service.cc b/services/shell/background/tests/test_service.cc
index 9575e1a..cde26bb 100644
--- a/services/shell/background/tests/test_service.cc
+++ b/services/shell/background/tests/test_service.cc
@@ -5,7 +5,7 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/shell/background/tests/test.mojom.h"
 #include "services/shell/public/c/main.h"
-#include "services/shell/public/cpp/connection.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/cpp/service_runner.h"
 
@@ -20,8 +20,9 @@
 
  private:
   // Service:
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface(this);
     return true;
   }
   bool OnStop() override {
diff --git a/services/shell/public/cpp/connection.h b/services/shell/public/cpp/connection.h
index 002cb7d4..1035eb6 100644
--- a/services/shell/public/cpp/connection.h
+++ b/services/shell/public/cpp/connection.h
@@ -5,40 +5,16 @@
 #ifndef SERVICES_SHELL_PUBLIC_CPP_CONNECTION_H_
 #define SERVICES_SHELL_PUBLIC_CPP_CONNECTION_H_
 
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-
-#include "base/callback_forward.h"
 #include "base/memory/weak_ptr.h"
-#include "services/shell/public/cpp/connect.h"
 #include "services/shell/public/cpp/identity.h"
 #include "services/shell/public/cpp/interface_provider.h"
-#include "services/shell/public/cpp/interface_registry.h"
-#include "services/shell/public/interfaces/connector.mojom.h"
-#include "services/shell/public/interfaces/interface_provider.mojom.h"
 
 namespace shell {
 
-class InterfaceBinder;
 class InterfaceProvider;
 
-// Represents a connection to another application. An instance of this class is
-// returned from Shell's ConnectToApplication(), and passed to Service's
-// OnConnect() each time an incoming connection is received.
-//
-// Call AddService<T>(factory) to expose an interface to the remote application,
-// and GetInterface(&interface_ptr) to consume an interface exposed by the
-// remote application.
-//
-// Internally, this class wraps an InterfaceRegistry that accepts interfaces
-// that may be exposed to a remote application. See documentation in
-// interface_registry.h for more information.
-//
-// A Connection returned via Shell::ConnectToApplication() is owned by the
-// caller. A Connection received via OnConnect is owned by the ServiceContext.
-// To close a connection, call CloseConnection which will destroy this object.
+// Represents a connection to another application. An implementation of this
+// interface is returned from Connector::Connect().
 class Connection {
  public:
   virtual ~Connection() {}
@@ -67,22 +43,6 @@
     Connection* connection_;
   };
 
-  // Allow the remote application to request instances of Interface.
-  // |factory| will create implementations of Interface on demand.
-  // Returns true if the interface was exposed, false if capability filtering
-  // from the shell prevented the interface from being exposed.
-  template <typename Interface>
-  bool AddInterface(InterfaceFactory<Interface>* factory) {
-    return GetInterfaceRegistry()->AddInterface<Interface>(factory);
-  }
-  template <typename Interface>
-  bool AddInterface(
-      const base::Callback<void(mojo::InterfaceRequest<Interface>)>& callback,
-      const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
-    return GetInterfaceRegistry()->AddInterface<Interface>(
-        callback, task_runner);
-  }
-
   // Binds |ptr| to an implementation of Interface in the remote application.
   // |ptr| can immediately be used to start sending requests to the remote
   // interface.
@@ -95,11 +55,6 @@
     GetRemoteInterfaces()->GetInterface(std::move(request));
   }
 
-  // Returns true if the remote application has the specified capability class
-  // specified in its manifest. Only valid for inbound connections. Will return
-  // false for outbound connections.
-  virtual bool HasCapabilityClass(const std::string& class_name) const = 0;
-
   // Returns the remote identity. While the connection is in the pending state,
   // the user_id() field will be the value passed via Connect(). After the
   // connection is completed, it will change to the value assigned by the shell.
@@ -126,14 +81,6 @@
   // available immediately.
   virtual void AddConnectionCompletedClosure(const base::Closure& callback) = 0;
 
-  // Returns true if the Shell allows |interface_name| to be exposed to the
-  // remote application.
-  virtual bool AllowsInterface(const std::string& interface_name) const = 0;
-
-  // Returns the InterfaceRegistry that implements the mojom::InterfaceProvider
-  // exposed to the remote application.
-  virtual InterfaceRegistry* GetInterfaceRegistry() = 0;
-
   // Returns an object encapsulating a remote InterfaceProvider.
   virtual InterfaceProvider* GetRemoteInterfaces() = 0;
 
diff --git a/services/shell/public/cpp/interface_registry.h b/services/shell/public/cpp/interface_registry.h
index ab62a8c..e1cc51a 100644
--- a/services/shell/public/cpp/interface_registry.h
+++ b/services/shell/public/cpp/interface_registry.h
@@ -13,6 +13,8 @@
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/shell/public/cpp/capabilities.h"
+#include "services/shell/public/cpp/identity.h"
 #include "services/shell/public/cpp/lib/callback_binder.h"
 #include "services/shell/public/cpp/lib/interface_factory_binder.h"
 #include "services/shell/public/interfaces/interface_provider.mojom.h"
@@ -64,12 +66,13 @@
     DISALLOW_COPY_AND_ASSIGN(TestApi);
   };
 
-  // Construct with a Connection (which may be null), and create an
-  // InterfaceProvider pipe, the client end of which may be obtained by calling
-  // TakeClientHandle(). If |connection| is non-null, the Mojo Shell's
-  // rules filtering which interfaces are allowed to be exposed to clients are
-  // imposed on this registry. If null, they are not.
-  explicit InterfaceRegistry(Connection* connection);
+  // Construct an InterfaceRegistry with no filtering rules applied.
+  InterfaceRegistry();
+
+  // Construct an InterfaceRegistry with filtering rules as specified in
+  // |capability_request| applied.
+  InterfaceRegistry(const Identity& remote_identity,
+                    const CapabilityRequest& capability_request);
   ~InterfaceRegistry() override;
 
   // Sets a default handler for incoming interface requests which are allowed by
@@ -143,13 +146,18 @@
   bool SetInterfaceBinderForName(std::unique_ptr<InterfaceBinder> binder,
                                  const std::string& name);
 
+  // Returns true if |remote_identity_| is allowed to bind |interface_name|,
+  // according to capability policy.
+  bool CanBindRequestForInterface(const std::string& interface_name) const;
+
   mojom::InterfaceProviderRequest pending_request_;
 
   mojo::Binding<mojom::InterfaceProvider> binding_;
-  Connection* connection_;
+  const Identity remote_identity_;
+  const CapabilityRequest capability_request_;
+  const bool allow_all_interfaces_;
 
   NameToInterfaceBinderMap name_to_binder_;
-
   Binder default_binder_;
 
   bool is_paused_ = false;
diff --git a/services/shell/public/cpp/lib/connection_impl.cc b/services/shell/public/cpp/lib/connection_impl.cc
index 9fa2995..870727c 100644
--- a/services/shell/public/cpp/lib/connection_impl.cc
+++ b/services/shell/public/cpp/lib/connection_impl.cc
@@ -20,29 +20,16 @@
 // ConnectionImpl, public:
 
 ConnectionImpl::ConnectionImpl()
-    : allow_all_interfaces_(true),
-      weak_factory_(this) {}
+    : weak_factory_(this) {}
 
-ConnectionImpl::ConnectionImpl(
-    const Identity& remote,
-    const CapabilityRequest& capability_request,
-    State initial_state)
+ConnectionImpl::ConnectionImpl(const Identity& remote, State initial_state)
     : remote_(remote),
       state_(initial_state),
-      capability_request_(capability_request),
-      allow_all_interfaces_(capability_request.interfaces.size() == 1 &&
-                            capability_request.interfaces.count("*") == 1),
       weak_factory_(this) {
 }
 
 ConnectionImpl::~ConnectionImpl() {}
 
-void ConnectionImpl::SetExposedInterfaces(
-    std::unique_ptr<InterfaceRegistry> exposed_interfaces) {
-  exposed_interfaces_owner_ = std::move(exposed_interfaces);
-  set_exposed_interfaces(exposed_interfaces_owner_.get());
-}
-
 void ConnectionImpl::SetRemoteInterfaces(
     std::unique_ptr<InterfaceProvider> remote_interfaces) {
   remote_interfaces_owner_ = std::move(remote_interfaces);
@@ -57,19 +44,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ConnectionImpl, Connection implementation:
 
-bool ConnectionImpl::HasCapabilityClass(const std::string& class_name) const {
-  return capability_request_.classes.count(class_name) > 0;
-}
-
 const Identity& ConnectionImpl::GetRemoteIdentity() const {
   return remote_;
 }
 
 void ConnectionImpl::SetConnectionLostClosure(const base::Closure& handler) {
-  if (remote_interfaces_)
-    remote_interfaces_->SetConnectionLostClosure(handler);
-  else
-    exposed_interfaces_->SetConnectionLostClosure(handler);
+  remote_interfaces_->SetConnectionLostClosure(handler);
 }
 
 shell::mojom::ConnectResult ConnectionImpl::GetResult() const {
@@ -88,15 +68,6 @@
     callback.Run();
 }
 
-bool ConnectionImpl::AllowsInterface(const std::string& interface_name) const {
-  return allow_all_interfaces_ ||
-         capability_request_.interfaces.count(interface_name);
-}
-
-InterfaceRegistry* ConnectionImpl::GetInterfaceRegistry() {
-  return exposed_interfaces_;
-}
-
 InterfaceProvider* ConnectionImpl::GetRemoteInterfaces() {
   return remote_interfaces_;
 }
diff --git a/services/shell/public/cpp/lib/connection_impl.h b/services/shell/public/cpp/lib/connection_impl.h
index 690644d0..363ef4f 100644
--- a/services/shell/public/cpp/lib/connection_impl.h
+++ b/services/shell/public/cpp/lib/connection_impl.h
@@ -27,25 +27,14 @@
 class ConnectionImpl : public Connection {
  public:
   ConnectionImpl();
-  // |allowed_interfaces| are the set of interfaces that the shell has allowed
-  // an application to expose to another application. If this set contains only
-  // the string value "*" all interfaces may be exposed.
-  ConnectionImpl(const Identity& remote,
-                 const CapabilityRequest& capability_request,
-                 State initial_state);
+  ConnectionImpl(const Identity& remote, State initial_state);
   ~ConnectionImpl() override;
 
-  // Sets the local registry & remote provider, transferring ownership to the
-  // ConnectionImpl.
-  void SetExposedInterfaces(
-      std::unique_ptr<InterfaceRegistry> exposed_interfaces);
+  // Sets the remote provider, transferring ownership to the ConnectionImpl.
   void SetRemoteInterfaces(
       std::unique_ptr<InterfaceProvider> remote_interfaces);
 
-  // Sets the local registry & remote provider, without transferring ownership.
-  void set_exposed_interfaces(InterfaceRegistry* exposed_interfaces) {
-    exposed_interfaces_ = exposed_interfaces;
-  }
+  // Sets the remote provider, without transferring ownership.
   void set_remote_interfaces(InterfaceProvider* remote_interfaces) {
     remote_interfaces_ = remote_interfaces;
   }
@@ -54,14 +43,11 @@
 
  private:
   // Connection:
-  bool HasCapabilityClass(const std::string& class_name) const override;
   const Identity& GetRemoteIdentity() const override;
   void SetConnectionLostClosure(const base::Closure& handler) override;
   shell::mojom::ConnectResult GetResult() const override;
   bool IsPending() const override;
   void AddConnectionCompletedClosure(const base::Closure& callback) override;
-  bool AllowsInterface(const std::string& interface_name) const override;
-  InterfaceRegistry* GetInterfaceRegistry() override;
   InterfaceProvider* GetRemoteInterfaces() override;
   base::WeakPtr<Connection> GetWeakPtr() override;
 
@@ -74,15 +60,10 @@
   shell::mojom::ConnectResult result_ = shell::mojom::ConnectResult::SUCCEEDED;
   std::vector<base::Closure> connection_completed_callbacks_;
 
-  InterfaceRegistry* exposed_interfaces_ = nullptr;
   InterfaceProvider* remote_interfaces_ = nullptr;
 
-  std::unique_ptr<InterfaceRegistry> exposed_interfaces_owner_;
   std::unique_ptr<InterfaceProvider> remote_interfaces_owner_;
 
-  const CapabilityRequest capability_request_;
-  const bool allow_all_interfaces_;
-
   base::WeakPtrFactory<ConnectionImpl> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ConnectionImpl);
diff --git a/services/shell/public/cpp/lib/connector_impl.cc b/services/shell/public/cpp/lib/connector_impl.cc
index f7faf96..f464137 100644
--- a/services/shell/public/cpp/lib/connector_impl.cc
+++ b/services/shell/public/cpp/lib/connector_impl.cc
@@ -48,14 +48,10 @@
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(params);
 
-  // We allow all interfaces on outgoing connections since we are presumably in
-  // a position to know who we're talking to.
-  CapabilityRequest request;
-  request.interfaces.insert("*");
   mojom::InterfaceProviderPtr remote_interfaces;
   mojom::InterfaceProviderRequest remote_request = GetProxy(&remote_interfaces);
   std::unique_ptr<internal::ConnectionImpl> connection(
-      new internal::ConnectionImpl(params->target(), request,
+      new internal::ConnectionImpl(params->target(),
                                    Connection::State::PENDING));
   if (params->remote_interfaces()) {
     params->remote_interfaces()->Bind(std::move(remote_interfaces));
diff --git a/services/shell/public/cpp/lib/interface_registry.cc b/services/shell/public/cpp/lib/interface_registry.cc
index 536bbabd..6a82a77 100644
--- a/services/shell/public/cpp/lib/interface_registry.cc
+++ b/services/shell/public/cpp/lib/interface_registry.cc
@@ -8,8 +8,19 @@
 
 namespace shell {
 
-InterfaceRegistry::InterfaceRegistry(Connection* connection)
-    : binding_(this), connection_(connection), weak_factory_(this) {}
+InterfaceRegistry::InterfaceRegistry()
+    : binding_(this), allow_all_interfaces_(true), weak_factory_(this) {}
+
+InterfaceRegistry::InterfaceRegistry(
+    const Identity& remote_identity,
+    const CapabilityRequest& capability_request)
+    : binding_(this),
+      remote_identity_(remote_identity),
+      capability_request_(capability_request),
+      allow_all_interfaces_(capability_request.interfaces.size() == 1 &&
+                            capability_request.interfaces.count("*") == 1),
+      weak_factory_(this) {}
+
 InterfaceRegistry::~InterfaceRegistry() {}
 
 void InterfaceRegistry::Bind(
@@ -76,14 +87,12 @@
 
   auto iter = name_to_binder_.find(interface_name);
   if (iter != name_to_binder_.end()) {
-    Identity remote_identity =
-        connection_ ? connection_->GetRemoteIdentity() : Identity();
-    iter->second->BindInterface(remote_identity,
+    iter->second->BindInterface(remote_identity_,
                                 interface_name,
                                 std::move(handle));
-  } else if (connection_ && !connection_->AllowsInterface(interface_name)) {
+  } else if (!CanBindRequestForInterface(interface_name)) {
     LOG(ERROR) << "Capability spec prevented service: "
-               << connection_->GetRemoteIdentity().name()
+               << remote_identity_.name()
                << " from binding interface: " << interface_name;
   } else if (!default_binder_.is_null()) {
     default_binder_.Run(interface_name, std::move(handle));
@@ -95,8 +104,7 @@
 bool InterfaceRegistry::SetInterfaceBinderForName(
     std::unique_ptr<InterfaceBinder> binder,
     const std::string& interface_name) {
-  if (!connection_ ||
-      (connection_ && connection_->AllowsInterface(interface_name))) {
+  if (CanBindRequestForInterface(interface_name)) {
     RemoveInterface(interface_name);
     name_to_binder_[interface_name] = std::move(binder);
     return true;
@@ -104,4 +112,10 @@
   return false;
 }
 
+bool InterfaceRegistry::CanBindRequestForInterface(
+    const std::string& interface_name) const {
+  return allow_all_interfaces_ ||
+      capability_request_.interfaces.count(interface_name);
+}
+
 }  // namespace shell
diff --git a/services/shell/public/cpp/lib/service.cc b/services/shell/public/cpp/lib/service.cc
index db9eb31..aa45468 100644
--- a/services/shell/public/cpp/lib/service.cc
+++ b/services/shell/public/cpp/lib/service.cc
@@ -13,20 +13,13 @@
 
 void Service::OnStart(const Identity& identity) {}
 
-bool Service::OnConnect(Connection* connection) {
+bool Service::OnConnect(const Identity& remote_identity,
+                        InterfaceRegistry* registry) {
   return false;
 }
 
 bool Service::OnStop() { return true; }
 
-InterfaceProvider* Service::GetInterfaceProviderForConnection() {
-  return nullptr;
-}
-
-InterfaceRegistry* Service::GetInterfaceRegistryForConnection() {
-  return nullptr;
-}
-
 Connector* Service::connector() {
   return context_->connector();
 }
diff --git a/services/shell/public/cpp/lib/service_context.cc b/services/shell/public/cpp/lib/service_context.cc
index 3da21a4..92ee74fce0 100644
--- a/services/shell/public/cpp/lib/service_context.cc
+++ b/services/shell/public/cpp/lib/service_context.cc
@@ -10,7 +10,7 @@
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "services/shell/public/cpp/capabilities.h"
-#include "services/shell/public/cpp/lib/connection_impl.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/lib/connector_impl.h"
 #include "services/shell/public/cpp/service.h"
 
@@ -66,22 +66,18 @@
     mojom::IdentityPtr source,
     mojom::InterfaceProviderRequest interfaces,
     mojom::CapabilityRequestPtr allowed_capabilities) {
-  std::unique_ptr<internal::ConnectionImpl> connection(
-      new internal::ConnectionImpl(source.To<Identity>(),
-                                   allowed_capabilities.To<CapabilityRequest>(),
-                                   Connection::State::CONNECTED));
+  shell::Identity remote_identity = source.To<Identity>();
+  std::unique_ptr<InterfaceRegistry> registry(
+      new InterfaceRegistry(remote_identity,
+                            allowed_capabilities.To<CapabilityRequest>()));
+  registry->Bind(std::move(interfaces));
 
-  std::unique_ptr<InterfaceRegistry> exposed_interfaces(
-      new InterfaceRegistry(connection.get()));
-  exposed_interfaces->Bind(std::move(interfaces));
-  connection->SetExposedInterfaces(std::move(exposed_interfaces));
-
-  if (!service_->OnConnect(connection.get()))
+  if (!service_->OnConnect(remote_identity, registry.get()))
     return;
 
   // TODO(beng): it appears we never prune this list. We should, when the
-  //             connection's remote service provider pipe breaks.
-  incoming_connections_.push_back(std::move(connection));
+  //             registry's remote interface provider pipe breaks.
+  incoming_connections_.push_back(std::move(registry));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/services/shell/public/cpp/service.h b/services/shell/public/cpp/service.h
index 2ad2a57..f7f2bee 100644
--- a/services/shell/public/cpp/service.h
+++ b/services/shell/public/cpp/service.h
@@ -9,12 +9,13 @@
 #include <string>
 
 #include "base/macros.h"
-#include "services/shell/public/cpp/connection.h"
-#include "services/shell/public/cpp/identity.h"
+#include "services/shell/public/cpp/interface_registry.h"
 
 namespace shell {
 
 class Connector;
+class Identity;
+class InterfaceRegistry;
 class ServiceContext;
 
 // The primary contract between a Service and the Service Manager, receiving
@@ -35,7 +36,8 @@
   // if the connection should succeed. Return false if the connection should
   // be rejected and the underlying pipe closed. The default implementation
   // returns false.
-  virtual bool OnConnect(Connection* connection);
+  virtual bool OnConnect(const Identity& remote_identity,
+                         InterfaceRegistry* registry);
 
   // Called when the Service Manager has stopped tracking this instance. The
   // service should use this as a signal to exit, and in fact its process may
@@ -48,10 +50,6 @@
   // quitting.
   virtual bool OnStop();
 
-  // TODO(rockot): remove
-  virtual InterfaceProvider* GetInterfaceProviderForConnection();
-  virtual InterfaceRegistry* GetInterfaceRegistryForConnection();
-
   Connector* connector();
   ServiceContext* context();
   void set_context(std::unique_ptr<ServiceContext> context);
diff --git a/services/shell/public/cpp/service_context.h b/services/shell/public/cpp/service_context.h
index 94764eb..eec15ad 100644
--- a/services/shell/public/cpp/service_context.h
+++ b/services/shell/public/cpp/service_context.h
@@ -78,7 +78,7 @@
 
   // We track the lifetime of incoming connection registries as it more
   // convenient for the client.
-  std::vector<std::unique_ptr<Connection>> incoming_connections_;
+  std::vector<std::unique_ptr<InterfaceRegistry>> incoming_connections_;
 
   // A pending Connector request which will eventually be passed to the Service
   // Manager.
diff --git a/services/shell/public/cpp/tests/interface_registry_unittest.cc b/services/shell/public/cpp/tests/interface_registry_unittest.cc
index ed3205d..747d9da2 100644
--- a/services/shell/public/cpp/tests/interface_registry_unittest.cc
+++ b/services/shell/public/cpp/tests/interface_registry_unittest.cc
@@ -30,7 +30,7 @@
 
   // Destruction.
   {
-    InterfaceRegistry registry(nullptr);
+    InterfaceRegistry registry;
     InterfaceRegistry::TestApi test_api(&registry);
     test_api.SetInterfaceBinderForName(new TestBinder(&delete_count), "TC1");
   }
@@ -38,7 +38,7 @@
 
   // Removal.
   {
-    std::unique_ptr<InterfaceRegistry> registry(new InterfaceRegistry(nullptr));
+    std::unique_ptr<InterfaceRegistry> registry(new InterfaceRegistry);
     InterfaceBinder* b = new TestBinder(&delete_count);
     InterfaceRegistry::TestApi test_api(registry.get());
     test_api.SetInterfaceBinderForName(b, "TC1");
@@ -49,7 +49,7 @@
 
   // Multiple.
   {
-    InterfaceRegistry registry(nullptr);
+    InterfaceRegistry registry;
     InterfaceRegistry::TestApi test_api(&registry);
     test_api.SetInterfaceBinderForName(new TestBinder(&delete_count), "TC1");
     test_api.SetInterfaceBinderForName(new TestBinder(&delete_count), "TC2");
@@ -58,7 +58,7 @@
 
   // Re-addition.
   {
-    InterfaceRegistry registry(nullptr);
+    InterfaceRegistry registry;
     InterfaceRegistry::TestApi test_api(&registry);
     test_api.SetInterfaceBinderForName(new TestBinder(&delete_count), "TC1");
     test_api.SetInterfaceBinderForName(new TestBinder(&delete_count), "TC1");
diff --git a/services/shell/service_manager.cc b/services/shell/service_manager.cc
index 28faee3..aa096e64 100644
--- a/services/shell/service_manager.cc
+++ b/services/shell/service_manager.cc
@@ -245,8 +245,9 @@
   uint32_t id() const { return id_; }
 
   // Service:
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<mojom::ServiceManager>(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<mojom::ServiceManager>(this);
     return true;
   }
 
@@ -531,20 +532,21 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ServiceManager, Service implementation:
 
-bool ServiceManager::OnConnect(Connection* connection) {
+bool ServiceManager::OnConnect(const Identity& remote_identity,
+                               InterfaceRegistry* registry) {
   // The only interface we expose is mojom::ServiceManager, and access to this
   // interface is brokered by a policy specific to each caller, managed by the
   // caller's instance. Here we look to see who's calling, and forward to the
   // caller's instance to continue.
   Instance* instance = nullptr;
   for (const auto& entry : identity_to_instance_) {
-    if (entry.first == connection->GetRemoteIdentity()) {
+    if (entry.first == remote_identity) {
       instance = entry.second;
       break;
     }
   }
   DCHECK(instance);
-  return instance->OnConnect(connection);
+  return instance->OnConnect(remote_identity, registry);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/services/shell/service_manager.h b/services/shell/service_manager.h
index d6e6b5d73..655e495 100644
--- a/services/shell/service_manager.h
+++ b/services/shell/service_manager.h
@@ -77,7 +77,8 @@
   class Instance;
 
   // Service:
-  bool OnConnect(Connection* connection) override;
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override;
 
   void InitCatalog(mojom::ServicePtr catalog);
 
diff --git a/services/shell/tests/connect/connect_test_app.cc b/services/shell/tests/connect/connect_test_app.cc
index 02992a66..e367e0c0 100644
--- a/services/shell/tests/connect/connect_test_app.cc
+++ b/services/shell/tests/connect/connect_test_app.cc
@@ -13,6 +13,7 @@
 #include "services/shell/public/c/main.h"
 #include "services/shell/public/cpp/connector.h"
 #include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/cpp/service_runner.h"
 #include "services/shell/public/interfaces/connector.mojom.h"
@@ -61,19 +62,20 @@
         base::Bind(&ConnectTestApp::OnConnectionError,
                    base::Unretained(this)));
   }
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<test::mojom::ConnectTestService>(this);
-    connection->AddInterface<test::mojom::StandaloneApp>(this);
-    connection->AddInterface<test::mojom::BlockedInterface>(this);
-    connection->AddInterface<test::mojom::UserIdTest>(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<test::mojom::ConnectTestService>(this);
+    registry->AddInterface<test::mojom::StandaloneApp>(this);
+    registry->AddInterface<test::mojom::BlockedInterface>(this);
+    registry->AddInterface<test::mojom::UserIdTest>(this);
 
     test::mojom::ConnectionStatePtr state(test::mojom::ConnectionState::New());
-    state->connection_remote_name = connection->GetRemoteIdentity().name();
-    state->connection_remote_userid = connection->GetRemoteIdentity().user_id();
+    state->connection_remote_name = remote_identity.name();
+    state->connection_remote_userid = remote_identity.user_id();
     state->initialize_local_name = identity_.name();
     state->initialize_userid = identity_.user_id();
 
-    connector()->ConnectToInterface(connection->GetRemoteIdentity(), &caller_);
+    connector()->ConnectToInterface(remote_identity, &caller_);
     caller_->ConnectionAccepted(std::move(state));
 
     return true;
diff --git a/services/shell/tests/connect/connect_test_class_app.cc b/services/shell/tests/connect/connect_test_class_app.cc
index b7045b7..1431e5f 100644
--- a/services/shell/tests/connect/connect_test_class_app.cc
+++ b/services/shell/tests/connect/connect_test_class_app.cc
@@ -10,6 +10,7 @@
 #include "services/shell/public/c/main.h"
 #include "services/shell/public/cpp/connector.h"
 #include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/cpp/service_runner.h"
 #include "services/shell/public/interfaces/connector.mojom.h"
@@ -34,13 +35,14 @@
   void OnStart(const Identity& identity) override {
     identity_ = identity;
   }
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<test::mojom::ConnectTestService>(this);
-    connection->AddInterface<test::mojom::ClassInterface>(this);
-    inbound_connections_.insert(connection);
-    connection->SetConnectionLostClosure(
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<test::mojom::ConnectTestService>(this);
+    registry->AddInterface<test::mojom::ClassInterface>(this);
+    inbound_connections_.insert(registry);
+    registry->SetConnectionLostClosure(
         base::Bind(&ConnectTestClassApp::OnConnectionError,
-                   base::Unretained(this), connection));
+                   base::Unretained(this), registry));
     return true;
   }
 
@@ -69,8 +71,8 @@
     callback.Run("PONG");
   }
 
-  void OnConnectionError(Connection* connection) {
-    auto it = inbound_connections_.find(connection);
+  void OnConnectionError(InterfaceRegistry* registry) {
+    auto it = inbound_connections_.find(registry);
     DCHECK(it != inbound_connections_.end());
     inbound_connections_.erase(it);
     if (inbound_connections_.empty())
@@ -78,7 +80,7 @@
   }
 
   Identity identity_;
-  std::set<Connection*> inbound_connections_;
+  std::set<InterfaceRegistry*> inbound_connections_;
   mojo::BindingSet<test::mojom::ConnectTestService> bindings_;
   mojo::BindingSet<test::mojom::ClassInterface> class_interface_bindings_;
 
diff --git a/services/shell/tests/connect/connect_test_driver.cc b/services/shell/tests/connect/connect_test_driver.cc
index 88579201..27b31cb 100644
--- a/services/shell/tests/connect/connect_test_driver.cc
+++ b/services/shell/tests/connect/connect_test_driver.cc
@@ -31,8 +31,9 @@
 
  private:
   // shell::Service:
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<ClientProcessTest>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+    shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<ClientProcessTest>(this);
     return true;
   }
   bool OnStop() override {
diff --git a/services/shell/tests/connect/connect_test_exe.cc b/services/shell/tests/connect/connect_test_exe.cc
index 58a7c426..7060c8d1 100644
--- a/services/shell/tests/connect/connect_test_exe.cc
+++ b/services/shell/tests/connect/connect_test_exe.cc
@@ -8,6 +8,8 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/shell/public/cpp/connection.h"
 #include "services/shell/public/cpp/connector.h"
+#include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/runner/child/test_native_main.h"
 #include "services/shell/runner/init.h"
@@ -30,8 +32,9 @@
   void OnStart(const shell::Identity& identity) override {
     identity_ = identity;
   }
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<ConnectTestService>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<ConnectTestService>(this);
     return true;
   }
 
diff --git a/services/shell/tests/connect/connect_test_package.cc b/services/shell/tests/connect/connect_test_package.cc
index cc5d73a..e913c1e 100644
--- a/services/shell/tests/connect/connect_test_package.cc
+++ b/services/shell/tests/connect/connect_test_package.cc
@@ -67,18 +67,19 @@
         base::Bind(&ProvidedService::OnConnectionError,
                    base::Unretained(this)));
   }
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<test::mojom::ConnectTestService>(this);
-    connection->AddInterface<test::mojom::BlockedInterface>(this);
-    connection->AddInterface<test::mojom::UserIdTest>(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<test::mojom::ConnectTestService>(this);
+    registry->AddInterface<test::mojom::BlockedInterface>(this);
+    registry->AddInterface<test::mojom::UserIdTest>(this);
 
     test::mojom::ConnectionStatePtr state(test::mojom::ConnectionState::New());
-    state->connection_remote_name = connection->GetRemoteIdentity().name();
-    state->connection_remote_userid = connection->GetRemoteIdentity().user_id();
+    state->connection_remote_name = remote_identity.name();
+    state->connection_remote_userid = remote_identity.user_id();
     state->initialize_local_name = identity_.name();
     state->initialize_userid = identity_.user_id();
 
-    connector()->ConnectToInterface(connection->GetRemoteIdentity(), &caller_);
+    connector()->ConnectToInterface(remote_identity, &caller_);
     caller_->ConnectionAccepted(std::move(state));
 
     return true;
@@ -174,9 +175,10 @@
         base::Bind(&ConnectTestService::OnConnectionError,
                    base::Unretained(this)));
   }
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<ServiceFactory>(this);
-    connection->AddInterface<test::mojom::ConnectTestService>(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<ServiceFactory>(this);
+    registry->AddInterface<test::mojom::ConnectTestService>(this);
     return true;
   }
 
diff --git a/services/shell/tests/connect/connect_test_singleton_app.cc b/services/shell/tests/connect/connect_test_singleton_app.cc
index 1505413..c4da059 100644
--- a/services/shell/tests/connect/connect_test_singleton_app.cc
+++ b/services/shell/tests/connect/connect_test_singleton_app.cc
@@ -16,7 +16,8 @@
 
  private:
   // shell::Service:
-  bool OnConnect(Connection* connection) override {
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
     return true;
   }
 
diff --git a/services/shell/tests/connect/connect_unittest.cc b/services/shell/tests/connect/connect_unittest.cc
index a1108934..5c2401e 100644
--- a/services/shell/tests/connect/connect_unittest.cc
+++ b/services/shell/tests/connect/connect_unittest.cc
@@ -107,8 +107,9 @@
     ~TestService() override {}
 
    private:
-    bool OnConnect(Connection* connection) override {
-      connection->AddInterface<test::mojom::ExposedInterface>(connect_test_);
+    bool OnConnect(const Identity& remote_identity,
+                   InterfaceRegistry* registry) override {
+      registry->AddInterface<test::mojom::ExposedInterface>(connect_test_);
       return true;
     }
 
diff --git a/services/shell/tests/lifecycle/app_client.cc b/services/shell/tests/lifecycle/app_client.cc
index b65c4ec..59502d31 100644
--- a/services/shell/tests/lifecycle/app_client.cc
+++ b/services/shell/tests/lifecycle/app_client.cc
@@ -4,6 +4,7 @@
 
 #include "services/shell/tests/lifecycle/app_client.h"
 
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service_context.h"
 
 namespace shell {
@@ -14,8 +15,9 @@
     : context_(new ServiceContext(this, std::move(request))) {}
 AppClient::~AppClient() {}
 
-bool AppClient::OnConnect(Connection* connection) {
-  connection->AddInterface<LifecycleControl>(this);
+bool AppClient::OnConnect(const Identity& remote_identity,
+                          InterfaceRegistry* registry) {
+  registry->AddInterface<LifecycleControl>(this);
   return true;
 }
 
diff --git a/services/shell/tests/lifecycle/app_client.h b/services/shell/tests/lifecycle/app_client.h
index 045cded0..55c6a86 100644
--- a/services/shell/tests/lifecycle/app_client.h
+++ b/services/shell/tests/lifecycle/app_client.h
@@ -37,7 +37,8 @@
   }
 
   // Service:
-  bool OnConnect(Connection* connection) override;
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override;
 
   // InterfaceFactory<LifecycleControl>:
   void Create(const Identity& remote_identity,
diff --git a/services/shell/tests/lifecycle/package.cc b/services/shell/tests/lifecycle/package.cc
index f2fdf9c..1926faf 100644
--- a/services/shell/tests/lifecycle/package.cc
+++ b/services/shell/tests/lifecycle/package.cc
@@ -38,8 +38,9 @@
 
  private:
   // shell::Service:
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<LifecycleControl>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<LifecycleControl>(this);
     return true;
   }
 
@@ -99,9 +100,10 @@
 
  private:
   // shell::test::AppClient:
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<shell::mojom::ServiceFactory>(this);
-    return app_client_.OnConnect(connection);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<shell::mojom::ServiceFactory>(this);
+    return app_client_.OnConnect(remote_identity, registry);
   }
 
   // shell::InterfaceFactory<shell::mojom::ServiceFactory>:
diff --git a/services/shell/tests/lifecycle/parent.cc b/services/shell/tests/lifecycle/parent.cc
index 1f5a9a4..3391e39 100644
--- a/services/shell/tests/lifecycle/parent.cc
+++ b/services/shell/tests/lifecycle/parent.cc
@@ -10,6 +10,8 @@
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/shell/public/c/main.h"
 #include "services/shell/public/cpp/connector.h"
+#include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/cpp/service_runner.h"
 #include "services/shell/tests/lifecycle/lifecycle_unittest.mojom.h"
@@ -32,8 +34,9 @@
 
  private:
   // Service:
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<shell::test::mojom::Parent>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<shell::test::mojom::Parent>(this);
     return true;
   }
 
diff --git a/services/shell/tests/shell/driver.cc b/services/shell/tests/shell/driver.cc
index b78d174..1f737b2 100644
--- a/services/shell/tests/shell/driver.cc
+++ b/services/shell/tests/shell/driver.cc
@@ -101,8 +101,9 @@
                                     child_token);
   }
 
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<shell::test::mojom::Driver>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<shell::test::mojom::Driver>(this);
     return true;
   }
 
diff --git a/services/shell/tests/shell/shell_unittest.cc b/services/shell/tests/shell/shell_unittest.cc
index edb5599..19f6126 100644
--- a/services/shell/tests/shell/shell_unittest.cc
+++ b/services/shell/tests/shell/shell_unittest.cc
@@ -39,8 +39,9 @@
 
  private:
   // test::ServiceTestClient:
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<test::mojom::CreateInstanceTest>(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<test::mojom::CreateInstanceTest>(this);
     return true;
   }
 
diff --git a/services/shell/tests/shutdown/shutdown_client_app.cc b/services/shell/tests/shutdown/shutdown_client_app.cc
index 102fb2b..c3c5918a 100644
--- a/services/shell/tests/shutdown/shutdown_client_app.cc
+++ b/services/shell/tests/shutdown/shutdown_client_app.cc
@@ -8,6 +8,7 @@
 #include "services/shell/public/c/main.h"
 #include "services/shell/public/cpp/connector.h"
 #include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/cpp/service_runner.h"
 #include "services/shell/tests/shutdown/shutdown_unittest.mojom.h"
@@ -25,8 +26,9 @@
 
  private:
   // shell::Service:
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<mojom::ShutdownTestClientController>(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<mojom::ShutdownTestClientController>(this);
     return true;
   }
 
diff --git a/services/shell/tests/shutdown/shutdown_service_app.cc b/services/shell/tests/shutdown/shutdown_service_app.cc
index b5db4fb..2aa562b 100644
--- a/services/shell/tests/shutdown/shutdown_service_app.cc
+++ b/services/shell/tests/shutdown/shutdown_service_app.cc
@@ -5,6 +5,8 @@
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/shell/public/c/main.h"
+#include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "services/shell/public/cpp/service.h"
 #include "services/shell/public/cpp/service_runner.h"
 #include "services/shell/tests/shutdown/shutdown_unittest.mojom.h"
@@ -24,8 +26,9 @@
 
  private:
   // shell::Service:
-  bool OnConnect(Connection* connection) override {
-    connection->AddInterface<mojom::ShutdownTestService>(this);
+  bool OnConnect(const Identity& remote_identity,
+                 InterfaceRegistry* registry) override {
+    registry->AddInterface<mojom::ShutdownTestService>(this);
     return true;
   }
 
diff --git a/services/tracing/service.cc b/services/tracing/service.cc
index 5cf938c..2d61ff42 100644
--- a/services/tracing/service.cc
+++ b/services/tracing/service.cc
@@ -12,16 +12,18 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
+#include "services/shell/public/cpp/interface_registry.h"
 
 namespace tracing {
 
 Service::Service() : collector_binding_(this), tracing_active_(false) {}
 Service::~Service() {}
 
-bool Service::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::Factory>(this);
-  connection->AddInterface<mojom::Collector>(this);
-  connection->AddInterface<mojom::StartupPerformanceDataCollector>(this);
+bool Service::OnConnect(const shell::Identity& remote_identity,
+                        shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::Factory>(this);
+  registry->AddInterface<mojom::Collector>(this);
+  registry->AddInterface<mojom::StartupPerformanceDataCollector>(this);
   return true;
 }
 
diff --git a/services/tracing/service.h b/services/tracing/service.h
index 4c8f39c..c80a732 100644
--- a/services/tracing/service.h
+++ b/services/tracing/service.h
@@ -36,7 +36,8 @@
 
  private:
   // shell::Service implementation.
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
   bool OnStop() override;
 
   // shell::InterfaceFactory<mojom::Factory>:
diff --git a/services/ui/common/gpu_service.cc b/services/ui/common/gpu_service.cc
index 9a2f4c56..113d086 100644
--- a/services/ui/common/gpu_service.cc
+++ b/services/ui/common/gpu_service.cc
@@ -22,8 +22,10 @@
 
 void PostTask(scoped_refptr<base::SingleThreadTaskRunner> runner,
               const tracked_objects::Location& from_here,
-              const base::Closure& callback) {
-  runner->PostTask(from_here, callback);
+              const gpu::GpuChannelEstablishedCallback& callback,
+              scoped_refptr<gpu::GpuChannelHost> established_channel_host) {
+  runner->PostTask(from_here,
+                   base::Bind(callback, std::move(established_channel_host)));
 }
 
 GpuService* g_gpu_service = nullptr;
@@ -67,11 +69,13 @@
   return g_gpu_service;
 }
 
-void GpuService::EstablishGpuChannel(const base::Closure& callback) {
+void GpuService::EstablishGpuChannel(
+    const gpu::GpuChannelEstablishedCallback& callback) {
   base::AutoLock auto_lock(lock_);
   auto runner = base::ThreadTaskRunnerHandle::Get();
-  if (GetGpuChannelLocked()) {
-    runner->PostTask(FROM_HERE, callback);
+  scoped_refptr<gpu::GpuChannelHost> channel = GetGpuChannelLocked();
+  if (channel) {
+    PostTask(runner, FROM_HERE, callback, std::move(channel));
     return;
   }
   establish_callbacks_.push_back(
@@ -109,11 +113,6 @@
   return gpu_channel_;
 }
 
-scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannel() {
-  base::AutoLock auto_lock(lock_);
-  return GetGpuChannelLocked();
-}
-
 scoped_refptr<gpu::GpuChannelHost> GpuService::GetGpuChannelLocked() {
   if (gpu_channel_ && gpu_channel_->IsLost()) {
     main_task_runner_->PostTask(
@@ -203,7 +202,7 @@
   gpu_service_.reset();
 
   for (const auto& i : establish_callbacks_)
-    i.Run();
+    i.Run(gpu_channel_);
   establish_callbacks_.clear();
 }
 
diff --git a/services/ui/common/gpu_service.h b/services/ui/common/gpu_service.h
index d00a60c..d15ba7116 100644
--- a/services/ui/common/gpu_service.h
+++ b/services/ui/common/gpu_service.h
@@ -25,13 +25,11 @@
 
 namespace ui {
 
-class MUS_COMMON_EXPORT GpuService : public gpu::GpuChannelHostFactory {
+class MUS_COMMON_EXPORT GpuService : public gpu::GpuChannelHostFactory,
+                                     public gpu::GpuChannelEstablishFactory {
  public:
   ~GpuService() override;
 
-  void EstablishGpuChannel(const base::Closure& callback);
-  scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync();
-  scoped_refptr<gpu::GpuChannelHost> GetGpuChannel();
   gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() const {
     return gpu_memory_buffer_manager_.get();
   }
@@ -41,6 +39,11 @@
   static std::unique_ptr<GpuService> Initialize(shell::Connector* connector);
   static GpuService* GetInstance();
 
+  // gpu::GpuChannelEstablishFactory:
+  void EstablishGpuChannel(
+      const gpu::GpuChannelEstablishedCallback& callback) override;
+  scoped_refptr<gpu::GpuChannelHost> EstablishGpuChannelSync() override;
+
  private:
   friend struct base::DefaultSingletonTraits<GpuService>;
 
@@ -72,7 +75,7 @@
   bool is_establishing_;
   ui::mojom::GpuServicePtr gpu_service_;
   scoped_refptr<gpu::GpuChannelHost> gpu_channel_;
-  std::vector<base::Closure> establish_callbacks_;
+  std::vector<gpu::GpuChannelEstablishedCallback> establish_callbacks_;
   base::ConditionVariable establishing_condition_;
 
   DISALLOW_COPY_AND_ASSIGN(GpuService);
diff --git a/services/ui/demo/mus_demo.cc b/services/ui/demo/mus_demo.cc
index 3710de8d..ac7ed7c8f 100644
--- a/services/ui/demo/mus_demo.cc
+++ b/services/ui/demo/mus_demo.cc
@@ -70,7 +70,8 @@
   window_tree_client_->ConnectAsWindowManager(connector());
 }
 
-bool MusDemo::OnConnect(shell::Connection* connection) {
+bool MusDemo::OnConnect(const shell::Identity& remote_identity,
+                        shell::InterfaceRegistry* registry) {
   return true;
 }
 
diff --git a/services/ui/demo/mus_demo.h b/services/ui/demo/mus_demo.h
index 78dbde7..4f4dd27 100644
--- a/services/ui/demo/mus_demo.h
+++ b/services/ui/demo/mus_demo.h
@@ -38,7 +38,8 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // WindowTreeClientDelegate:
   void OnEmbed(Window* root) override;
diff --git a/services/ui/input_devices/input_device_server.cc b/services/ui/input_devices/input_device_server.cc
index c6bf1e94..acd30397 100644
--- a/services/ui/input_devices/input_device_server.cc
+++ b/services/ui/input_devices/input_device_server.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "mojo/public/cpp/bindings/array.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "ui/events/devices/input_device.h"
 #include "ui/events/devices/touchscreen_device.h"
 
@@ -33,9 +34,9 @@
   return manager_ != nullptr;
 }
 
-void InputDeviceServer::AddInterface(shell::Connection* connection) {
+void InputDeviceServer::AddInterface(shell::InterfaceRegistry* registry) {
   DCHECK(IsRegisteredAsObserver());
-  connection->AddInterface<mojom::InputDeviceServer>(this);
+  registry->AddInterface<mojom::InputDeviceServer>(this);
 }
 
 void InputDeviceServer::AddObserver(
diff --git a/services/ui/input_devices/input_device_server.h b/services/ui/input_devices/input_device_server.h
index 2819055..34abe28 100644
--- a/services/ui/input_devices/input_device_server.h
+++ b/services/ui/input_devices/input_device_server.h
@@ -14,6 +14,10 @@
 #include "ui/events/devices/device_data_manager.h"
 #include "ui/events/devices/input_device_event_observer.h"
 
+namespace shell {
+class InterfaceRegistry;
+}
+
 namespace ui {
 
 // Listens to DeviceDataManager for updates on input-devices and forwards those
@@ -31,11 +35,11 @@
   void RegisterAsObserver();
   bool IsRegisteredAsObserver() const;
 
-  // Adds interface with the shell connection so remote observers can connect.
-  // You should have already called RegisterAsObserver() to get local
+  // Adds interface with the connection registry so remote observers can
+  // connect. You should have already called RegisterAsObserver() to get local
   // input-device event updates and checked it was successful by calling
   // IsRegisteredAsObserver().
-  void AddInterface(shell::Connection* connection);
+  void AddInterface(shell::InterfaceRegistry* registry);
 
   // mojom::InputDeviceServer:
   void AddObserver(mojom::InputDeviceObserverMojoPtr observer) override;
diff --git a/services/ui/public/cpp/tests/window_server_shelltest_base.cc b/services/ui/public/cpp/tests/window_server_shelltest_base.cc
index c34ce7f..9ef29be 100644
--- a/services/ui/public/cpp/tests/window_server_shelltest_base.cc
+++ b/services/ui/public/cpp/tests/window_server_shelltest_base.cc
@@ -28,8 +28,9 @@
 
  private:
   // shell::test::ServiceTestClient:
-  bool OnConnect(shell::Connection* connection) override {
-    return test_->OnConnect(connection);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    return test_->OnConnect(remote_identity, registry);
   }
 
   WindowServerServiceTestBase* test_;
diff --git a/services/ui/public/cpp/tests/window_server_shelltest_base.h b/services/ui/public/cpp/tests/window_server_shelltest_base.h
index ad02871..12bed02 100644
--- a/services/ui/public/cpp/tests/window_server_shelltest_base.h
+++ b/services/ui/public/cpp/tests/window_server_shelltest_base.h
@@ -17,7 +17,8 @@
   WindowServerServiceTestBase();
   ~WindowServerServiceTestBase() override;
 
-  virtual bool OnConnect(shell::Connection* connection) = 0;
+  virtual bool OnConnect(const shell::Identity& remote_identity,
+                         shell::InterfaceRegistry* registry) = 0;
 
  private:
   // shell::test::ServiceTest:
diff --git a/services/ui/public/cpp/tests/window_server_test_base.cc b/services/ui/public/cpp/tests/window_server_test_base.cc
index c3b2f67..025a56d 100644
--- a/services/ui/public/cpp/tests/window_server_test_base.cc
+++ b/services/ui/public/cpp/tests/window_server_test_base.cc
@@ -73,8 +73,9 @@
   std::swap(window_manager_, most_recent_client_);
 }
 
-bool WindowServerTestBase::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<mojom::WindowTreeClient>(this);
+bool WindowServerTestBase::OnConnect(const shell::Identity& remote_identity,
+                                     shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::WindowTreeClient>(this);
   return true;
 }
 
diff --git a/services/ui/public/cpp/tests/window_server_test_base.h b/services/ui/public/cpp/tests/window_server_test_base.h
index 0fb403b1..5e66744 100644
--- a/services/ui/public/cpp/tests/window_server_test_base.h
+++ b/services/ui/public/cpp/tests/window_server_test_base.h
@@ -63,7 +63,8 @@
   void SetUp() override;
 
   // WindowServerServiceTestBase:
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // WindowTreeClientDelegate:
   void OnEmbed(Window* root) override;
diff --git a/services/ui/service.cc b/services/ui/service.cc
index d98909f..01a74eb 100644
--- a/services/ui/service.cc
+++ b/services/ui/service.cc
@@ -194,26 +194,27 @@
         new ws::TouchController(window_server_->display_manager()));
 }
 
-bool Service::OnConnect(Connection* connection) {
-  connection->AddInterface<mojom::AccessibilityManager>(this);
-  connection->AddInterface<mojom::Clipboard>(this);
-  connection->AddInterface<mojom::DisplayManager>(this);
-  connection->AddInterface<mojom::GpuService>(this);
-  connection->AddInterface<mojom::UserAccessManager>(this);
-  connection->AddInterface<mojom::UserActivityMonitor>(this);
-  connection->AddInterface<WindowTreeHostFactory>(this);
-  connection->AddInterface<mojom::WindowManagerWindowTreeFactory>(this);
-  connection->AddInterface<mojom::WindowTreeFactory>(this);
+bool Service::OnConnect(const shell::Identity& remote_identity,
+                        shell::InterfaceRegistry* registry) {
+  registry->AddInterface<mojom::AccessibilityManager>(this);
+  registry->AddInterface<mojom::Clipboard>(this);
+  registry->AddInterface<mojom::DisplayManager>(this);
+  registry->AddInterface<mojom::GpuService>(this);
+  registry->AddInterface<mojom::UserAccessManager>(this);
+  registry->AddInterface<mojom::UserActivityMonitor>(this);
+  registry->AddInterface<WindowTreeHostFactory>(this);
+  registry->AddInterface<mojom::WindowManagerWindowTreeFactory>(this);
+  registry->AddInterface<mojom::WindowTreeFactory>(this);
   if (test_config_)
-    connection->AddInterface<WindowServerTest>(this);
+    registry->AddInterface<WindowServerTest>(this);
 
   // On non-Linux platforms there will be no DeviceDataManager instance and no
   // purpose in adding the Mojo interface to connect to.
   if (input_device_server_.IsRegisteredAsObserver())
-    input_device_server_.AddInterface(connection);
+    input_device_server_.AddInterface(registry);
 
 #if defined(USE_OZONE)
-  ui::OzonePlatform::GetInstance()->AddInterfaces(connection);
+  ui::OzonePlatform::GetInstance()->AddInterfaces(registry);
 #endif
 
   return true;
diff --git a/services/ui/service.h b/services/ui/service.h
index ca7589f7..0f6dbc3 100644
--- a/services/ui/service.h
+++ b/services/ui/service.h
@@ -97,7 +97,8 @@
 
   // shell::Service:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // WindowServerDelegate:
   void OnFirstDisplayReady() override;
diff --git a/services/ui/test_ime/main.cc b/services/ui/test_ime/main.cc
index f52f6206..db1f1a4 100644
--- a/services/ui/test_ime/main.cc
+++ b/services/ui/test_ime/main.cc
@@ -20,8 +20,9 @@
  private:
   // shell::Service:
   void OnStart(const shell::Identity& identity) override {}
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface<mojom::IMEDriver>(this);
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<mojom::IMEDriver>(this);
     return true;
   }
 
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc
index 6f6382f75..31ba777d 100644
--- a/services/ui/ws/window_tree_client_unittest.cc
+++ b/services/ui/ws/window_tree_client_unittest.cc
@@ -585,8 +585,9 @@
   }
 
   // WindowServerServiceTestBase:
-  bool OnConnect(shell::Connection* connection) override {
-    connection->AddInterface(client_factory_.get());
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override {
+    registry->AddInterface(client_factory_.get());
     return true;
   }
 
diff --git a/services/user/user_shell_client.cc b/services/user/user_shell_client.cc
index d91a39fa..aa70576 100644
--- a/services/user/user_shell_client.cc
+++ b/services/user/user_shell_client.cc
@@ -95,9 +95,10 @@
       new UserShellClient::LevelDBServiceObjects(leveldb_service_runner_));
 }
 
-bool UserShellClient::OnConnect(shell::Connection* connection) {
-  connection->AddInterface<leveldb::mojom::LevelDBService>(this);
-  connection->AddInterface<mojom::UserService>(this);
+bool UserShellClient::OnConnect(const shell::Identity& remote_identity,
+                                shell::InterfaceRegistry* registry) {
+  registry->AddInterface<leveldb::mojom::LevelDBService>(this);
+  registry->AddInterface<mojom::UserService>(this);
   return true;
 }
 
diff --git a/services/user/user_shell_client.h b/services/user/user_shell_client.h
index 3684a59..e0e1c651 100644
--- a/services/user/user_shell_client.h
+++ b/services/user/user_shell_client.h
@@ -34,7 +34,8 @@
  private:
   // |Service| override:
   void OnStart(const shell::Identity& identity) override;
-  bool OnConnect(shell::Connection* connection) override;
+  bool OnConnect(const shell::Identity& remote_identity,
+                 shell::InterfaceRegistry* registry) override;
 
   // |InterfaceFactory<mojom::UserService>| implementation:
   void Create(const shell::Identity& remote_identity,
@@ -44,8 +45,6 @@
   void Create(const shell::Identity& remote_identity,
               leveldb::mojom::LevelDBServiceRequest request) override;
 
-  void OnLevelDBServiceRequest(shell::Connection* connection,
-                               leveldb::mojom::LevelDBServiceRequest request);
   void OnLevelDBServiceError();
 
   scoped_refptr<base::SingleThreadTaskRunner> user_service_runner_;
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index bd08ccede..9f6ad2c 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -841,9 +841,7 @@
 crbug.com/487880 virtual/threaded/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Pass Timeout ]
 crbug.com/487880 virtual/threaded/fast/scroll-behavior/overflow-scroll-animates.html [ Pass Timeout ]
 crbug.com/552556 virtual/threaded/fast/scroll-behavior/smooth-scroll/mousewheel-scroll.html [ Pass Failure ]
-
 crbug.com/425113 svg/clip-path/clip-path-multiple-children.svg [ Failure ]
-
 crbug.com/480769 http/tests/inspector/service-workers/service-workers-redundant.html [ Crash Pass Failure ]
 crbug.com/480769 http/tests/inspector/service-workers/service-worker-agents.html [ Crash Pass Timeout ]
 
@@ -1222,9 +1220,6 @@
 crbug.com/594672 fast/events/scale-and-scroll-iframe-body.html [ Failure Pass ]
 crbug.com/594672 fast/events/updateLayoutForHitTest.html [ Failure Pass ]
 crbug.com/594672 fast/events/scale-and-scroll-iframe-window.html [ Failure Pass ]
-crbug.com/67848 fast/forms/search/search-rtl.html [ NeedsRebaseline ]
-crbug.com/67848 fast/forms/placeholder-position.html [ NeedsRebaseline ]
-crbug.com/67848 fast/css/text-overflow-input.html [ NeedsRebaseline ]
 crbug.com/603728 [ Linux ] virtual/gpu-rasterization/fast/images/color-profile-filter.html [ Failure Timeout Pass ]
 
 crbug.com/593568 [ Win Debug ] virtual/threaded/fast/scroll-behavior/smooth-scroll/horizontal-smooth-scroll-in-rtl.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-identical-aside-from-inherited.html b/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-identical-aside-from-inherited.html
new file mode 100644
index 0000000..337e0e2a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/atapply/at-apply-identical-aside-from-inherited.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<style>
+#parent1 {
+  --mixin: {
+    border: 5px solid black;
+  };
+}
+#parent2 {
+  --mixin: {
+    border: 10px dotted orange;
+  };
+}
+
+#child1, #child2, #child3 {
+  @apply --mixin;
+}
+</style>
+<div id="parent1">
+  <div id="child1">X</div>
+</div>
+<div id="parent2">
+  <div id="child2">X</div>
+</div>
+<div id="parent3">
+  <div id="child3">X</div>
+</div>
+<script>
+test(function() {
+  assert_equals(getComputedStyle(child1).borderWidth, '5px');
+  assert_equals(getComputedStyle(child2).borderWidth, '10px');
+  assert_equals(getComputedStyle(child3).borderWidth, '0px');
+}, "Elements style identically aside from an @apply'd variable with different inherited values are computed properly");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw-expected.txt
index c5986e1..4314ed43 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw-expected.txt
@@ -1,7 +1,6 @@
-CONSOLE WARNING: line 42: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
 This is a testharness.js-based test.
-PASS Check that exception is created in called function's context. 
-PASS Check that DOM exception is created in setter's context. 
+FAIL Check that DOM exception is created in called function's context. assert_not_equals: got disallowed value [stringifying object threw TypeError: Illegal invocation with type object]
+FAIL Check that DOM exception is created in setter's context. assert_not_equals: got disallowed value [stringifying object threw TypeError: Illegal invocation with type object]
 PASS Check that native exception is created in setter's context. 
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw.html b/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw.html
index 7245ca571..a762690 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/cross-frame-accessor-throw.html
@@ -16,6 +16,11 @@
     assert_not_equals(DOMException.prototype, Object.getPrototypeOf(exception));
 }
 
+function assert_dom_exception_in_incumbent(exception) {
+    assert_not_equals(frameWindow.DOMException.prototype, Object.getPrototypeOf(exception));
+    assert_equals(DOMException.prototype, Object.getPrototypeOf(exception));
+}
+
 test(function () {
     // Sanity check over functions.
     try {
@@ -26,18 +31,36 @@
         assert_true(e.name == "HierarchyRequestError");
         assert_dom_exception_in_frame(e);
     }
-}, "Check that exception is created in called function's context.");
+    try {
+        var element = frameWindow.document.createElement('textarea');
+        Node.prototype.appendChild.call(element, element);
+        assert_unreached("Cyclic appendChild() should throw HierarchyRequestError.");
+    } catch (e) {
+        assert_true(e.name == "HierarchyRequestError");
+        assert_dom_exception_in_incumbent(e);
+    }
+}, "Check that DOM exception is created in called function's context.");
 
 test(function () {
     try {
-        var i = frameWindow.document.createElement('input');
-        i.size = 0;
+        var input = frameWindow.document.createElement('input');
+        input.size = 0;
         assert_unreached("Setting input.size to zero should throw IndexSizeError.");
     } catch (e) {
         assert_true(e.name == "IndexSizeError");
         assert_dom_exception_in_frame(e);
     }
     try {
+        var input = frameWindow.document.createElement('input');
+        var pd = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'size');
+        pd.set.call(input, 0);
+        assert_unreached("Setting input.size to zero should throw IndexSizeError.");
+    } catch (e) {
+        assert_true(e.name == "IndexSizeError");
+        assert_dom_exception_in_incumbent(e);
+    }
+
+    try {
         var xhr = new frameWindow.XMLHttpRequest();
         xhr.open('GET', 'nonExistent.html', false);
         xhr.timeout = 10;
@@ -46,18 +69,37 @@
         assert_true(e.name == "InvalidAccessError");
         assert_dom_exception_in_frame(e);
     }
+    try {
+        var xhr = new frameWindow.XMLHttpRequest();
+        xhr.open('GET', 'nonExistent.html', false);
+        var pd = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'timeout');
+        pd.set.call(xhr, 10);
+        assert_unreached("Setting xhr.timeout on sync XHR object should throw InvalidAccessError.");
+    } catch (e) {
+        assert_true(e.name == "InvalidAccessError");
+        assert_dom_exception_in_incumbent(e);
+    }
 }, "Check that DOM exception is created in setter's context.");
 
 test(function () {
     try {
         var serializer = new frameWindow.XMLSerializer();
-	serializer.serializeToString(null);
+        serializer.serializeToString(null);
         assert_unreached("serializing null should throw a TypeError");
     } catch (e) {
         assert_true(e.name == "TypeError");
         assert_equals(frameWindow.TypeError.prototype, Object.getPrototypeOf(e));
         assert_not_equals(TypeError.prototype, Object.getPrototypeOf(e));
     }
+    try {
+        var serializer = new frameWindow.XMLSerializer();
+        XMLSerializer.prototype.serializeToString.call(serializer, null);
+        assert_unreached("serializing null should throw a TypeError");
+    } catch (e) {
+        assert_true(e.name == "TypeError");
+        assert_not_equals(frameWindow.TypeError.prototype, Object.getPrototypeOf(e));
+        assert_equals(TypeError.prototype, Object.getPrototypeOf(e));
+    }
 }, "Check that native exception is created in setter's context.");
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/color/input-appearance-color.html b/third_party/WebKit/LayoutTests/fast/forms/color/input-appearance-color.html
index 9c61c01..0bb617129 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/color/input-appearance-color.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/color/input-appearance-color.html
@@ -33,3 +33,5 @@
 <input type="color" value="#FF0000" style="background-color:yellow" list>
 <input type="color" value="#FF0000" style="border:1px solid lime; border-radius:0">
 <input type="color" value="#FF0000" style="border:1px solid lime; border-radius:0" list>
+<input type="color" value="#40e0d0" dir=rtl>
+<input type="color" value="#FF0000" list dir=rtl>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-rtl.html b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-rtl.html
new file mode 100644
index 0000000..8e11852
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-rtl.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<style>
+.bidi1 {
+    direction: rtl; 
+    -webkit-rtl-ordering: logical;
+    width: 100px;
+}
+.bidi2 {
+    width: 200px;
+    text-align: right;
+}
+.bidi3 {
+    width: 100px;
+}
+</style>
+<p>
+This tests that bidirectional text is correctly rendered in popup controls.
+The order of the text below each popup button should match the order of the
+select's option text, and the order of the text in the popup menu.</p>
+<dl>
+<dt>1) direction: rtl; -webkit-rtl-ordering: logical
+<dd><select class="bidi1"><option>abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</option></select>
+<div class="bidi1">abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</div>
+<dt>2) text-align: right
+<dd><select class="bidi2"><option>abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</option></select>
+<div class="bidi2" style="text-align: left">abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</div>
+<dt>3) No style
+<dd><select class="bidi3"><option>abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</option></select>
+<div class="bidi3">abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</div>
+</dl>
+
+<hr>
+<div dir=ltr>The following line and the SELECT element should have same text, and no characters are lacking.
+<div style="font:menu">الاقتراحات / الشكاوي</div>
+<select>
+<option selected value="الاقتراحات / الشكاوي">الاقتراحات / الشكاوي</option>
+</select>
+</div>
+
+<hr>
+<style>
+.menu {
+  display: block;
+  font-size: 16px;
+  width: 350px
+}
+.reflection {
+  font: 13px "Lucida Grande";
+  padding: 1px;
+  width: 350px;
+}
+</style>
+<p>Verify that the alignment and writing direction of each selected item matches
+the one below the pop-up button.</p>
+
+<div style="column-count:2">
+<div id="left-aligned">
+<select class="menu">
+<option style="direction: ltr;">
+First שניה (03) רביעית fifth
+</option>
+<option style="direction: rtl;">
+First שניה (03) רביעית fifth
+</option>
+<option style="direction: ltr; unicode-bidi: bidi-override;">
+First שניה (03) רביעית fifth
+</option>
+<option style="direction: rtl; unicode-bidi: bidi-override;">
+First שניה (03) רביעית fifth
+</option>
+</select>
+<div class="reflection" style="direction:ltr;">
+First שניה (03) רביעית fifth
+</div>
+</div>
+</div>
+<script>
+// Clone 3 left-aligned <select>.
+var select = document.getElementsByClassName("menu")[0];
+var div = document.getElementsByClassName("reflection")[0];
+for (var i = 1; i < 4; ++i) {
+    var clonedSelect = select.cloneNode(true);
+    var clonedDiv = div.cloneNode(true);
+    var optionStyle = getComputedStyle(select.options[i]);
+    clonedDiv.style.direction = optionStyle.direction;
+    clonedDiv.style.unicodeBidi = optionStyle.unicodeBidi;
+    clonedDiv.style.textAlign = "left";
+    document.getElementById("left-aligned").appendChild(clonedSelect);
+    document.getElementById("left-aligned").appendChild(clonedDiv);
+}
+
+// Clone 4 right-aligned <select>.
+var leftAligned = document.getElementById("left-aligned");
+var cloned = leftAligned.cloneNode(true);
+for (var child = cloned.firstChild; child; child = child.nextSibling) {
+    if (child.tagName == "SELECT") 
+        child.style.direction = "rtl";
+    if (child.tagName == "DIV") 
+        child.style.textAlign = "right";
+}
+cloned.setAttribute("id", "right-aligned");
+leftAligned.parentNode.appendChild(cloned);
+
+var selectElements = document.getElementsByClassName("menu");
+for (var i = 0; i < selectElements.length; ++i) {
+    selectElements[i].selectedIndex = i % 4;
+}
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/text/international/bidi-menulist.html b/third_party/WebKit/LayoutTests/fast/text/international/bidi-menulist.html
deleted file mode 100644
index 96c32ec..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/international/bidi-menulist.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<style>
-.bidi1 {
-    direction: rtl; 
-    -webkit-rtl-ordering: logical;
-    width: 100px;
-}
-.bidi2 {
-    width: 200px;
-    text-align: right;
-}
-.bidi3 {
-    width: 100px;
-}
-</style>
-<p>
-This tests that bidirectional text is correctly rendered in popup controls.<br>
-The order of the text below each popup button should match the order of the select's option text, and the order of the text in the popup menu.
-</p>
-    1) direction: rtl; -webkit-rtl-ordering: logical<br>
-<select class="bidi1"><option>abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</option></select><br>
-<div class="bidi1" style="direction: ltr">abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</div><br>
-    2) text-align: right<br>
-<select class="bidi2"><option>abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</option></select><br>
-<div class="bidi2" style="text-align: left">abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</div><br>
-    3) No style<br>
-<select class="bidi3"><option>abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</option></select><br>
-<div class="bidi3">abc&#x05d0;&#x05e4;&#x05e8;&#x05e1;&#x05de;&#x05d5;&#x05df;</div><br>
diff --git a/third_party/WebKit/LayoutTests/fast/text/international/menulist-width-rtl.html b/third_party/WebKit/LayoutTests/fast/text/international/menulist-width-rtl.html
deleted file mode 100644
index dd06f8b3..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/international/menulist-width-rtl.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-</head>
-<body dir=rtl>
-<div dir=ltr>The following line and the SELECT element should have same text, and no characters are lacking.</div>
-<div style="font:menu">الاقتراحات / الشكاوي</div>
-<select>
-<option selected value="الاقتراحات / الشكاوي">الاقتراحات / الشكاوي</option>
-</select>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/text/international/pop-up-button-text-alignment-and-direction.html b/third_party/WebKit/LayoutTests/fast/text/international/pop-up-button-text-alignment-and-direction.html
deleted file mode 100644
index 7053ffe..0000000
--- a/third_party/WebKit/LayoutTests/fast/text/international/pop-up-button-text-alignment-and-direction.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<style>
-   select { display: block; font-size: 16px; }
-   .reflection { font: 13px "Lucida Grande"; padding: 10px; width: 245px; }
-</style>
-</head>
-<body>
-<p>
-    Verify that the alignment and writing direction of each selected item matches
-    the one below the pop-up button.
-</p>
-
-<div id="left-aligned">
-    <select class="menu" style="width:500px">
-        <option style="direction: ltr;">
-            First שניה (03) רביעית fifth
-        </option>
-        <option style="direction: rtl;">
-            First שניה (03) רביעית fifth
-        </option>
-        <option style="direction: ltr; unicode-bidi: bidi-override;">
-            First שניה (03) רביעית fifth
-        </option>
-        <option style="direction: rtl; unicode-bidi: bidi-override;">
-            First שניה (03) רביעית fifth
-        </option>
-    </select>
-    <div class="reflection" style="direction:ltr; width:450px">
-            First שניה (03) רביעית fifth
-    </div>
-</div>
-
-<script>
-    // Clone 3 left-aligned <select>.
-    var select = document.getElementsByClassName("menu")[0];
-    var div = document.getElementsByClassName("reflection")[0];
-    for (var i = 1; i < 4; ++i) {
-        var clonedSelect = select.cloneNode(true);
-        var clonedDiv = div.cloneNode(true);
-        var optionStyle = getComputedStyle(select.options[i]);
-        clonedDiv.style.direction = optionStyle.direction;
-        clonedDiv.style.unicodeBidi = optionStyle.unicodeBidi;
-        clonedDiv.style.textAlign = "left";
-        document.getElementById("left-aligned").appendChild(clonedSelect);
-        document.getElementById("left-aligned").appendChild(clonedDiv);
-    }
-
-    // Clone 4 right-aligned <select>.
-    var cloned = document.getElementById("left-aligned").cloneNode(true);
-    for (var child = cloned.firstChild; child; child = child.nextSibling) {
-        if (child.tagName == "SELECT") 
-            child.style.direction = "rtl";
-        if (child.tagName == "DIV") 
-            child.style.textAlign = "right";
-    }
-    cloned.setAttribute("id", "right-aligned");
-    document.body.appendChild(cloned);
-
-    var selectElements = document.getElementsByClassName("menu");
-    for (var i = 0; i < selectElements.length; ++i) {
-        document.body.offsetTop; // Force layout
-        selectElements[i].selectedIndex = i % 4;
-    }
-</script>
-</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
index e88ae63..3c308257 100644
--- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js
@@ -4,12 +4,12 @@
 
 InspectorTest.inlineStyleSection = function()
 {
-    return WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks[0].sections[0];
+    return WebInspector.panels.elements._stylesWidget._sectionBlocks[0].sections[0];
 }
 
 InspectorTest.computedStyleWidget = function()
 {
-    return WebInspector.panels.elements.sidebarPanes.computedStyle;
+    return WebInspector.panels.elements._computedStyleWidget;
 }
 
 InspectorTest.dumpComputedStyle = function(doNotAutoExpand)
@@ -59,7 +59,7 @@
 
 InspectorTest.firstMatchedStyleSection = function()
 {
-    return WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks[0].sections[1];
+    return WebInspector.panels.elements._stylesWidget._sectionBlocks[0].sections[1];
 }
 
 InspectorTest.firstMediaTextElementInSection = function(section)
@@ -299,12 +299,12 @@
 {
     var regex = text ? new RegExp(text, "i") : null;
     InspectorTest.addResult("Filtering styles by: " + text);
-    WebInspector.panels.elements.sidebarPanes.styles.onFilterChanged(regex);
+    WebInspector.panels.elements._stylesWidget.onFilterChanged(regex);
 }
 
 InspectorTest.dumpRenderedMatchedStyles = function()
 {
-    var sectionBlocks = WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks;
+    var sectionBlocks = WebInspector.panels.elements._stylesWidget._sectionBlocks;
     for (var block of sectionBlocks) {
         for (var section of block.sections) {
             // Skip sections which were filtered out.
@@ -352,7 +352,7 @@
 
 InspectorTest.dumpSelectedElementStyles = function(excludeComputed, excludeMatched, omitLonghands, includeSelectorGroupMarks)
 {
-    var sectionBlocks = WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks;
+    var sectionBlocks = WebInspector.panels.elements._stylesWidget._sectionBlocks;
     if (!excludeComputed)
         InspectorTest.dumpComputedStyle();
     for (var block of sectionBlocks) {
@@ -436,9 +436,13 @@
 
 InspectorTest.eventListenersWidget = function()
 {
-    var sidebarPane = WebInspector.panels.elements.sidebarPanes.eventListeners;
-    sidebarPane.revealView();
-    return sidebarPane;
+    WebInspector.viewManager.showView("elements.eventListeners");
+    return self.runtime.sharedInstance(WebInspector.EventListenersWidget);
+}
+
+InspectorTest.showEventListenersWidget = function()
+{
+    return WebInspector.viewManager.showView("elements.eventListeners");
 }
 
 InspectorTest.expandAndDumpSelectedElementEventListeners = function(callback)
@@ -478,7 +482,7 @@
 // FIXME: this returns the first tree item found (may fail for same-named properties in a style).
 InspectorTest.getMatchedStylePropertyTreeItem = function(propertyName)
 {
-    var sectionBlocks = WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks;
+    var sectionBlocks = WebInspector.panels.elements._stylesWidget._sectionBlocks;
     for (var block of sectionBlocks) {
         for (var section of block.sections) {
             var treeItem = InspectorTest.getFirstPropertyTreeItemForSection(section, propertyName);
@@ -930,7 +934,7 @@
 InspectorTest.addNewRuleInStyleSheet = function(styleSheetHeader, selector, callback)
 {
     InspectorTest.addSniffer(WebInspector.StylesSidebarPane.prototype, "_addBlankSection", onBlankSection.bind(null, selector, callback));
-    WebInspector.panels.elements.sidebarPanes.styles._createNewRuleInStyleSheet(styleSheetHeader);
+    WebInspector.panels.elements._stylesWidget._createNewRuleInStyleSheet(styleSheetHeader);
 }
 
 InspectorTest.addNewRule = function(selector, callback)
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-filters-internals-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-filters-internals-expected.txt
new file mode 100644
index 0000000..2adf3899
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-filters-internals-expected.txt
@@ -0,0 +1,12 @@
+Tests to ensure data being passed from outside network to filter results filters properly.
+
+
+filterType: domain
+filterValue: 127.0.0.1
+
+filterType: scheme
+filterValue: http
+
+Found results: 4
+
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-filters-internals.html b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-filters-internals.html
new file mode 100644
index 0000000..93f3e0a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-filters-internals.html
@@ -0,0 +1,60 @@
+<html>
+<head>
+<script src="../inspector-test.js"></script>
+<script src="../network-test.js"></script>
+<script>
+function test()
+{
+    InspectorTest.recordNetwork();
+
+    var totalResourceCount = 3;
+    InspectorTest.makeFetch("resources/style.css", {}, ensureAllResources);
+    InspectorTest.makeFetch("resources/abe.png", {}, ensureAllResources);
+    InspectorTest.makeFetch("resources/abe.png", {}, ensureAllResources);
+    InspectorTest.makeFetch("resources/cyrillic.html", {}, ensureAllResources);
+    var filterArray = [
+        {
+            filterType: WebInspector.NetworkLogView.FilterType.Domain,
+            filterValue: "127.0.0.1"
+        } ,{
+            filterType: WebInspector.NetworkLogView.FilterType.Scheme,
+            filterValue: "http"
+        }
+    ];
+
+    var resourceCount = 0;
+    function ensureAllResources()
+    {
+        if (++resourceCount >= totalResourceCount)
+            checkFilters();
+    }
+
+    function checkFilters()
+    {
+        for (var filter of filterArray) {
+            InspectorTest.addResult("");
+            InspectorTest.addResult("filterType: " + filter.filterType);
+            InspectorTest.addResult("filterValue: " + filter.filterValue);
+        }
+        InspectorTest.addResult("");
+
+        WebInspector.NetworkPanel.revealAndFilter(filterArray);
+
+        var nodes = WebInspector.panels.network._networkLogView._nodesByRequestId.valuesArray();
+        var foundNodesCount = 0;
+        for (var i = 0; i < nodes.length; i++) {
+            if (!nodes[i][WebInspector.NetworkLogView._isFilteredOutSymbol])
+                foundNodesCount++;
+        }
+
+        InspectorTest.addResult("Found results: " + foundNodesCount);
+        InspectorTest.addResult("");
+        InspectorTest.completeTest();
+    }
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Tests to ensure data being passed from outside network to filter results filters properly.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/accessibility/accessibility-pane-test.js b/third_party/WebKit/LayoutTests/inspector/elements/accessibility/accessibility-pane-test.js
index 06e2e06..2fb48260 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/accessibility/accessibility-pane-test.js
+++ b/third_party/WebKit/LayoutTests/inspector/elements/accessibility/accessibility-pane-test.js
@@ -1,42 +1,8 @@
 var initialize_AccessibilityTest = function() {
 
-/**
- * @return {Promise}
- */
-InspectorTest.showAccessibilityView = function()
+InspectorTest.accessibilitySidebarPane = function()
 {
-    var sidebarPane = _getAccessibilitySidebarPane();
-    if (sidebarPane) {
-        sidebarPane.revealView();
-        return InspectorTest.waitForAccessibilityNodeUpdate();
-    } else {
-        return _waitForViewsLoaded()
-            .then(() => {
-                return InspectorTest.showAccessibilityView();
-            });
-    }
-}
-
-
-/**
- * @return {Promise}
- */
-function _waitForViewsLoaded()
-{
-    return new Promise(function(resolve, reject)
-    {
-        InspectorTest.addSniffer(WebInspector.ElementsPanel.prototype,
-                                 "_sidebarViewsLoadedForTest",
-                                 resolve);
-        WebInspector.panels.elements._loadSidebarViews();
-    });
-}
-
-function _getAccessibilitySidebarPane()
-{
-    var sidebarViews = WebInspector.panels.elements._elementsSidebarViews;
-    var sidebarPane = sidebarViews.find((view) => { return view._title === "Accessibility"; });
-    return sidebarPane;
+    return self.runtime.sharedInstance(WebInspector.AccessibilitySidebarView);
 }
 
 /**
@@ -45,16 +11,16 @@
  */
 InspectorTest.selectNodeAndWaitForAccessibility = function(idValue)
 {
-    return Promise.all([InspectorTest.waitForAccessibilityNodeUpdateInARIAPane(),
-                        InspectorTest.waitForAccessibilityNodeUpdate(),
-                        new Promise(function(resolve) {
-                            InspectorTest.selectNodeWithId(idValue, resolve);
-                        })]);
+    return new Promise((resolve) => {
+        InspectorTest.selectNodeWithId(idValue, function() {
+            self.runtime.sharedInstance(WebInspector.AccessibilitySidebarView).doUpdate().then(resolve);
+        });
+    });
 }
 
 InspectorTest.dumpSelectedElementAccessibilityNode = function()
 {
-    var sidebarPane = _getAccessibilitySidebarPane();
+    var sidebarPane = InspectorTest.accessibilitySidebarPane();
 
     if (!sidebarPane) {
         InspectorTest.addResult("No sidebarPane in dumpSelectedElementAccessibilityNode");
@@ -94,7 +60,7 @@
  */
 InspectorTest.findARIAAttributeTreeElement = function(attribute)
 {
-    var sidebarPane = _getAccessibilitySidebarPane();
+    var sidebarPane = InspectorTest.accessibilitySidebarPane();
 
     if (!sidebarPane) {
         InspectorTest.addResult("Could not get Accessibility sidebar pane.");
@@ -112,25 +78,4 @@
     return null;
 }
 
-/**
- * @return {Promise}
- */
-InspectorTest.waitForAccessibilityNodeUpdate = function()
-{
-    return new Promise(function(resolve, reject)
-    {
-        InspectorTest.addSniffer(WebInspector.AccessibilitySidebarView.prototype, "_accessibilityNodeUpdatedForTest", resolve);
-    });
-}
-
-/**
- * @return {Promise}
- */
-InspectorTest.waitForAccessibilityNodeUpdateInARIAPane = function()
-{
-    return new Promise(function(resolve, reject)
-    {
-        InspectorTest.addSniffer(WebInspector.ARIAAttributesPane.prototype, "_gotNodeForTest", resolve);
-    });
-}
 };
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/accessibility/edit-aria-attributes.html b/third_party/WebKit/LayoutTests/inspector/elements/accessibility/edit-aria-attributes.html
index e08c0ad..9853651 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/accessibility/edit-aria-attributes.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/accessibility/edit-aria-attributes.html
@@ -7,11 +7,9 @@
 
 function test()
 {
-    InspectorTest.showAccessibilityView().then((view) => {
-        InspectorTest.selectNodeAndWaitForAccessibility("inspected")
-                     .then(() => {
-                         editAriaChecked(); });
-                     });
+    WebInspector.viewManager.showView("accessibility.view")
+        .then(() => InspectorTest.selectNodeAndWaitForAccessibility("inspected"))
+        .then(editAriaChecked);
 
     function editAriaChecked()
     {
@@ -20,8 +18,8 @@
         var treeElement = InspectorTest.findARIAAttributeTreeElement("aria-checked");
         treeElement._startEditing();
         treeElement._prompt._element.textContent = "false";
-        InspectorTest.waitForAccessibilityNodeUpdate().then(() => { editRole(); });
         treeElement._prompt._element.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
+        self.runtime.sharedInstance(WebInspector.AccessibilitySidebarView).doUpdate().then(() => { editRole(); });
     }
 
     function editRole()
@@ -31,8 +29,8 @@
         var treeElement = InspectorTest.findARIAAttributeTreeElement("role");
         treeElement._startEditing();
         treeElement._prompt._element.textContent = "radio";
-        InspectorTest.waitForAccessibilityNodeUpdate().then(() => { postRoleChange(); });
         treeElement._prompt._element.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
+        self.runtime.sharedInstance(WebInspector.AccessibilitySidebarView).doUpdate().then(() => { postRoleChange(); });
     }
 
     function postRoleChange()
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-custom-framework.html b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-custom-framework.html
index 114aa31e..d0992d0 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-custom-framework.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-custom-framework.html
@@ -92,8 +92,6 @@
 
 function test()
 {
-    var sidebarPane = WebInspector.panels.elements.sidebarPanes.eventListeners;
-
     WebInspector.settingForTest("showEventListenersForAncestors").set(false);
     InspectorTest.selectNodeWithId("inspectedNode", step1);
 
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery1.html b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery1.html
index 5772dc5..67dafa9 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery1.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery1.html
@@ -14,13 +14,12 @@
 
 function test()
 {
-    var sidebarPane = WebInspector.panels.elements.sidebarPanes.eventListeners;
-
     WebInspector.settingForTest("showEventListenersForAncestors").set(true);
     InspectorTest.selectNodeWithId("node", step1);
 
     function step1()
     {
+        InspectorTest.showEventListenersWidget();
         InspectorTest.expandAndDumpSelectedElementEventListeners(InspectorTest.completeTest.bind(this));
     }
 }
@@ -33,6 +32,7 @@
 </script>
 </head>
 
+
 <body onload="onloadHandler()">
 <p>
 Tests event listeners output in the Elements sidebar panel.
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery2.html b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery2.html
index 4f4c723..b0e4ebe 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery2.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar-jquery2.html
@@ -15,13 +15,12 @@
 
 function test()
 {
-    var sidebarPane = WebInspector.panels.elements.sidebarPanes.eventListeners;
-
     WebInspector.settingForTest("showEventListenersForAncestors").set(true);
     InspectorTest.selectNodeWithId("node", step1);
 
     function step1()
     {
+        InspectorTest.showEventListenersWidget();
         InspectorTest.expandAndDumpSelectedElementEventListeners(step2);
     }
 
@@ -41,6 +40,7 @@
     }
 }
 
+
 function onloadHandler()
 {
     setupEventListeners();
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar.html b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar.html
index dc15db6..1fa1cc8 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/event-listener-sidebar.html
@@ -37,8 +37,6 @@
 
 function test()
 {
-    var sidebarPane = WebInspector.panels.elements.sidebarPanes.eventListeners;
-
     WebInspector.settingForTest("showEventListenersForAncestors").set(true);
     InspectorTest.selectNodeWithId("node", step1);
 
@@ -73,6 +71,8 @@
 </script>
 </head>
 
+
+
 <body onload="onloadHandler()">
 <p>
 Tests event listeners output in the Elements sidebar panel.
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-1/color-aware-property-value-edit.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-1/color-aware-property-value-edit.html
index 1f0002ab..1aa4127 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-1/color-aware-property-value-edit.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-1/color-aware-property-value-edit.html
@@ -81,7 +81,7 @@
     function setFormat(newFormat, callback)
     {
         WebInspector.settingForTest("colorFormat").set(newFormat);
-        WebInspector.panels.elements.sidebarPanes.styles.doUpdate().then(callback);
+        WebInspector.panels.elements._stylesWidget.doUpdate().then(callback);
     }
 
     function startEditingAndDumpValue(format, propertyName, next)
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-1/commit-selector-mark-matching.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-1/commit-selector-mark-matching.html
index c77efdd..2c68fcb 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-1/commit-selector-mark-matching.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-1/commit-selector-mark-matching.html
@@ -21,7 +21,7 @@
             function nodeCallback(node)
             {
                 nodeId = node.id;
-                stylesPane = WebInspector.panels.elements.sidebarPanes.styles;
+                stylesPane = WebInspector.panels.elements._stylesWidget;
                 InspectorTest.addNewRule("foo, #inspected, .bar, #inspected", callback);
             }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-2/filter-matched-styles-hides-separators.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-2/filter-matched-styles-hides-separators.html
index ea6844b..0b43e89 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-2/filter-matched-styles-hides-separators.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-2/filter-matched-styles-hides-separators.html
@@ -66,7 +66,7 @@
 
     function dumpSidebarSeparators()
     {
-        var separators = WebInspector.panels.elements.sidebarPanes.styles.element.querySelectorAll(".sidebar-separator");
+        var separators = WebInspector.panels.elements._stylesWidget.element.querySelectorAll(".sidebar-separator");
         for (var i = 0; i < separators.length; ++i) {
             var separator = separators[i];
             var hidden = separator.classList.contains("hidden");
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-2/metrics-box-sizing.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-2/metrics-box-sizing.html
index ca95de0..fa5c5d7 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-2/metrics-box-sizing.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-2/metrics-box-sizing.html
@@ -81,7 +81,7 @@
 
         function testBorderBoxInit2(next)
         {
-            section = WebInspector.panels.elements.sidebarPanes.metrics;
+            section = WebInspector.panels.elements._metricsWidget;
             section.expand();
             InspectorTest.addSniffer(section._updateController._updateThrottler, "_processCompletedForTests", next);
         },
@@ -113,7 +113,7 @@
 
         function testContentBoxInit2(next)
         {
-            section = WebInspector.panels.elements.sidebarPanes.metrics;
+            section = WebInspector.panels.elements._metricsWidget;
             section.expand();
             InspectorTest.addSniffer(section._updateController._updateThrottler, "_processCompletedForTests", next);
         },
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-2/page-reload-update-sidebar.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-2/page-reload-update-sidebar.html
index 6d7d9b8..f185d82 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-2/page-reload-update-sidebar.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-2/page-reload-update-sidebar.html
@@ -11,7 +11,7 @@
 
 function test()
 {
-    var stylesSidebarPane = WebInspector.panels.elements.sidebarPanes.styles;
+    var stylesSidebarPane = WebInspector.panels.elements._stylesWidget;
     InspectorTest.runTestSuite([
         function selectInspectedNode(next)
         {
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/style-update-during-selector-edit.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/style-update-during-selector-edit.html
index 69f75307..1659df6 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/style-update-during-selector-edit.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/style-update-during-selector-edit.html
@@ -25,7 +25,7 @@
 
     function rebuildUpdate()
     {
-        if (WebInspector.panels.elements.sidebarPanes.styles.node === treeOutline.selectedDOMNode())
+        if (WebInspector.panels.elements._stylesWidget.node === treeOutline.selectedDOMNode())
             seenRebuildUpdate = true;
     }
 
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-keyframes.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-keyframes.html
index ccd9a83..eb799ef3d5 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-keyframes.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-keyframes.html
@@ -25,7 +25,7 @@
     {
         InspectorTest.addResult("=== Before key modification ===");
         InspectorTest.dumpSelectedElementStyles(true);
-        var section = WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks[1].sections[1];
+        var section = WebInspector.panels.elements._stylesWidget._sectionBlocks[1].sections[1];
         section.startEditingSelector();
         section._selectorElement.textContent = "1%";
         section._selectorElement.dispatchEvent(InspectorTest.createKeyEvent("Enter"));
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links-2.html b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links-2.html
index 84ce46e..c6a984e5 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links-2.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links-2.html
@@ -29,7 +29,7 @@
 
         function testEditSelector(next)
         {
-            var section = WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks[0].sections[3];
+            var section = WebInspector.panels.elements._stylesWidget._sectionBlocks[0].sections[3];
             section.startEditingSelector();
             section._selectorElement.textContent = ".should-change, .INSERTED-OTHER-SELECTOR";
             InspectorTest.waitForSelectorCommitted(onSelectorEdited);
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links.js b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links.js
index 945f3e23..2ae14f9 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links.js
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles-4/styles-update-links.js
@@ -98,7 +98,7 @@
     InspectorTest.getMatchedRules = function()
     {
         var rules = [];
-        for (var block of WebInspector.panels.elements.sidebarPanes.styles._sectionBlocks) {
+        for (var block of WebInspector.panels.elements._stylesWidget._sectionBlocks) {
             for (var section of block.sections) {
                 var rule = section.style().parentRule;
                 if (rule)
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/styles/updates-throttled.html b/third_party/WebKit/LayoutTests/inspector/elements/styles/updates-throttled.html
index cfaa7750..de31570e 100644
--- a/third_party/WebKit/LayoutTests/inspector/elements/styles/updates-throttled.html
+++ b/third_party/WebKit/LayoutTests/inspector/elements/styles/updates-throttled.html
@@ -13,7 +13,7 @@
     function selectCallback()
     {
         InspectorTest.addSniffer(WebInspector.StylesSidebarPane.prototype, "_innerRebuildUpdate", sniffRebuild, true);
-        var stylesPane = WebInspector.panels.elements.sidebarPanes.styles;
+        var stylesPane = WebInspector.panels.elements._stylesWidget;
         for (var i = 0; i < UPDATE_COUNT; ++i)
             WebInspector.context.setFlavor(WebInspector.DOMNode, stylesPane.node());
 
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/sources-panel-focus-editor-on-select-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/sources-panel-focus-editor-on-select-expected.txt
new file mode 100644
index 0000000..c3b30c3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/sources-panel-focus-editor-on-select-expected.txt
@@ -0,0 +1,5 @@
+Verifies that text editor has focus after panel re-selecting.
+
+initial: focused = true
+after panel reselected: focused = true
+
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/sources-panel-focus-editor-on-select.html b/third_party/WebKit/LayoutTests/inspector/sources/sources-panel-focus-editor-on-select.html
new file mode 100644
index 0000000..604bcf6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/sources/sources-panel-focus-editor-on-select.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/debugger-test.js"></script>
+<script>
+function test()
+{
+    InspectorTest.showScriptSource("inspector-test.js", onSourceFrame);
+    function onSourceFrame(sourceFrame)
+    {
+        InspectorTest.addResult("initial: focused = " + sourceFrame.hasFocus());
+        WebInspector.inspectorView.showPanel("elements")
+            .then(() => WebInspector.inspectorView.showPanel("sources"))
+            .then(onPanelReselected.bind(null, sourceFrame));
+    }
+
+    function onPanelReselected(sourceFrame)
+    {
+        InspectorTest.addResult("after panel reselected: focused = " + sourceFrame.hasFocus());
+        InspectorTest.completeTest();
+    }
+};
+</script>
+</head>
+<body onload="runTest()">
+<p>Verifies that text editor has focus after panel re-selecting.</p>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/forms/color/input-appearance-color-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/forms/color/input-appearance-color-expected.txt
new file mode 100644
index 0000000..2b162df
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/android/fast/forms/color/input-appearance-color-expected.txt
@@ -0,0 +1,149 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {H3} at (0,0) size 784x23
+        LayoutText {#text} at (0,0) size 163x22
+          text run at (0,0) width 163: "Default Appearance"
+      LayoutBlockFlow (anonymous) at (0,41.72) size 784x43
+        LayoutText {#text} at (0,0) size 272x19
+          text run at (0,0) width 272: "List color controls have different appearance."
+        LayoutBR {BR} at (271,15) size 1x0
+        LayoutBlockFlow {INPUT} at (0,20) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#000000] [border: (1px solid #777777)]
+        LayoutBlockFlow {INPUT} at (44,20) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#000000] [border: (1px solid #000000)]
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {H3} at (0,103.44) size 784x23
+        LayoutText {#text} at (0,0) size 162x22
+          text run at (0,0) width 162: "Different Font Sizes"
+      LayoutBlockFlow (anonymous) at (0,145.16) size 784x43
+        LayoutText {#text} at (0,0) size 549x19
+          text run at (0,0) width 549: "List color controls have different sizes depending on font sizes. Normal color controls don't."
+        LayoutBR {BR} at (548,15) size 1x0
+        LayoutBlockFlow {INPUT} at (0,20) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#00FF00] [border: (1px solid #777777)]
+        LayoutText {#text} at (44,21) size 4x19
+          text run at (44,21) width 4: " "
+        LayoutBlockFlow {INPUT} at (48,20) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#00FF00] [border: (1px solid #777777)]
+        LayoutText {#text} at (92,21) size 4x19
+          text run at (92,21) width 4: " "
+        LayoutBlockFlow {INPUT} at (96,20) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#00FF00] [border: (1px solid #777777)]
+        LayoutText {#text} at (140,21) size 4x19
+          text run at (140,21) width 4: " "
+        LayoutBlockFlow {INPUT} at (144,20) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutText {#text} at (232,21) size 4x19
+          text run at (232,21) width 4: " "
+        LayoutBlockFlow {INPUT} at (236,20) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutText {#text} at (324,21) size 4x19
+          text run at (324,21) width 4: " "
+        LayoutBlockFlow {INPUT} at (328,20) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {H3} at (0,206.88) size 784x23
+        LayoutText {#text} at (0,0) size 123x22
+          text run at (0,0) width 123: "Various Colors"
+      LayoutBlockFlow (anonymous) at (0,248.59) size 784x23
+        LayoutBlockFlow {INPUT} at (0,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#FF0000] [border: (1px solid #777777)]
+        LayoutText {#text} at (44,1) size 4x19
+          text run at (44,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (48,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#00FF00] [border: (1px solid #777777)]
+        LayoutText {#text} at (92,1) size 4x19
+          text run at (92,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (96,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#0000FF] [border: (1px solid #777777)]
+        LayoutText {#text} at (140,1) size 4x19
+          text run at (140,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (144,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#EC008C] [border: (1px solid #777777)]
+        LayoutText {#text} at (188,1) size 4x19
+          text run at (188,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (192,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#40E0D0] [border: (1px solid #777777)]
+        LayoutText {#text} at (236,1) size 4x19
+          text run at (236,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (240,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#FF0000] [border: (1px solid #000000)]
+        LayoutText {#text} at (328,1) size 4x19
+          text run at (328,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (332,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#00FF00] [border: (1px solid #000000)]
+        LayoutText {#text} at (420,1) size 4x19
+          text run at (420,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (424,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#0000FF] [border: (1px solid #000000)]
+        LayoutText {#text} at (512,1) size 4x19
+          text run at (512,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (516,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#EC008C] [border: (1px solid #000000)]
+        LayoutText {#text} at (604,1) size 4x19
+          text run at (604,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (608,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#40E0D0] [border: (1px solid #000000)]
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {H3} at (0,290.31) size 784x23
+        LayoutText {#text} at (0,0) size 115x22
+          text run at (0,0) width 115: "Arbitrary Size"
+      LayoutBlockFlow (anonymous) at (0,332.03) size 784x46
+        LayoutBlockFlow {INPUT} at (0,9) size 100x30 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 94x26
+            LayoutBlockFlow {DIV} at (2,4) size 90x18 [bgcolor=#FF0000] [border: (1px solid #777777)]
+        LayoutText {#text} at (100,17) size 4x19
+          text run at (100,17) width 4: " "
+        LayoutBlockFlow {INPUT} at (104,0) size 88x46 [bgcolor=#DDDDDD] [border: (2px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (6,4) size 76x38
+            LayoutBlockFlow {DIV} at (4,8) size 68x22 [bgcolor=#FF0000] [border: (2px solid #777777)]
+        LayoutText {#text} at (192,17) size 4x19
+          text run at (192,17) width 4: " "
+        LayoutBlockFlow {INPUT} at (196,0) size 176x46 [bgcolor=#DDDDDD] [border: (2px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (6,4) size 164x38
+            LayoutBlockFlow {DIV} at (16,8) size 100x22 [bgcolor=#FF0000] [border: (2px solid #000000)]
+        LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {H3} at (0,396.75) size 784x23
+        LayoutText {#text} at (0,0) size 98x22
+          text run at (0,0) width 98: "Other styles"
+      LayoutBlockFlow (anonymous) at (0,438.47) size 784x23
+        LayoutBlockFlow {INPUT} at (0,0) size 44x23 [bgcolor=#FFFF00] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#FF0000] [border: (1px solid #777777)]
+        LayoutText {#text} at (44,1) size 4x19
+          text run at (44,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (48,0) size 88x23 [bgcolor=#FFFF00] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#FF0000] [border: (1px solid #000000)]
+        LayoutText {#text} at (136,1) size 4x19
+          text run at (136,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (140,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #00FF00)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#FF0000] [border: (1px solid #777777)]
+        LayoutText {#text} at (184,1) size 4x19
+          text run at (184,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (188,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #00FF00)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#FF0000] [border: (1px solid #000000)]
+        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/bidi-menulist-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/text/international/bidi-menulist-expected.png
deleted file mode 100644
index 952e9b6..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/bidi-menulist-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/menulist-width-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/text/international/menulist-width-rtl-expected.png
deleted file mode 100644
index f8508520..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/menulist-width-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/menulist-width-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/text/international/menulist-width-rtl-expected.txt
deleted file mode 100644
index 74581524..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/menulist-width-rtl-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x75
-  LayoutBlockFlow {HTML} at (0,0) size 800x75
-    LayoutBlockFlow {BODY} at (8,8) size 784x59
-      LayoutBlockFlow {DIV} at (0,0) size 784x20
-        LayoutText {#text} at (0,0) size 587x19
-          text run at (0,0) width 587: "The following line and the SELECT element should have same text, and no characters are lacking."
-      LayoutBlockFlow {DIV} at (0,20) size 784x19
-        LayoutText {#text} at (676,0) size 108x18
-          text run at (676,0) width 108 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-      LayoutBlockFlow (anonymous) at (0,39) size 784x20
-        LayoutMenuList {SELECT} at (668,0) size 116x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 114x18
-            LayoutText (anonymous) at (19,1) size 91x16
-              text run at (19,1) width 91 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
deleted file mode 100644
index 925a94a..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
deleted file mode 100644
index d8a1d419..0000000
--- a/third_party/WebKit/LayoutTests/platform/android/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x532
-  LayoutBlockFlow {HTML} at (0,0) size 800x532
-    LayoutBlockFlow {BODY} at (8,16) size 784x508
-      LayoutBlockFlow {P} at (0,0) size 784x20
-        LayoutText {#text} at (0,0) size 659x19
-          text run at (0,0) width 457: "Verify that the alignment and writing direction of each selected item matches "
-          text run at (456,0) width 203: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,36) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 35: "First "
-              text run at (39,1) width 50 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (89,1) width 18: "03"
-              text run at (107,1) width 39 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (146,1) width 28: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 27: "First "
-            text run at (37,10) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (75,10) width 12: "03"
-            text run at (87,10) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (115,10) width 25: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 24: "fifth"
-              text run at (28,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (82,1) width 18: "03"
-              text run at (100,1) width 43 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (143,1) width 31: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 22: "fifth"
-            text run at (32,10) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (73,10) width 12: "03"
-            text run at (85,10) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (116,10) width 24: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 170 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 170 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,272) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 35: "First "
-              text run at (359,1) width 50 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (409,1) width 18: "03"
-              text run at (427,1) width 39 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (466,1) width 28: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 27: "First "
-            text run at (357,10) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (395,10) width 12: "03"
-            text run at (407,10) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (435,10) width 25: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 24: "fifth"
-              text run at (348,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (402,1) width 18: "03"
-              text run at (420,1) width 43 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (463,1) width 31: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 22: "fifth"
-            text run at (352,10) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (393,10) width 12: "03"
-            text run at (405,10) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (436,10) width 24: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 170 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 170 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.png
index 465d9ca..62b7a53 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.txt
index 8d77c69..654a9bd 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/text-overflow-input-expected.txt
@@ -32,7 +32,7 @@
           text run at (154,65) width 4: " "
         LayoutTextControl {INPUT} at (158,64) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 150x16
-            LayoutBlockFlow {DIV} at (0,0) size 137x16
+            LayoutBlockFlow {DIV} at (12,0) size 138x16
         LayoutText {#text} at (314,65) size 4x19
           text run at (314,65) width 4: " "
         LayoutTextControl {INPUT} at (318,64) size 154x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -40,7 +40,7 @@
           text run at (472,65) width 4: " "
         LayoutTextControl {INPUT} at (476,64) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 150x16
-            LayoutBlockFlow {DIV} at (0,0) size 137x16
+            LayoutBlockFlow {DIV} at (12,0) size 138x16
         LayoutText {#text} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,86) size 154x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutText {#text} at (0,0) size 0x0
@@ -70,7 +70,7 @@
           text run at (154,65) width 4: " "
         LayoutTextControl {INPUT} at (158,64) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 150x16
-            LayoutBlockFlow {DIV} at (0,0) size 137x16
+            LayoutBlockFlow {DIV} at (12,0) size 138x16
         LayoutText {#text} at (314,65) size 4x19
           text run at (314,65) width 4: " "
         LayoutTextControl {INPUT} at (318,64) size 154x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -78,7 +78,7 @@
           text run at (472,65) width 4: " "
         LayoutTextControl {INPUT} at (476,64) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 150x16
-            LayoutBlockFlow {DIV} at (0,0) size 137x16
+            LayoutBlockFlow {DIV} at (12,0) size 138x16
         LayoutText {#text} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,86) size 154x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutText {#text} at (0,0) size 0x0
@@ -134,20 +134,20 @@
       text run at (-167,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,119) size 150x16
   LayoutBlockFlow {DIV} at (2,3) size 150x16
-layer at (169,119) size 137x16 scrollX 180.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (3,3) size 137x16 [color=#A9A9A9]
-    LayoutText {#text} at (-180,0) size 317x16
-      text run at (-180,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (169,119) size 137x16
-  LayoutBlockFlow {DIV} at (0,0) size 137x16
+layer at (181,119) size 138x16 scrollX 179.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (15,3) size 138x16 [color=#A9A9A9]
+    LayoutText {#text} at (-179,0) size 317x16
+      text run at (-179,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (181,119) size 138x16
+  LayoutBlockFlow {DIV} at (0,0) size 138x16
 layer at (328,119) size 150x16 scrollX 167.00 scrollWidth 317
   LayoutBlockFlow {DIV} at (2,3) size 150x16
     LayoutText {#text} at (-167,0) size 317x16
       text run at (-167,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (487,119) size 137x16 scrollX 180.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (0,0) size 137x16
-    LayoutText {#text} at (-180,0) size 317x16
-      text run at (-180,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (499,119) size 138x16 scrollX 179.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (0,0) size 138x16
+    LayoutText {#text} at (-179,0) size 317x16
+      text run at (-179,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,141) size 150x16 scrollX 125.00 scrollWidth 275
   LayoutBlockFlow {DIV} at (2,3) size 150x16
     LayoutText {#text} at (-125,0) size 275x16
@@ -182,20 +182,20 @@
       text run at (-167,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,243) size 150x16
   LayoutBlockFlow {DIV} at (2,3) size 150x16
-layer at (169,243) size 137x16 scrollX 180.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (3,3) size 137x16 [color=#A9A9A9]
-    LayoutText {#text} at (-180,0) size 317x16
-      text run at (-180,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (169,243) size 137x16
-  LayoutBlockFlow {DIV} at (0,0) size 137x16
+layer at (181,243) size 138x16 scrollX 179.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (15,3) size 138x16 [color=#A9A9A9]
+    LayoutText {#text} at (-179,0) size 317x16
+      text run at (-179,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (181,243) size 138x16
+  LayoutBlockFlow {DIV} at (0,0) size 138x16
 layer at (328,243) size 150x16 scrollX 167.00 scrollWidth 317
   LayoutBlockFlow {DIV} at (2,3) size 150x16
     LayoutText {#text} at (-167,0) size 317x16
       text run at (-167,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (487,243) size 137x16 scrollX 180.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (0,0) size 137x16
-    LayoutText {#text} at (-180,0) size 317x16
-      text run at (-180,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (499,243) size 138x16 scrollX 179.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (0,0) size 138x16
+    LayoutText {#text} at (-179,0) size 317x16
+      text run at (-179,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,265) size 150x16 scrollX 125.00 scrollWidth 275
   LayoutBlockFlow {DIV} at (2,3) size 150x16
     LayoutText {#text} at (-125,0) size 275x16
@@ -224,15 +224,15 @@
   LayoutBlockFlow {DIV} at (138,3.50) size 9x9
 layer at (625,79) size 9x9 transparent
   LayoutBlockFlow {DIV} at (138,3.50) size 9x9
-layer at (307,123) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (138,3.50) size 9x9
-layer at (625,123) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (138,3.50) size 9x9
+layer at (169,123) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (487,123) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
 layer at (307,203) size 9x9 transparent
   LayoutBlockFlow {DIV} at (138,3.50) size 9x9
 layer at (625,203) size 9x9 transparent
   LayoutBlockFlow {DIV} at (138,3.50) size 9x9
-layer at (307,247) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (138,3.50) size 9x9
-layer at (625,247) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (138,3.50) size 9x9
+layer at (169,247) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (487,247) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.png
index 6861565..3cd1ad4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.txt
index 2b162df..3844f1d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/color/input-appearance-color-expected.txt
@@ -146,4 +146,14 @@
         LayoutBlockFlow {INPUT} at (188,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #00FF00)]
           LayoutFlexibleBox {DIV} at (3,2) size 82x19
             LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#FF0000] [border: (1px solid #000000)]
+        LayoutText {#text} at (276,1) size 4x19
+          text run at (276,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (280,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#40E0D0] [border: (1px solid #777777)]
+        LayoutText {#text} at (324,1) size 4x19
+          text run at (324,1) width 4: " "
+        LayoutBlockFlow {INPUT} at (328,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (24,4) size 50x11 [bgcolor=#FF0000] [border: (1px solid #000000)]
         LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.png
index 926cc7d..168400e 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.txt
index 20aeb597..8bdc0c2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/placeholder-position-expected.txt
@@ -21,7 +21,7 @@
       LayoutBR {BR} at (354,38) size 0x0
       LayoutTextControl {INPUT} at (0,44) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (3,3) size 150x16
-          LayoutBlockFlow {DIV} at (0,0) size 137x16
+          LayoutBlockFlow {DIV} at (12,0) size 138x16
       LayoutBR {BR} at (156,60) size 0x0
       LayoutTextControl {INPUT} at (0,66) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (3,3) size 150x16
@@ -83,12 +83,12 @@
       text run at (0,0) width 105: "\x{65E5}\x{672C}\x{8A9E}placeholder"
 layer at (206,33) size 150x16
   LayoutBlockFlow {DIV} at (2,3) size 150x16
-layer at (11,55) size 137x16
-  LayoutBlockFlow {DIV} at (3,3) size 137x16 [color=#A9A9A9]
-    LayoutText {#text} at (71,0) size 66x16
-      text run at (71,0) width 66: "placeholder"
-layer at (11,55) size 137x16
-  LayoutBlockFlow {DIV} at (0,0) size 137x16
+layer at (23,55) size 138x16
+  LayoutBlockFlow {DIV} at (15,3) size 138x16 [color=#A9A9A9]
+    LayoutText {#text} at (72,0) size 66x16
+      text run at (72,0) width 66: "placeholder"
+layer at (23,55) size 138x16
+  LayoutBlockFlow {DIV} at (0,0) size 138x16
 layer at (11,77) size 137x16
   LayoutBlockFlow {DIV} at (3,3) size 137x16 [color=#A9A9A9]
     LayoutText {#text} at (0,0) size 66x16
@@ -165,8 +165,8 @@
   LayoutBlockFlow {DIV} at (2,3) size 150x16
 layer at (149,15) size 9x9 transparent
   LayoutBlockFlow {DIV} at (138,3.50) size 9x9
-layer at (149,59) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (138,3.50) size 9x9
+layer at (11,59) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
 layer at (149,81) size 9x9 transparent
   LayoutBlockFlow {DIV} at (138,3.50) size 9x9
 layer at (8,334) size 154x36
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.png
index e6bdefc..8474407 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.txt
index 3561b371..8574261 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/search/search-rtl-expected.txt
@@ -18,45 +18,45 @@
       LayoutBlockFlow {P} at (0,36) size 784x66
         LayoutTextControl {INPUT} at (0,0) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 150x16
-            LayoutBlockFlow {DIV} at (0,0) size 137x16
+            LayoutBlockFlow {DIV} at (12,0) size 138x16
         LayoutText {#text} at (156,1) size 4x19
           text run at (156,1) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,22) size 216x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 210x16
-            LayoutBlockFlow {DIV} at (0,0) size 197x16
+            LayoutBlockFlow {DIV} at (12,0) size 198x16
         LayoutText {#text} at (216,23) size 4x19
           text run at (216,23) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,44) size 156x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 150x16
-            LayoutBlockFlow {DIV} at (0,0) size 137x16
+            LayoutBlockFlow {DIV} at (12,0) size 138x16
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {P} at (0,118) size 784x20
         LayoutText {#text} at (0,0) size 37x19
           text run at (0,0) width 37: "PASS"
-layer at (11,47) size 137x16 scrollX 6.00 scrollWidth 143
-  LayoutBlockFlow {DIV} at (0,0) size 137x16
-    LayoutText {#text} at (-6,0) size 143x16
-      text run at (-6,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
-      text run at (17,0) width 21: "she"
-      text run at (38,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
-      text run at (84,0) width 14: "he"
-      text run at (98,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (11,69) size 197x16
-  LayoutBlockFlow {DIV} at (0,0) size 197x16
-    LayoutText {#text} at (54,0) size 143x16
-      text run at (54,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
-      text run at (77,0) width 21: "she"
-      text run at (98,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
-      text run at (144,0) width 14: "he"
-      text run at (158,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (11,91) size 137x16
-  LayoutBlockFlow {DIV} at (0,0) size 137x16
-layer at (149,51) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (138,3.50) size 9x9
-layer at (209,73) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (198,3.50) size 9x9
-layer at (149,95) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (138,3.50) size 9x9
+layer at (23,47) size 138x16 scrollX 5.00 scrollWidth 143
+  LayoutBlockFlow {DIV} at (0,0) size 138x16
+    LayoutText {#text} at (-5,0) size 143x16
+      text run at (-5,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
+      text run at (18,0) width 21: "she"
+      text run at (39,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
+      text run at (85,0) width 14: "he"
+      text run at (99,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
+layer at (23,69) size 198x16
+  LayoutBlockFlow {DIV} at (0,0) size 198x16
+    LayoutText {#text} at (55,0) size 143x16
+      text run at (55,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
+      text run at (78,0) width 21: "she"
+      text run at (99,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
+      text run at (145,0) width 14: "he"
+      text run at (159,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
+layer at (23,91) size 138x16
+  LayoutBlockFlow {DIV} at (0,0) size 138x16
+layer at (11,51) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (11,73) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (11,95) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
 caret: position 0 of child 0 {DIV} of child 0 {DIV} of child 0 {DIV} of {#document-fragment} of child 9 {INPUT} of child 3 {P} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-rtl-expected.png
new file mode 100644
index 0000000..8350d5d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-rtl-expected.txt
new file mode 100644
index 0000000..acc56fd0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -0,0 +1,168 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x567
+  LayoutBlockFlow {HTML} at (0,0) size 800x567
+    LayoutBlockFlow {BODY} at (8,16) size 784x543
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 755x39
+          text run at (0,0) width 755: "This tests that bidirectional text is correctly rendered in popup controls. The order of the text below each popup button should"
+          text run at (0,20) width 520: "match the order of the select's option text, and the order of the text in the popup menu."
+      LayoutBlockFlow {DL} at (0,56) size 784x180
+        LayoutBlockFlow {DT} at (0,0) size 784x20
+          LayoutText {#text} at (0,0) size 262x19
+            text run at (0,0) width 262: "1) direction: rtl; -webkit-rtl-ordering: logical"
+        LayoutBlockFlow {DD} at (40,20) size 744x40
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 98x18
+                LayoutText (anonymous) at (31,1) size 63x16
+                  text run at (31,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+                  text run at (73,1) width 21: "abc"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 100x20
+            LayoutText {#text} at (31,0) size 69x19
+              text run at (31,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+              text run at (78,0) width 22: "abc"
+        LayoutBlockFlow {DT} at (0,60) size 784x20
+          LayoutText {#text} at (0,0) size 105x19
+            text run at (0,0) width 105: "2) text-align: right"
+        LayoutBlockFlow {DD} at (40,80) size 744x40
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 200x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 198x18
+                LayoutText (anonymous) at (4,1) size 63x16
+                  text run at (4,1) width 21: "abc"
+                  text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 200x20
+            LayoutText {#text} at (0,0) size 69x19
+              text run at (0,0) width 22: "abc"
+              text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+        LayoutBlockFlow {DT} at (0,120) size 784x20
+          LayoutText {#text} at (0,0) size 68x19
+            text run at (0,0) width 68: "3) No style"
+        LayoutBlockFlow {DD} at (40,140) size 744x40
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 98x18
+                LayoutText (anonymous) at (4,1) size 63x16
+                  text run at (4,1) width 21: "abc"
+                  text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 100x20
+            LayoutText {#text} at (0,0) size 69x19
+              text run at (0,0) width 22: "abc"
+              text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+      LayoutBlockFlow {HR} at (0,252) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {DIV} at (0,262) size 784x59
+        LayoutBlockFlow (anonymous) at (0,0) size 784x20
+          LayoutText {#text} at (0,0) size 587x19
+            text run at (0,0) width 587: "The following line and the SELECT element should have same text, and no characters are lacking."
+        LayoutBlockFlow {DIV} at (0,20) size 784x19
+          LayoutText {#text} at (0,0) size 108x18
+            text run at (0,0) width 108 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+        LayoutBlockFlow (anonymous) at (0,39) size 784x20
+          LayoutMenuList {SELECT} at (0,0) size 115x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+            LayoutBlockFlow (anonymous) at (1,1) size 113x18
+              LayoutText (anonymous) at (4,1) size 82x16
+                text run at (4,1) width 82 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+          LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {HR} at (0,329) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {P} at (0,347) size 784x20
+        LayoutText {#text} at (0,0) size 659x19
+          text run at (0,0) width 659: "Verify that the alignment and writing direction of each selected item matches the one below the pop-up button."
+layer at (8,399) size 784x160
+  LayoutBlockFlow {DIV} at (0,383) size 784x160
+    LayoutMultiColumnSet (anonymous) at (0,0) size 784x160
+layer at (8,399) size 384x320 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
+  LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x320
+    LayoutBlockFlow {DIV} at (0,0) size 384x160
+      LayoutMenuList {SELECT} at (0,0) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (4,1) size 170x18
+            text run at (4,1) width 35: "First "
+            text run at (39,1) width 50 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (89,1) width 18: "03"
+            text run at (107,1) width 39 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (146,1) width 28: " fifth"
+      LayoutBlockFlow {DIV} at (0,22) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 27: "First "
+          text run at (28,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (66,1) width 12: "03"
+          text run at (78,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (106,1) width 25: " fifth"
+      LayoutMenuList {SELECT} at (0,40) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (4,1) size 170x18
+            text run at (4,1) width 24: "fifth"
+            text run at (28,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (82,1) width 18: "03"
+            text run at (100,1) width 43 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (143,1) width 31: "First"
+      LayoutBlockFlow {DIV} at (0,62) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 22: "fifth"
+          text run at (23,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (64,1) width 12: "03"
+          text run at (76,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (107,1) width 24: "First"
+      LayoutMenuList {SELECT} at (0,80) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (4,1) size 170x18
+            text run at (4,1) width 170 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,102) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,120) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (4,1) size 170x18
+            text run at (4,1) width 170 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,142) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+    LayoutBlockFlow {DIV} at (0,160) size 384x160
+      LayoutMenuList {SELECT} at (0,0) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (174,1) size 170x18
+            text run at (174,1) width 35: "First "
+            text run at (209,1) width 50 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (259,1) width 18: "03"
+            text run at (277,1) width 39 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (316,1) width 28: " fifth"
+      LayoutBlockFlow {DIV} at (0,22) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 27: "First "
+          text run at (248,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (286,1) width 12: "03"
+          text run at (298,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (326,1) width 25: " fifth"
+      LayoutMenuList {SELECT} at (0,40) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (174,1) size 170x18
+            text run at (174,1) width 24: "fifth"
+            text run at (198,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (252,1) width 18: "03"
+            text run at (270,1) width 43 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (313,1) width 31: "First"
+      LayoutBlockFlow {DIV} at (0,62) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 22: "fifth"
+          text run at (243,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (284,1) width 12: "03"
+          text run at (296,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (327,1) width 24: "First"
+      LayoutMenuList {SELECT} at (0,80) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (174,1) size 170x18
+            text run at (174,1) width 170 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,102) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,120) size 350x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (174,1) size 170x18
+            text run at (174,1) width 170 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,142) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/bidi-menulist-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/bidi-menulist-expected.png
deleted file mode 100644
index fee3b41..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/bidi-menulist-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/bidi-menulist-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/bidi-menulist-expected.txt
deleted file mode 100644
index e53403a..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/bidi-menulist-expected.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x60
-        LayoutText {#text} at (0,0) size 426x19
-          text run at (0,0) width 426: "This tests that bidirectional text is correctly rendered in popup controls."
-        LayoutBR {BR} at (426,15) size 0x0
-        LayoutText {#text} at (0,20) size 766x39
-          text run at (0,20) width 766: "The order of the text below each popup button should match the order of the select's option text, and the order of the text in the"
-          text run at (0,40) width 79: "popup menu."
-      LayoutBlockFlow (anonymous) at (0,76) size 784x40
-        LayoutText {#text} at (0,0) size 262x19
-          text run at (0,0) width 262: "1) direction: rtl; -webkit-rtl-ordering: logical"
-        LayoutBR {BR} at (262,15) size 0x0
-        LayoutMenuList {SELECT} at (0,20) size 100x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 98x18
-            LayoutText (anonymous) at (31,1) size 63x16
-              text run at (31,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-              text run at (73,1) width 21: "abc"
-        LayoutBR {BR} at (100,35) size 0x0
-      LayoutBlockFlow {DIV} at (0,116) size 100x20
-        LayoutText {#text} at (0,0) size 69x19
-          text run at (0,0) width 22: "abc"
-          text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,136) size 784x60
-        LayoutBR {BR} at (0,0) size 0x19
-        LayoutText {#text} at (0,20) size 105x19
-          text run at (0,20) width 105: "2) text-align: right"
-        LayoutBR {BR} at (105,35) size 0x0
-        LayoutMenuList {SELECT} at (0,40) size 200x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 198x18
-            LayoutText (anonymous) at (4,1) size 63x16
-              text run at (4,1) width 21: "abc"
-              text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (200,55) size 0x0
-      LayoutBlockFlow {DIV} at (0,196) size 200x20
-        LayoutText {#text} at (0,0) size 69x19
-          text run at (0,0) width 22: "abc"
-          text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,216) size 784x60
-        LayoutBR {BR} at (0,0) size 0x19
-        LayoutText {#text} at (0,20) size 68x19
-          text run at (0,20) width 68: "3) No style"
-        LayoutBR {BR} at (68,35) size 0x0
-        LayoutMenuList {SELECT} at (0,40) size 100x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 98x18
-            LayoutText (anonymous) at (4,1) size 63x16
-              text run at (4,1) width 21: "abc"
-              text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (100,55) size 0x0
-      LayoutBlockFlow {DIV} at (0,276) size 100x20
-        LayoutText {#text} at (0,0) size 69x19
-          text run at (0,0) width 22: "abc"
-          text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,296) size 784x20
-        LayoutBR {BR} at (0,0) size 0x19
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/menulist-width-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/menulist-width-rtl-expected.png
deleted file mode 100644
index 5b1d60d0..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/menulist-width-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/menulist-width-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/menulist-width-rtl-expected.txt
deleted file mode 100644
index 738474b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/menulist-width-rtl-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x75
-  LayoutBlockFlow {HTML} at (0,0) size 800x75
-    LayoutBlockFlow {BODY} at (8,8) size 784x59
-      LayoutBlockFlow {DIV} at (0,0) size 784x20
-        LayoutText {#text} at (0,0) size 587x19
-          text run at (0,0) width 587: "The following line and the SELECT element should have same text, and no characters are lacking."
-      LayoutBlockFlow {DIV} at (0,20) size 784x19
-        LayoutText {#text} at (676,0) size 108x18
-          text run at (676,0) width 108 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-      LayoutBlockFlow (anonymous) at (0,39) size 784x20
-        LayoutMenuList {SELECT} at (669,0) size 115x20 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 113x18
-            LayoutText (anonymous) at (18,1) size 91x16
-              text run at (18,1) width 91 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
deleted file mode 100644
index ae16307..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
deleted file mode 100644
index 7d9605b..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x524
-  LayoutBlockFlow {HTML} at (0,0) size 800x524
-    LayoutBlockFlow {BODY} at (8,16) size 784x500
-      LayoutBlockFlow {P} at (0,0) size 784x20
-        LayoutText {#text} at (0,0) size 659x19
-          text run at (0,0) width 457: "Verify that the alignment and writing direction of each selected item matches "
-          text run at (456,0) width 203: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,36) size 784x232
-        LayoutMenuList {SELECT} at (0,0) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 35: "First "
-              text run at (39,1) width 50 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (89,1) width 18: "03"
-              text run at (107,1) width 39 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (146,1) width 28: " fifth"
-        LayoutBlockFlow {DIV} at (0,22) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 27: "First "
-            text run at (37,10) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (75,10) width 12: "03"
-            text run at (87,10) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (115,10) width 25: " fifth"
-        LayoutMenuList {SELECT} at (0,58) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 24: "fifth"
-              text run at (28,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (82,1) width 18: "03"
-              text run at (100,1) width 43 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (143,1) width 31: "First"
-        LayoutBlockFlow {DIV} at (0,80) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 22: "fifth"
-            text run at (32,10) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (73,10) width 12: "03"
-            text run at (85,10) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (116,10) width 24: "First"
-        LayoutMenuList {SELECT} at (0,116) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 170 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,138) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,174) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (4,1) size 170x18
-              text run at (4,1) width 170 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,196) size 470x36
-          LayoutText {#text} at (10,10) size 130x15
-            text run at (10,10) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,268) size 784x232
-        LayoutMenuList {SELECT} at (0,0) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 35: "First "
-              text run at (359,1) width 50 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (409,1) width 18: "03"
-              text run at (427,1) width 39 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (466,1) width 28: " fifth"
-        LayoutBlockFlow {DIV} at (0,22) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 27: "First "
-            text run at (357,10) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (395,10) width 12: "03"
-            text run at (407,10) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (435,10) width 25: " fifth"
-        LayoutMenuList {SELECT} at (0,58) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 24: "fifth"
-              text run at (348,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (402,1) width 18: "03"
-              text run at (420,1) width 43 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (463,1) width 31: "First"
-        LayoutBlockFlow {DIV} at (0,80) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 22: "fifth"
-            text run at (352,10) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (393,10) width 12: "03"
-            text run at (405,10) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (436,10) width 24: "First"
-        LayoutMenuList {SELECT} at (0,116) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 170 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,138) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,174) size 500x22 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (324,1) size 170x18
-              text run at (324,1) width 170 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,196) size 470x36
-          LayoutText {#text} at (330,10) size 130x15
-            text run at (330,10) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.png
index 88fb335..91eb255 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.txt
index 8d667d0..ccebf2e0 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/css/text-overflow-input-expected.txt
@@ -33,7 +33,7 @@
           text run at (131,37) width 4: " "
         LayoutTextControl {INPUT} at (135,37) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 125x13
-            LayoutBlockFlow {DIV} at (0,0) size 113x13
+            LayoutBlockFlow {DIV} at (12,0) size 113x13
         LayoutText {#text} at (268,37) size 4x18
           text run at (268,37) width 4: " "
         LayoutTextControl {INPUT} at (272,37) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -41,7 +41,7 @@
           text run at (403,37) width 4: " "
         LayoutTextControl {INPUT} at (407,37) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 125x13
-            LayoutBlockFlow {DIV} at (0,0) size 113x13
+            LayoutBlockFlow {DIV} at (12,0) size 113x13
         LayoutText {#text} at (540,37) size 4x18
           text run at (540,37) width 4: " "
         LayoutTextControl {INPUT} at (544,37) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -73,7 +73,7 @@
           text run at (131,37) width 4: " "
         LayoutTextControl {INPUT} at (135,37) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 125x13
-            LayoutBlockFlow {DIV} at (0,0) size 113x13
+            LayoutBlockFlow {DIV} at (12,0) size 113x13
         LayoutText {#text} at (268,37) size 4x18
           text run at (268,37) width 4: " "
         LayoutTextControl {INPUT} at (272,37) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -81,7 +81,7 @@
           text run at (403,37) width 4: " "
         LayoutTextControl {INPUT} at (407,37) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 125x13
-            LayoutBlockFlow {DIV} at (0,0) size 113x13
+            LayoutBlockFlow {DIV} at (12,0) size 113x13
         LayoutText {#text} at (540,37) size 4x18
           text run at (540,37) width 4: " "
         LayoutTextControl {INPUT} at (544,37) size 131x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -138,17 +138,17 @@
       text run at (-148,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (11,90) size 125x13
   LayoutBlockFlow {DIV} at (3,3) size 125x13
-layer at (147,90) size 113x13 scrollX 160.00 scrollWidth 274
-  LayoutBlockFlow {DIV} at (4,3) size 113x13 [color=#A9A9A9]
+layer at (159,90) size 113x13 scrollX 160.00 scrollWidth 274
+  LayoutBlockFlow {DIV} at (16,3) size 113x13 [color=#A9A9A9]
     LayoutText {#text} at (-160,0) size 274x13
       text run at (-160,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (147,90) size 113x13
+layer at (159,90) size 113x13
   LayoutBlockFlow {DIV} at (0,0) size 113x13
 layer at (283,90) size 125x13 scrollX 148.00 scrollWidth 274
   LayoutBlockFlow {DIV} at (3,3) size 125x13
     LayoutText {#text} at (-148,0) size 274x13
       text run at (-148,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (419,90) size 113x13 scrollX 160.00 scrollWidth 274
+layer at (431,90) size 113x13 scrollX 160.00 scrollWidth 274
   LayoutBlockFlow {DIV} at (0,0) size 113x13
     LayoutText {#text} at (-160,0) size 274x13
       text run at (-160,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
@@ -186,17 +186,17 @@
       text run at (-148,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (11,162) size 125x13
   LayoutBlockFlow {DIV} at (3,3) size 125x13
-layer at (147,162) size 113x13 scrollX 160.00 scrollWidth 274
-  LayoutBlockFlow {DIV} at (4,3) size 113x13 [color=#A9A9A9]
+layer at (159,162) size 113x13 scrollX 160.00 scrollWidth 274
+  LayoutBlockFlow {DIV} at (16,3) size 113x13 [color=#A9A9A9]
     LayoutText {#text} at (-160,0) size 274x13
       text run at (-160,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (147,162) size 113x13
+layer at (159,162) size 113x13
   LayoutBlockFlow {DIV} at (0,0) size 113x13
 layer at (283,162) size 125x13 scrollX 148.00 scrollWidth 274
   LayoutBlockFlow {DIV} at (3,3) size 125x13
     LayoutText {#text} at (-148,0) size 274x13
       text run at (-148,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (419,162) size 113x13 scrollX 160.00 scrollWidth 274
+layer at (431,162) size 113x13 scrollX 160.00 scrollWidth 274
   LayoutBlockFlow {DIV} at (0,0) size 113x13
     LayoutText {#text} at (-160,0) size 274x13
       text run at (-160,0) width 273: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
@@ -228,15 +228,15 @@
   LayoutBlockFlow {DIV} at (114,1) size 11x11
 layer at (533,72) size 11x11 transparent
   LayoutBlockFlow {DIV} at (114,1) size 11x11
-layer at (261,91) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (114,1) size 11x11
-layer at (533,91) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (114,1) size 11x11
+layer at (147,91) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (419,91) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
 layer at (261,144) size 11x11 transparent
   LayoutBlockFlow {DIV} at (114,1) size 11x11
 layer at (533,144) size 11x11 transparent
   LayoutBlockFlow {DIV} at (114,1) size 11x11
-layer at (261,163) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (114,1) size 11x11
-layer at (533,163) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (114,1) size 11x11
+layer at (147,163) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (419,163) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png
index 3277d8d..0fbcf68 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.txt
index 566f283e..19dcd53 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/placeholder-position-expected.txt
@@ -21,7 +21,7 @@
       LayoutBR {BR} at (285,33) size 0x0
       LayoutTextControl {INPUT} at (0,38) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (4,3) size 125x13
-          LayoutBlockFlow {DIV} at (0,0) size 113x13
+          LayoutBlockFlow {DIV} at (12,0) size 113x13
       LayoutBR {BR} at (133,52) size 0x0
       LayoutTextControl {INPUT} at (0,57) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (4,3) size 125x13
@@ -84,11 +84,11 @@
       text run at (0,0) width 92: "\x{65E5}\x{672C}\x{8A9E}placeholder"
 layer at (161,30) size 125x13
   LayoutBlockFlow {DIV} at (3,3) size 125x13
-layer at (12,49) size 113x13
-  LayoutBlockFlow {DIV} at (4,3) size 113x13 [color=#A9A9A9]
+layer at (24,49) size 113x13
+  LayoutBlockFlow {DIV} at (16,3) size 113x13 [color=#A9A9A9]
     LayoutText {#text} at (54,0) size 59x13
       text run at (54,0) width 59: "placeholder"
-layer at (12,49) size 113x13
+layer at (24,49) size 113x13
   LayoutBlockFlow {DIV} at (0,0) size 113x13
 layer at (12,68) size 113x13
   LayoutBlockFlow {DIV} at (4,3) size 113x13 [color=#A9A9A9]
@@ -166,8 +166,8 @@
   LayoutBlockFlow {DIV} at (3,3) size 125x13
 layer at (126,12) size 11x11 transparent
   LayoutBlockFlow {DIV} at (114,1) size 11x11
-layer at (126,50) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (114,1) size 11x11
+layer at (12,50) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
 layer at (126,69) size 11x11 transparent
   LayoutBlockFlow {DIV} at (114,1) size 11x11
 layer at (8,283) size 131x33
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.png
index bb8e115..6cf6e9a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.txt
index e639333..56069e7 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/search/search-rtl-expected.txt
@@ -18,24 +18,24 @@
       LayoutBlockFlow {P} at (0,34) size 784x57
         LayoutTextControl {INPUT} at (0,0) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 125x13
-            LayoutBlockFlow {DIV} at (0,0) size 113x13
+            LayoutBlockFlow {DIV} at (12,0) size 113x13
         LayoutText {#text} at (133,0) size 4x18
           text run at (133,0) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,19) size 193x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 185x13
-            LayoutBlockFlow {DIV} at (0,0) size 173x13
+            LayoutBlockFlow {DIV} at (12,0) size 173x13
         LayoutText {#text} at (193,19) size 4x18
           text run at (193,19) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,38) size 133x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 125x13
-            LayoutBlockFlow {DIV} at (0,0) size 113x13
+            LayoutBlockFlow {DIV} at (12,0) size 113x13
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {P} at (0,107) size 784x18
         LayoutText {#text} at (0,0) size 37x18
           text run at (0,0) width 37: "PASS"
-layer at (12,45) size 113x13 scrollX 17.00 scrollWidth 130
+layer at (24,45) size 113x13 scrollX 17.00 scrollWidth 130
   LayoutBlockFlow {DIV} at (0,0) size 113x13
     LayoutText {#text} at (-17,0) size 131x13
       text run at (-17,0) width 22 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
@@ -43,7 +43,7 @@
       text run at (22,0) width 43 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
       text run at (64,0) width 13: "he"
       text run at (76,0) width 37 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (12,64) size 173x13
+layer at (24,64) size 173x13
   LayoutBlockFlow {DIV} at (0,0) size 173x13
     LayoutText {#text} at (42,0) size 131x13
       text run at (42,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
@@ -51,12 +51,12 @@
       text run at (82,0) width 43 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
       text run at (124,0) width 13: "he"
       text run at (136,0) width 37 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (12,83) size 113x13
+layer at (24,83) size 113x13
   LayoutBlockFlow {DIV} at (0,0) size 113x13
-layer at (126,46) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (114,1) size 11x11
-layer at (186,65) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (174,1) size 11x11
-layer at (126,84) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (114,1) size 11x11
+layer at (12,46) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (12,65) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (12,84) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
 caret: position 0 of child 0 {DIV} of child 0 {DIV} of child 0 {DIV} of {#document-fragment} of child 9 {INPUT} of child 3 {P} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png
index 7461214a..0f690f79 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt
index 8a8f726d..330b364 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-basic-expected.txt
@@ -125,26 +125,26 @@
       LayoutBR {BR} at (72,409) size 0x18
       LayoutMenuList {SELECT} at (4,443) size 48x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 48x18
-          LayoutText (anonymous) at (8,2) size 17x13
-            text run at (8,2) width 17: "foo"
+          LayoutText (anonymous) at (23,2) size 17x13
+            text run at (23,2) width 17: "foo"
       LayoutText {#text} at (56,442) size 4x18
         text run at (56,442) width 4: " "
       LayoutMenuList {SELECT} at (64,441) size 44x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (3,3) size 38x16
-          LayoutText (anonymous) at (8,1) size 17x13
-            text run at (8,1) width 17: "foo"
+          LayoutText (anonymous) at (13,1) size 17x13
+            text run at (13,1) width 17: "foo"
       LayoutText {#text} at (112,442) size 4x18
         text run at (112,442) width 4: " "
       LayoutMenuList {SELECT} at (120,436) size 54x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (8,8) size 38x16
-          LayoutText (anonymous) at (8,1) size 17x13
-            text run at (8,1) width 17: "foo"
+          LayoutText (anonymous) at (13,1) size 17x13
+            text run at (13,1) width 17: "foo"
       LayoutText {#text} at (178,442) size 4x18
         text run at (178,442) width 4: " "
       LayoutMenuList {SELECT} at (186,443) size 40x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 38x16
-          LayoutText (anonymous) at (8,1) size 17x13
-            text run at (8,1) width 17: "foo"
+          LayoutText (anonymous) at (13,1) size 17x13
+            text run at (13,1) width 17: "foo"
       LayoutText {#text} at (230,442) size 4x18
         text run at (230,442) width 4: " "
       LayoutBR {BR} at (234,442) size 0x18
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-rtl-expected.png
new file mode 100644
index 0000000..0de9691
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-rtl-expected.txt
new file mode 100644
index 0000000..71bbeb0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -0,0 +1,168 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x549
+  LayoutBlockFlow {HTML} at (0,0) size 800x549
+    LayoutBlockFlow {BODY} at (8,16) size 784x525
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 758x36
+          text run at (0,0) width 758: "This tests that bidirectional text is correctly rendered in popup controls. The order of the text below each popup button"
+          text run at (0,18) width 600: "should match the order of the select's option text, and the order of the text in the popup menu."
+      LayoutBlockFlow {DL} at (0,52) size 784x168
+        LayoutBlockFlow {DT} at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 286x18
+            text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
+        LayoutBlockFlow {DD} at (40,18) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 100x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 100x18
+                LayoutText (anonymous) at (32,2) size 60x13
+                  text run at (32,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+                  text run at (73,2) width 19: "abc"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 100x19
+            LayoutText {#text} at (18,1) size 82x18
+              text run at (18,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+              text run at (77,1) width 23: "abc"
+        LayoutBlockFlow {DT} at (0,56) size 784x18
+          LayoutText {#text} at (0,0) size 118x18
+            text run at (0,0) width 118: "2) text-align: right"
+        LayoutBlockFlow {DD} at (40,74) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 200x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 200x18
+                LayoutText (anonymous) at (8,2) size 60x13
+                  text run at (8,2) width 19: "abc"
+                  text run at (26,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 200x19
+            LayoutText {#text} at (0,1) size 82x18
+              text run at (0,1) width 23: "abc"
+              text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+        LayoutBlockFlow {DT} at (0,112) size 784x18
+          LayoutText {#text} at (0,0) size 72x18
+            text run at (0,0) width 72: "3) No style"
+        LayoutBlockFlow {DD} at (40,130) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 100x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 100x18
+                LayoutText (anonymous) at (8,2) size 60x13
+                  text run at (8,2) width 19: "abc"
+                  text run at (26,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 100x19
+            LayoutText {#text} at (0,1) size 82x18
+              text run at (0,1) width 23: "abc"
+              text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+      LayoutBlockFlow {HR} at (0,236) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {DIV} at (0,246) size 784x55
+        LayoutBlockFlow (anonymous) at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 632x18
+            text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
+        LayoutBlockFlow {DIV} at (0,18) size 784x18
+          LayoutText {#text} at (0,0) size 99x16
+            text run at (0,0) width 99 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+        LayoutBlockFlow (anonymous) at (0,36) size 784x19
+          LayoutMenuList {SELECT} at (0,1) size 115x18 [bgcolor=#F8F8F8]
+            LayoutBlockFlow (anonymous) at (0,0) size 115x21
+              LayoutText (anonymous) at (8,2) size 76x13
+                text run at (8,2) width 76 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+          LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {HR} at (0,309) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {P} at (0,327) size 784x18
+        LayoutText {#text} at (0,0) size 709x18
+          text run at (0,0) width 709: "Verify that the alignment and writing direction of each selected item matches the one below the pop-up button."
+layer at (8,377) size 784x164
+  LayoutBlockFlow {DIV} at (0,361) size 784x164
+    LayoutMultiColumnSet (anonymous) at (0,0) size 784x164
+layer at (8,377) size 384x328 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
+  LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x328
+    LayoutBlockFlow {DIV} at (0,0) size 384x164
+      LayoutMenuList {SELECT} at (0,0) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 188x18
+            text run at (8,1) width 37: "First "
+            text run at (44,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (102,1) width 19: "03"
+            text run at (120,1) width 44 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (163,1) width 33: " fifth"
+      LayoutBlockFlow {DIV} at (0,23) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 32: "First "
+          text run at (32,1) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (80,1) width 17: "03"
+          text run at (96,1) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (132,1) width 32: " fifth"
+      LayoutMenuList {SELECT} at (0,41) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 188x18
+            text run at (8,1) width 28: "fifth"
+            text run at (35,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (98,1) width 19: "03"
+            text run at (116,1) width 48 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (163,1) width 33: "First"
+      LayoutBlockFlow {DIV} at (0,64) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 27: "fifth"
+          text run at (27,1) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (78,1) width 17: "03"
+          text run at (94,1) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (135,1) width 29: "First"
+      LayoutMenuList {SELECT} at (0,82) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 188x18
+            text run at (8,1) width 188 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,105) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,123) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 188x18
+            text run at (8,1) width 188 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,146) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+    LayoutBlockFlow {DIV} at (0,164) size 384x164
+      LayoutMenuList {SELECT} at (0,0) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (152,1) size 188x18
+            text run at (152,1) width 37: "First "
+            text run at (188,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (246,1) width 19: "03"
+            text run at (264,1) width 45 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (308,1) width 32: " fifth"
+      LayoutBlockFlow {DIV} at (0,23) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 33: "First "
+          text run at (220,1) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (267,1) width 18: "03"
+          text run at (284,1) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (320,1) width 31: " fifth"
+      LayoutMenuList {SELECT} at (0,41) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (152,1) size 188x18
+            text run at (152,1) width 28: "fifth"
+            text run at (179,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (242,1) width 19: "03"
+            text run at (260,1) width 49 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (308,1) width 32: "First"
+      LayoutBlockFlow {DIV} at (0,64) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 28: "fifth"
+          text run at (215,1) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (266,1) width 17: "03"
+          text run at (282,1) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (323,1) width 28: "First"
+      LayoutMenuList {SELECT} at (0,82) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (152,1) size 188x18
+            text run at (152,1) width 188 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,105) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,123) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (152,1) size 188x18
+            text run at (152,1) width 188 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,146) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.png
index 149bb77f..9ba8ca6 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.txt
index b877c44f..61a5a10 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/select-writing-direction-natural-expected.txt
@@ -84,58 +84,58 @@
         LayoutBlockFlow {DIV} at (0,0) size 784x19
           LayoutMenuList {SELECT} at (222,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8: "A"
-                text run at (39,2) width 8 RTL: "\x{5D0}"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8: "A"
+                text run at (54,2) width 8 RTL: "\x{5D0}"
           LayoutText {#text} at (218,0) size 4x18
             text run at (218,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (148,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8 RTL: "\x{5D0}"
-                text run at (39,2) width 8: "A"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8 RTL: "\x{5D0}"
+                text run at (54,2) width 8: "A"
           LayoutText {#text} at (144,0) size 4x18
             text run at (144,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (74,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (29,2) size 18x13
-                text run at (29,2) width 9: "A"
-                text run at (37,2) width 10 RTL: "(\x{5D0}"
+              LayoutText (anonymous) at (44,2) size 18x13
+                text run at (44,2) width 9: "A"
+                text run at (52,2) width 10 RTL: "(\x{5D0}"
           LayoutText {#text} at (70,0) size 4x18
             text run at (70,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (0,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (29,2) size 18x13
-                text run at (29,2) width 8 RTL: "\x{5D0}"
-                text run at (36,2) width 9: "A"
-                text run at (44,2) width 3 RTL: "("
+              LayoutText (anonymous) at (44,2) size 18x13
+                text run at (44,2) width 8 RTL: "\x{5D0}"
+                text run at (51,2) width 9: "A"
+                text run at (59,2) width 3 RTL: "("
           LayoutText {#text} at (0,0) size 0x0
         LayoutBlockFlow {DIV} at (0,19) size 784x19
           LayoutMenuList {SELECT} at (714,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8: "A"
-                text run at (39,2) width 8 RTL: "\x{5D0}"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8: "A"
+                text run at (54,2) width 8 RTL: "\x{5D0}"
           LayoutText {#text} at (710,0) size 4x18
             text run at (710,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (640,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8 RTL: "\x{5D0}"
-                text run at (39,2) width 8: "A"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8 RTL: "\x{5D0}"
+                text run at (54,2) width 8: "A"
           LayoutText {#text} at (636,0) size 4x18
             text run at (636,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (566,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (29,2) size 18x13
-                text run at (29,2) width 9: "A"
-                text run at (37,2) width 10 RTL: "(\x{5D0}"
+              LayoutText (anonymous) at (44,2) size 18x13
+                text run at (44,2) width 9: "A"
+                text run at (52,2) width 10 RTL: "(\x{5D0}"
           LayoutText {#text} at (562,0) size 4x18
             text run at (562,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (492,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (29,2) size 18x13
-                text run at (29,2) width 8 RTL: "\x{5D0}"
-                text run at (36,2) width 9: "A"
-                text run at (44,2) width 3 RTL: "("
+              LayoutText (anonymous) at (44,2) size 18x13
+                text run at (44,2) width 8 RTL: "\x{5D0}"
+                text run at (51,2) width 9: "A"
+                text run at (59,2) width 3 RTL: "("
           LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/bidi-menulist-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/bidi-menulist-expected.png
deleted file mode 100644
index d79f73d..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/bidi-menulist-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/bidi-menulist-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/bidi-menulist-expected.txt
deleted file mode 100644
index 63cad0e61..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/bidi-menulist-expected.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x54
-        LayoutText {#text} at (0,0) size 458x18
-          text run at (0,0) width 458: "This tests that bidirectional text is correctly rendered in popup controls."
-        LayoutBR {BR} at (457,14) size 1x0
-        LayoutText {#text} at (0,18) size 773x36
-          text run at (0,18) width 773: "The order of the text below each popup button should match the order of the select's option text, and the order of the text"
-          text run at (0,36) width 124: "in the popup menu."
-      LayoutBlockFlow (anonymous) at (0,70) size 784x36
-        LayoutText {#text} at (0,0) size 286x18
-          text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
-        LayoutBR {BR} at (285,14) size 1x0
-        LayoutMenuList {SELECT} at (0,18) size 100x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 100x18
-            LayoutText (anonymous) at (17,2) size 60x13
-              text run at (17,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-              text run at (58,2) width 19: "abc"
-        LayoutBR {BR} at (100,31) size 0x0
-      LayoutBlockFlow {DIV} at (0,106) size 100x19
-        LayoutText {#text} at (0,1) size 82x18
-          text run at (0,1) width 23: "abc"
-          text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,125) size 784x54
-        LayoutBR {BR} at (0,0) size 0x18
-        LayoutText {#text} at (0,18) size 118x18
-          text run at (0,18) width 118: "2) text-align: right"
-        LayoutBR {BR} at (117,32) size 1x0
-        LayoutMenuList {SELECT} at (0,36) size 200x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 200x18
-            LayoutText (anonymous) at (8,2) size 60x13
-              text run at (8,2) width 19: "abc"
-              text run at (26,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (200,49) size 0x0
-      LayoutBlockFlow {DIV} at (0,179) size 200x19
-        LayoutText {#text} at (0,1) size 82x18
-          text run at (0,1) width 23: "abc"
-          text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,198) size 784x54
-        LayoutBR {BR} at (0,0) size 0x18
-        LayoutText {#text} at (0,18) size 72x18
-          text run at (0,18) width 72: "3) No style"
-        LayoutBR {BR} at (71,32) size 1x0
-        LayoutMenuList {SELECT} at (0,36) size 100x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 100x18
-            LayoutText (anonymous) at (8,2) size 60x13
-              text run at (8,2) width 19: "abc"
-              text run at (26,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (100,49) size 0x0
-      LayoutBlockFlow {DIV} at (0,252) size 100x19
-        LayoutText {#text} at (0,1) size 82x18
-          text run at (0,1) width 23: "abc"
-          text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,271) size 784x18
-        LayoutBR {BR} at (0,0) size 0x18
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/menulist-width-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/menulist-width-rtl-expected.png
deleted file mode 100644
index 40bc23e0..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/menulist-width-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
deleted file mode 100644
index dc8cf4bd..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
deleted file mode 100644
index 2b2073d..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x530
-  LayoutBlockFlow {HTML} at (0,0) size 800x530
-    LayoutBlockFlow {BODY} at (8,16) size 784x506
-      LayoutBlockFlow {P} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 709x18
-          text run at (0,0) width 497: "Verify that the alignment and writing direction of each selected item matches "
-          text run at (496,0) width 213: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,34) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 188x18
-              text run at (8,1) width 37: "First "
-              text run at (44,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (102,1) width 19: "03"
-              text run at (120,1) width 44 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (163,1) width 33: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 32: "First "
-            text run at (41,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (89,10) width 17: "03"
-            text run at (105,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (141,10) width 32: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 188x18
-              text run at (8,1) width 28: "fifth"
-              text run at (35,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (98,1) width 19: "03"
-              text run at (116,1) width 48 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (163,1) width 33: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 27: "fifth"
-            text run at (36,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (87,10) width 17: "03"
-            text run at (103,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (144,10) width 29: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 188x18
-              text run at (8,1) width 188 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 188x18
-              text run at (8,1) width 188 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,270) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (294,1) size 188x18
-              text run at (294,1) width 37: "First "
-              text run at (330,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (388,1) width 19: "03"
-              text run at (406,1) width 45 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (450,1) width 32: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 33: "First "
-            text run at (329,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (376,10) width 18: "03"
-            text run at (393,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (429,10) width 31: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (294,1) size 188x18
-              text run at (294,1) width 28: "fifth"
-              text run at (321,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (384,1) width 19: "03"
-              text run at (402,1) width 49 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (450,1) width 32: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 28: "fifth"
-            text run at (324,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (375,10) width 17: "03"
-            text run at (391,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (432,10) width 28: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (294,1) size 188x18
-              text run at (294,1) width 188 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (294,1) size 188x18
-              text run at (294,1) width 188 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.png
index 3025082..448e9f44 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.txt
index 660a312b..fc04006 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/css/text-overflow-input-expected.txt
@@ -33,7 +33,7 @@
           text run at (123,37) width 4: " "
         LayoutTextControl {INPUT} at (127,37) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 117x13
-            LayoutBlockFlow {DIV} at (0,0) size 105x13
+            LayoutBlockFlow {DIV} at (12,0) size 105x13
         LayoutText {#text} at (252,37) size 4x18
           text run at (252,37) width 4: " "
         LayoutTextControl {INPUT} at (256,37) size 123x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -41,7 +41,7 @@
           text run at (379,37) width 4: " "
         LayoutTextControl {INPUT} at (383,37) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 117x13
-            LayoutBlockFlow {DIV} at (0,0) size 105x13
+            LayoutBlockFlow {DIV} at (12,0) size 105x13
         LayoutText {#text} at (508,37) size 4x18
           text run at (508,37) width 4: " "
         LayoutTextControl {INPUT} at (512,37) size 123x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -73,7 +73,7 @@
           text run at (123,37) width 4: " "
         LayoutTextControl {INPUT} at (127,37) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 117x13
-            LayoutBlockFlow {DIV} at (0,0) size 105x13
+            LayoutBlockFlow {DIV} at (12,0) size 105x13
         LayoutText {#text} at (252,37) size 4x18
           text run at (252,37) width 4: " "
         LayoutTextControl {INPUT} at (256,37) size 123x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -81,7 +81,7 @@
           text run at (379,37) width 4: " "
         LayoutTextControl {INPUT} at (383,37) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 117x13
-            LayoutBlockFlow {DIV} at (0,0) size 105x13
+            LayoutBlockFlow {DIV} at (12,0) size 105x13
         LayoutText {#text} at (508,37) size 4x18
           text run at (508,37) width 4: " "
         LayoutTextControl {INPUT} at (512,37) size 123x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -138,17 +138,17 @@
       text run at (-178,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (11,90) size 117x13
   LayoutBlockFlow {DIV} at (3,3) size 117x13
-layer at (139,90) size 105x13 scrollX 190.00 scrollWidth 295
-  LayoutBlockFlow {DIV} at (4,3) size 105x13 [color=#A9A9A9]
+layer at (151,90) size 105x13 scrollX 190.00 scrollWidth 295
+  LayoutBlockFlow {DIV} at (16,3) size 105x13 [color=#A9A9A9]
     LayoutText {#text} at (-190,0) size 296x13
       text run at (-190,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (139,90) size 105x13
+layer at (151,90) size 105x13
   LayoutBlockFlow {DIV} at (0,0) size 105x13
 layer at (267,90) size 117x13 scrollX 178.00 scrollWidth 295
   LayoutBlockFlow {DIV} at (3,3) size 117x13
     LayoutText {#text} at (-178,0) size 296x13
       text run at (-178,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (395,90) size 105x13 scrollX 190.00 scrollWidth 295
+layer at (407,90) size 105x13 scrollX 190.00 scrollWidth 295
   LayoutBlockFlow {DIV} at (0,0) size 105x13
     LayoutText {#text} at (-190,0) size 296x13
       text run at (-190,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
@@ -186,17 +186,17 @@
       text run at (-178,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (11,162) size 117x13
   LayoutBlockFlow {DIV} at (3,3) size 117x13
-layer at (139,162) size 105x13 scrollX 190.00 scrollWidth 295
-  LayoutBlockFlow {DIV} at (4,3) size 105x13 [color=#A9A9A9]
+layer at (151,162) size 105x13 scrollX 190.00 scrollWidth 295
+  LayoutBlockFlow {DIV} at (16,3) size 105x13 [color=#A9A9A9]
     LayoutText {#text} at (-190,0) size 296x13
       text run at (-190,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (139,162) size 105x13
+layer at (151,162) size 105x13
   LayoutBlockFlow {DIV} at (0,0) size 105x13
 layer at (267,162) size 117x13 scrollX 178.00 scrollWidth 295
   LayoutBlockFlow {DIV} at (3,3) size 117x13
     LayoutText {#text} at (-178,0) size 296x13
       text run at (-178,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (395,162) size 105x13 scrollX 190.00 scrollWidth 295
+layer at (407,162) size 105x13 scrollX 190.00 scrollWidth 295
   LayoutBlockFlow {DIV} at (0,0) size 105x13
     LayoutText {#text} at (-190,0) size 296x13
       text run at (-190,0) width 295: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
@@ -228,15 +228,15 @@
   LayoutBlockFlow {DIV} at (106,1) size 11x11
 layer at (501,72) size 11x11 transparent
   LayoutBlockFlow {DIV} at (106,1) size 11x11
-layer at (245,91) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (106,1) size 11x11
-layer at (501,91) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (106,1) size 11x11
+layer at (139,91) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (395,91) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
 layer at (245,144) size 11x11 transparent
   LayoutBlockFlow {DIV} at (106,1) size 11x11
 layer at (501,144) size 11x11 transparent
   LayoutBlockFlow {DIV} at (106,1) size 11x11
-layer at (245,163) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (106,1) size 11x11
-layer at (501,163) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (106,1) size 11x11
+layer at (139,163) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (395,163) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png
index 9a62e8d7..0c1e002 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/color/input-appearance-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png
index 2c5625c..6cec8b1 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.txt
index 150fb9b..3f2220a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/placeholder-position-expected.txt
@@ -21,7 +21,7 @@
       LayoutBR {BR} at (281,33) size 0x0
       LayoutTextControl {INPUT} at (0,38) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (4,3) size 117x13
-          LayoutBlockFlow {DIV} at (0,0) size 105x13
+          LayoutBlockFlow {DIV} at (12,0) size 105x13
       LayoutBR {BR} at (125,52) size 0x0
       LayoutTextControl {INPUT} at (0,57) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (4,3) size 117x13
@@ -84,11 +84,11 @@
       text run at (0,2) width 96: "\x{65E5}\x{672C}\x{8A9E}placeholder"
 layer at (165,30) size 117x13
   LayoutBlockFlow {DIV} at (3,3) size 117x13
-layer at (12,49) size 105x13
-  LayoutBlockFlow {DIV} at (4,3) size 105x13 [color=#A9A9A9]
+layer at (24,49) size 105x13
+  LayoutBlockFlow {DIV} at (16,3) size 105x13 [color=#A9A9A9]
     LayoutText {#text} at (42,0) size 63x13
       text run at (42,0) width 63: "placeholder"
-layer at (12,49) size 105x13
+layer at (24,49) size 105x13
   LayoutBlockFlow {DIV} at (0,0) size 105x13
 layer at (12,68) size 105x13
   LayoutBlockFlow {DIV} at (4,3) size 105x13 [color=#A9A9A9]
@@ -166,8 +166,8 @@
   LayoutBlockFlow {DIV} at (3,3) size 117x13
 layer at (118,12) size 11x11 transparent
   LayoutBlockFlow {DIV} at (106,1) size 11x11
-layer at (118,50) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (106,1) size 11x11
+layer at (12,50) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
 layer at (118,69) size 11x11 transparent
   LayoutBlockFlow {DIV} at (106,1) size 11x11
 layer at (8,284) size 123x33
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.png
index f9b2f6b..dfc1b0a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.txt
index 3f336ea3..dcb508d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/search/search-rtl-expected.txt
@@ -18,24 +18,24 @@
       LayoutBlockFlow {P} at (0,34) size 784x57
         LayoutTextControl {INPUT} at (0,0) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 117x13
-            LayoutBlockFlow {DIV} at (0,0) size 105x13
+            LayoutBlockFlow {DIV} at (12,0) size 105x13
         LayoutText {#text} at (125,0) size 4x18
           text run at (125,0) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,19) size 175x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 167x13
-            LayoutBlockFlow {DIV} at (0,0) size 155x13
+            LayoutBlockFlow {DIV} at (12,0) size 155x13
         LayoutText {#text} at (175,19) size 4x18
           text run at (175,19) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,38) size 125x19 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (4,3) size 117x13
-            LayoutBlockFlow {DIV} at (0,0) size 105x13
+            LayoutBlockFlow {DIV} at (12,0) size 105x13
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {P} at (0,107) size 784x18
         LayoutText {#text} at (0,0) size 37x18
           text run at (0,0) width 37: "PASS"
-layer at (12,45) size 105x13 scrollX 29.00 scrollWidth 135
+layer at (24,45) size 105x13 scrollX 29.00 scrollWidth 135
   LayoutBlockFlow {DIV} at (0,0) size 105x13
     LayoutText {#text} at (-29,0) size 135x13
       text run at (-29,0) width 22 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
@@ -43,7 +43,7 @@
       text run at (11,0) width 45 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
       text run at (55,0) width 14: "he"
       text run at (68,0) width 37 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (12,64) size 155x13
+layer at (24,64) size 155x13
   LayoutBlockFlow {DIV} at (0,0) size 155x13
     LayoutText {#text} at (20,0) size 135x13
       text run at (20,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
@@ -51,12 +51,12 @@
       text run at (61,0) width 45 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
       text run at (105,0) width 14: "he"
       text run at (118,0) width 37 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (12,83) size 105x13
+layer at (24,83) size 105x13
   LayoutBlockFlow {DIV} at (0,0) size 105x13
-layer at (118,46) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (106,1) size 11x11
-layer at (168,65) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (156,1) size 11x11
-layer at (118,84) size 11x11 transparent
-  LayoutBlockFlow {DIV} at (106,1) size 11x11
+layer at (12,46) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (12,65) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
+layer at (12,84) size 11x11 transparent
+  LayoutBlockFlow {DIV} at (0,1) size 11x11
 caret: position 0 of child 0 {DIV} of child 0 {DIV} of child 0 {DIV} of {#document-fragment} of child 9 {INPUT} of child 3 {P} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png
index e099a09..67ae39d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt
index 2e1cd2c..1125f17 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-basic-expected.txt
@@ -123,31 +123,31 @@
       LayoutText {#text} at (68,409) size 4x18
         text run at (68,409) width 4: " "
       LayoutBR {BR} at (72,409) size 0x18
-      LayoutMenuList {SELECT} at (4,443) size 49x18 [bgcolor=#F8F8F8]
-        LayoutBlockFlow (anonymous) at (0,0) size 49x18
-          LayoutText (anonymous) at (8,2) size 18x13
-            text run at (8,2) width 18: "foo"
-      LayoutText {#text} at (57,442) size 4x18
-        text run at (57,442) width 4: " "
-      LayoutMenuList {SELECT} at (65,441) size 45x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
-        LayoutBlockFlow (anonymous) at (3,3) size 39x16
-          LayoutText (anonymous) at (8,1) size 18x13
-            text run at (8,1) width 18: "foo"
-      LayoutText {#text} at (114,442) size 4x18
-        text run at (114,442) width 4: " "
-      LayoutMenuList {SELECT} at (122,436) size 55x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
-        LayoutBlockFlow (anonymous) at (8,8) size 39x16
-          LayoutText (anonymous) at (8,1) size 18x13
-            text run at (8,1) width 18: "foo"
-      LayoutText {#text} at (181,442) size 4x18
-        text run at (181,442) width 4: " "
-      LayoutMenuList {SELECT} at (189,443) size 41x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+      LayoutMenuList {SELECT} at (4,443) size 41x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 39x16
-          LayoutText (anonymous) at (8,1) size 18x13
-            text run at (8,1) width 18: "foo"
-      LayoutText {#text} at (234,442) size 4x18
-        text run at (234,442) width 4: " "
-      LayoutBR {BR} at (238,442) size 0x18
+          LayoutText (anonymous) at (13,1) size 18x13
+            text run at (13,1) width 18: "foo"
+      LayoutText {#text} at (49,442) size 4x18
+        text run at (49,442) width 4: " "
+      LayoutMenuList {SELECT} at (57,441) size 45x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
+        LayoutBlockFlow (anonymous) at (3,3) size 39x16
+          LayoutText (anonymous) at (13,1) size 18x13
+            text run at (13,1) width 18: "foo"
+      LayoutText {#text} at (106,442) size 4x18
+        text run at (106,442) width 4: " "
+      LayoutMenuList {SELECT} at (114,436) size 55x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
+        LayoutBlockFlow (anonymous) at (8,8) size 39x16
+          LayoutText (anonymous) at (13,1) size 18x13
+            text run at (13,1) width 18: "foo"
+      LayoutText {#text} at (173,442) size 4x18
+        text run at (173,442) width 4: " "
+      LayoutMenuList {SELECT} at (181,443) size 41x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 39x16
+          LayoutText (anonymous) at (13,1) size 18x13
+            text run at (13,1) width 18: "foo"
+      LayoutText {#text} at (226,442) size 4x18
+        text run at (226,442) width 4: " "
+      LayoutBR {BR} at (230,442) size 0x18
 layer at (12,253) size 200x25 clip at (13,254) size 187x23 scrollHeight 43
   LayoutListBox {SELECT} at (4,245) size 200x25 [bgcolor=#FFFFFF] [border: (1px solid #999999)]
     LayoutBlockFlow {OPTION} at (1,1) size 187x14.19
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-rtl-expected.png
new file mode 100644
index 0000000..abb3ae10
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-rtl-expected.txt
new file mode 100644
index 0000000..2c9b570
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -0,0 +1,168 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x549
+  LayoutBlockFlow {HTML} at (0,0) size 800x549
+    LayoutBlockFlow {BODY} at (8,16) size 784x525
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 758x36
+          text run at (0,0) width 758: "This tests that bidirectional text is correctly rendered in popup controls. The order of the text below each popup button"
+          text run at (0,18) width 600: "should match the order of the select's option text, and the order of the text in the popup menu."
+      LayoutBlockFlow {DL} at (0,52) size 784x168
+        LayoutBlockFlow {DT} at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 286x18
+            text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
+        LayoutBlockFlow {DD} at (40,18) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 100x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+              LayoutBlockFlow (anonymous) at (1,1) size 98x16
+                LayoutText (anonymous) at (30,1) size 60x13
+                  text run at (30,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+                  text run at (71,1) width 19: "abc"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 100x19
+            LayoutText {#text} at (18,1) size 82x18
+              text run at (18,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+              text run at (77,1) width 23: "abc"
+        LayoutBlockFlow {DT} at (0,56) size 784x18
+          LayoutText {#text} at (0,0) size 118x18
+            text run at (0,0) width 118: "2) text-align: right"
+        LayoutBlockFlow {DD} at (40,74) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 200x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 200x18
+                LayoutText (anonymous) at (8,2) size 60x13
+                  text run at (8,2) width 19: "abc"
+                  text run at (26,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 200x19
+            LayoutText {#text} at (0,1) size 82x18
+              text run at (0,1) width 23: "abc"
+              text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+        LayoutBlockFlow {DT} at (0,112) size 784x18
+          LayoutText {#text} at (0,0) size 72x18
+            text run at (0,0) width 72: "3) No style"
+        LayoutBlockFlow {DD} at (40,130) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 100x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 100x18
+                LayoutText (anonymous) at (8,2) size 60x13
+                  text run at (8,2) width 19: "abc"
+                  text run at (26,2) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 100x19
+            LayoutText {#text} at (0,1) size 82x18
+              text run at (0,1) width 23: "abc"
+              text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+      LayoutBlockFlow {HR} at (0,236) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {DIV} at (0,246) size 784x55
+        LayoutBlockFlow (anonymous) at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 632x18
+            text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
+        LayoutBlockFlow {DIV} at (0,18) size 784x18
+          LayoutText {#text} at (0,0) size 102x16
+            text run at (0,0) width 102 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+        LayoutBlockFlow (anonymous) at (0,36) size 784x19
+          LayoutMenuList {SELECT} at (0,1) size 118x18 [bgcolor=#F8F8F8]
+            LayoutBlockFlow (anonymous) at (0,0) size 118x21
+              LayoutText (anonymous) at (8,2) size 79x13
+                text run at (8,2) width 79 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+          LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {HR} at (0,309) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {P} at (0,327) size 784x18
+        LayoutText {#text} at (0,0) size 709x18
+          text run at (0,0) width 709: "Verify that the alignment and writing direction of each selected item matches the one below the pop-up button."
+layer at (8,377) size 784x164
+  LayoutBlockFlow {DIV} at (0,361) size 784x164
+    LayoutMultiColumnSet (anonymous) at (0,0) size 784x164
+layer at (8,377) size 384x328 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
+  LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x328
+    LayoutBlockFlow {DIV} at (0,0) size 384x164
+      LayoutMenuList {SELECT} at (0,0) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 200x18
+            text run at (8,1) width 39: "First "
+            text run at (46,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (105,1) width 21: "03"
+            text run at (125,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (170,1) width 38: " fifth"
+      LayoutBlockFlow {DIV} at (0,23) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 32: "First "
+          text run at (32,1) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (80,1) width 17: "03"
+          text run at (96,1) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (132,1) width 32: " fifth"
+      LayoutMenuList {SELECT} at (0,41) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 200x18
+            text run at (8,1) width 33: "fifth"
+            text run at (40,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (103,1) width 21: "03"
+            text run at (123,1) width 51 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (173,1) width 35: "First"
+      LayoutBlockFlow {DIV} at (0,64) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 27: "fifth"
+          text run at (27,1) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (78,1) width 17: "03"
+          text run at (94,1) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (135,1) width 29: "First"
+      LayoutMenuList {SELECT} at (0,82) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 200x18
+            text run at (8,1) width 200 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,105) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,123) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 200x18
+            text run at (8,1) width 200 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,146) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+    LayoutBlockFlow {DIV} at (0,164) size 384x164
+      LayoutMenuList {SELECT} at (0,0) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (140,1) size 200x18
+            text run at (140,1) width 40: "First "
+            text run at (179,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (237,1) width 22: "03"
+            text run at (258,1) width 45 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (302,1) width 38: " fifth"
+      LayoutBlockFlow {DIV} at (0,23) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 33: "First "
+          text run at (220,1) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (267,1) width 18: "03"
+          text run at (284,1) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (320,1) width 31: " fifth"
+      LayoutMenuList {SELECT} at (0,41) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (140,1) size 200x18
+            text run at (140,1) width 33: "fifth"
+            text run at (172,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (236,1) width 21: "03"
+            text run at (256,1) width 51 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (306,1) width 34: "First"
+      LayoutBlockFlow {DIV} at (0,64) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 28: "fifth"
+          text run at (215,1) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (266,1) width 17: "03"
+          text run at (282,1) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (323,1) width 28: "First"
+      LayoutMenuList {SELECT} at (0,82) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (140,1) size 200x18
+            text run at (140,1) width 200 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,105) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,123) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (140,1) size 200x18
+            text run at (140,1) width 200 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,146) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.png
index 11755b0..c4f7549 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.txt
index 525bcd40..bf10454 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/select-writing-direction-natural-expected.txt
@@ -82,60 +82,60 @@
           LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {DIV} at (0,125) size 784x38
         LayoutBlockFlow {DIV} at (0,0) size 784x19
-          LayoutMenuList {SELECT} at (222,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8: "A"
-                text run at (39,2) width 8 RTL: "\x{5D0}"
+          LayoutMenuList {SELECT} at (222,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (45,1) size 15x13
+                text run at (45,1) width 8: "A"
+                text run at (52,1) width 8 RTL: "\x{5D0}"
           LayoutText {#text} at (218,0) size 4x18
             text run at (218,0) width 4 RTL: " "
-          LayoutMenuList {SELECT} at (148,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8 RTL: "\x{5D0}"
-                text run at (39,2) width 8: "A"
+          LayoutMenuList {SELECT} at (148,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (45,1) size 15x13
+                text run at (45,1) width 8 RTL: "\x{5D0}"
+                text run at (52,1) width 8: "A"
           LayoutText {#text} at (144,0) size 4x18
             text run at (144,0) width 4 RTL: " "
-          LayoutMenuList {SELECT} at (74,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 9: "A"
-                text run at (36,2) width 11 RTL: "(\x{5D0}"
+          LayoutMenuList {SELECT} at (74,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (41,1) size 19x13
+                text run at (41,1) width 9: "A"
+                text run at (49,1) width 11 RTL: "(\x{5D0}"
           LayoutText {#text} at (70,0) size 4x18
             text run at (70,0) width 4 RTL: " "
-          LayoutMenuList {SELECT} at (0,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 8 RTL: "\x{5D0}"
-                text run at (35,2) width 9: "A"
-                text run at (43,2) width 4 RTL: "("
+          LayoutMenuList {SELECT} at (0,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (41,1) size 19x13
+                text run at (41,1) width 8 RTL: "\x{5D0}"
+                text run at (48,1) width 9: "A"
+                text run at (56,1) width 4 RTL: "("
           LayoutText {#text} at (0,0) size 0x0
         LayoutBlockFlow {DIV} at (0,19) size 784x19
-          LayoutMenuList {SELECT} at (714,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8: "A"
-                text run at (39,2) width 8 RTL: "\x{5D0}"
+          LayoutMenuList {SELECT} at (714,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (45,1) size 15x13
+                text run at (45,1) width 8: "A"
+                text run at (52,1) width 8 RTL: "\x{5D0}"
           LayoutText {#text} at (710,0) size 4x18
             text run at (710,0) width 4 RTL: " "
-          LayoutMenuList {SELECT} at (640,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8 RTL: "\x{5D0}"
-                text run at (39,2) width 8: "A"
+          LayoutMenuList {SELECT} at (640,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (45,1) size 15x13
+                text run at (45,1) width 8 RTL: "\x{5D0}"
+                text run at (52,1) width 8: "A"
           LayoutText {#text} at (636,0) size 4x18
             text run at (636,0) width 4 RTL: " "
-          LayoutMenuList {SELECT} at (566,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 9: "A"
-                text run at (36,2) width 11 RTL: "(\x{5D0}"
+          LayoutMenuList {SELECT} at (566,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (41,1) size 19x13
+                text run at (41,1) width 9: "A"
+                text run at (49,1) width 11 RTL: "(\x{5D0}"
           LayoutText {#text} at (562,0) size 4x18
             text run at (562,0) width 4 RTL: " "
-          LayoutMenuList {SELECT} at (492,1) size 70x18 [bgcolor=#F8F8F8]
-            LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 8 RTL: "\x{5D0}"
-                text run at (35,2) width 9: "A"
-                text run at (43,2) width 4 RTL: "("
+          LayoutMenuList {SELECT} at (492,1) size 70x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+            LayoutBlockFlow (anonymous) at (1,1) size 68x16
+              LayoutText (anonymous) at (41,1) size 19x13
+                text run at (41,1) width 8 RTL: "\x{5D0}"
+                text run at (48,1) width 9: "A"
+                text run at (56,1) width 4 RTL: "("
           LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/bidi-menulist-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/bidi-menulist-expected.png
deleted file mode 100644
index 1cd1129..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/bidi-menulist-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/menulist-width-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/menulist-width-rtl-expected.png
deleted file mode 100644
index 55ad28b..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/menulist-width-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/menulist-width-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/menulist-width-rtl-expected.txt
deleted file mode 100644
index 256d8b0..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/menulist-width-rtl-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x71
-  LayoutBlockFlow {HTML} at (0,0) size 800x71
-    LayoutBlockFlow {BODY} at (8,8) size 784x55
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 632x18
-          text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
-      LayoutBlockFlow {DIV} at (0,18) size 784x18
-        LayoutText {#text} at (682,0) size 102x16
-          text run at (682,0) width 102 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-      LayoutBlockFlow (anonymous) at (0,36) size 784x19
-        LayoutMenuList {SELECT} at (666,1) size 118x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 118x21
-            LayoutText (anonymous) at (8,2) size 87x13
-              text run at (8,2) width 87 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
deleted file mode 100644
index 4e2f75f..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
deleted file mode 100644
index d7f9069..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x530
-  LayoutBlockFlow {HTML} at (0,0) size 800x530
-    LayoutBlockFlow {BODY} at (8,16) size 784x506
-      LayoutBlockFlow {P} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 709x18
-          text run at (0,0) width 497: "Verify that the alignment and writing direction of each selected item matches "
-          text run at (496,0) width 213: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,34) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 200x18
-              text run at (8,1) width 39: "First "
-              text run at (46,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (105,1) width 21: "03"
-              text run at (125,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (170,1) width 38: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 32: "First "
-            text run at (41,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (89,10) width 17: "03"
-            text run at (105,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (141,10) width 32: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 200x18
-              text run at (8,1) width 33: "fifth"
-              text run at (40,1) width 64 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (103,1) width 21: "03"
-              text run at (123,1) width 51 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (173,1) width 35: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 27: "fifth"
-            text run at (36,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (87,10) width 17: "03"
-            text run at (103,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (144,10) width 29: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 200x18
-              text run at (8,1) width 200 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 200x18
-              text run at (8,1) width 200 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,270) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (282,1) size 200x18
-              text run at (282,1) width 40: "First "
-              text run at (321,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (379,1) width 22: "03"
-              text run at (400,1) width 45 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (444,1) width 38: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 33: "First "
-            text run at (329,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (376,10) width 18: "03"
-            text run at (393,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (429,10) width 31: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (282,1) size 200x18
-              text run at (282,1) width 33: "fifth"
-              text run at (314,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (378,1) width 21: "03"
-              text run at (398,1) width 51 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (448,1) width 34: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 28: "fifth"
-            text run at (324,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (375,10) width 17: "03"
-            text run at (391,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (432,10) width 28: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (282,1) size 200x18
-              text run at (282,1) width 200 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (282,1) size 200x18
-              text run at (282,1) width 200 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png
index 6786dd0..466a899 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt
index 253e2498..cc65e50e 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/color/input-appearance-color-expected.txt
@@ -146,4 +146,14 @@
         LayoutBlockFlow {INPUT} at (188,0) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #00FF00)]
           LayoutFlexibleBox {DIV} at (1,1) size 86x21
             LayoutBlockFlow {DIV} at (8,4) size 54x13 [bgcolor=#FF0000] [border: (1px solid #000000)]
+        LayoutText {#text} at (276,3) size 4x18
+          text run at (276,3) width 4: " "
+        LayoutBlockFlow {INPUT} at (280,0) size 44x23 [bgcolor=#C0C0C0] [border: none (1px solid #A9A9A9) none (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,1) size 38x21
+            LayoutBlockFlow {DIV} at (2,4) size 34x13 [bgcolor=#40E0D0] [border: (1px solid #777777)]
+        LayoutText {#text} at (324,3) size 4x18
+          text run at (324,3) width 4: " "
+        LayoutBlockFlow {INPUT} at (328,0) size 88x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+          LayoutFlexibleBox {DIV} at (1,1) size 86x21
+            LayoutBlockFlow {DIV} at (24,4) size 54x13 [bgcolor=#FF0000] [border: (1px solid #000000)]
         LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png
index 7aadfa1..b1c334b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt
index bc2f9adf..0be68d26 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-basic-expected.txt
@@ -125,26 +125,26 @@
       LayoutBR {BR} at (72,409) size 0x18
       LayoutMenuList {SELECT} at (4,443) size 48x18 [bgcolor=#F8F8F8]
         LayoutBlockFlow (anonymous) at (0,0) size 48x18
-          LayoutText (anonymous) at (8,2) size 17x13
-            text run at (8,2) width 17: "foo"
+          LayoutText (anonymous) at (23,2) size 17x13
+            text run at (23,2) width 17: "foo"
       LayoutText {#text} at (56,442) size 4x18
         text run at (56,442) width 4: " "
       LayoutMenuList {SELECT} at (64,441) size 44x22 [bgcolor=#F8F8F8] [border: (3px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (3,3) size 38x16
-          LayoutText (anonymous) at (8,1) size 17x13
-            text run at (8,1) width 17: "foo"
+          LayoutText (anonymous) at (13,1) size 17x13
+            text run at (13,1) width 17: "foo"
       LayoutText {#text} at (112,442) size 4x18
         text run at (112,442) width 4: " "
       LayoutMenuList {SELECT} at (120,436) size 54x32 [bgcolor=#F8F8F8] [border: (8px solid #00FF00)]
         LayoutBlockFlow (anonymous) at (8,8) size 38x16
-          LayoutText (anonymous) at (8,1) size 17x13
-            text run at (8,1) width 17: "foo"
+          LayoutText (anonymous) at (13,1) size 17x13
+            text run at (13,1) width 17: "foo"
       LayoutText {#text} at (178,442) size 4x18
         text run at (178,442) width 4: " "
       LayoutMenuList {SELECT} at (186,443) size 40x18 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
         LayoutBlockFlow (anonymous) at (1,1) size 38x16
-          LayoutText (anonymous) at (8,1) size 17x13
-            text run at (8,1) width 17: "foo"
+          LayoutText (anonymous) at (13,1) size 17x13
+            text run at (13,1) width 17: "foo"
       LayoutText {#text} at (230,442) size 4x18
         text run at (230,442) width 4: " "
       LayoutBR {BR} at (234,442) size 0x18
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-rtl-expected.png
new file mode 100644
index 0000000..22dabf4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-rtl-expected.txt
new file mode 100644
index 0000000..ed835d3f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -0,0 +1,168 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x549
+  LayoutBlockFlow {HTML} at (0,0) size 800x549
+    LayoutBlockFlow {BODY} at (8,16) size 784x525
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 758x36
+          text run at (0,0) width 758: "This tests that bidirectional text is correctly rendered in popup controls. The order of the text below each popup button"
+          text run at (0,18) width 600: "should match the order of the select's option text, and the order of the text in the popup menu."
+      LayoutBlockFlow {DL} at (0,52) size 784x168
+        LayoutBlockFlow {DT} at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 286x18
+            text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
+        LayoutBlockFlow {DD} at (40,18) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 100x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 100x18
+                LayoutText (anonymous) at (31,2) size 61x13
+                  text run at (31,2) width 43 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+                  text run at (73,2) width 19: "abc"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 100x19
+            LayoutText {#text} at (18,1) size 82x18
+              text run at (18,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+              text run at (77,1) width 23: "abc"
+        LayoutBlockFlow {DT} at (0,56) size 784x18
+          LayoutText {#text} at (0,0) size 118x18
+            text run at (0,0) width 118: "2) text-align: right"
+        LayoutBlockFlow {DD} at (40,74) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 200x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 200x18
+                LayoutText (anonymous) at (8,2) size 61x13
+                  text run at (8,2) width 19: "abc"
+                  text run at (26,2) width 43 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 200x19
+            LayoutText {#text} at (0,1) size 82x18
+              text run at (0,1) width 23: "abc"
+              text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+        LayoutBlockFlow {DT} at (0,112) size 784x18
+          LayoutText {#text} at (0,0) size 72x18
+            text run at (0,0) width 72: "3) No style"
+        LayoutBlockFlow {DD} at (40,130) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x19
+            LayoutMenuList {SELECT} at (0,1) size 100x18 [bgcolor=#F8F8F8]
+              LayoutBlockFlow (anonymous) at (0,0) size 100x18
+                LayoutText (anonymous) at (8,2) size 61x13
+                  text run at (8,2) width 19: "abc"
+                  text run at (26,2) width 43 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,19) size 100x19
+            LayoutText {#text} at (0,1) size 82x18
+              text run at (0,1) width 23: "abc"
+              text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+      LayoutBlockFlow {HR} at (0,236) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {DIV} at (0,246) size 784x55
+        LayoutBlockFlow (anonymous) at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 632x18
+            text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
+        LayoutBlockFlow {DIV} at (0,18) size 784x18
+          LayoutText {#text} at (0,0) size 99x16
+            text run at (0,0) width 99 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+        LayoutBlockFlow (anonymous) at (0,36) size 784x19
+          LayoutMenuList {SELECT} at (0,1) size 115x18 [bgcolor=#F8F8F8]
+            LayoutBlockFlow (anonymous) at (0,0) size 115x21
+              LayoutText (anonymous) at (8,2) size 76x13
+                text run at (8,2) width 76 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+          LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {HR} at (0,309) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {P} at (0,327) size 784x18
+        LayoutText {#text} at (0,0) size 709x18
+          text run at (0,0) width 709: "Verify that the alignment and writing direction of each selected item matches the one below the pop-up button."
+layer at (8,377) size 784x164
+  LayoutBlockFlow {DIV} at (0,361) size 784x164
+    LayoutMultiColumnSet (anonymous) at (0,0) size 784x164
+layer at (8,377) size 384x328 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
+  LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x328
+    LayoutBlockFlow {DIV} at (0,0) size 384x164
+      LayoutMenuList {SELECT} at (0,0) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 198x18
+            text run at (8,1) width 38: "First "
+            text run at (45,1) width 61 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (105,1) width 21: "03"
+            text run at (125,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (170,1) width 36: " fifth"
+      LayoutBlockFlow {DIV} at (0,23) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 32: "First "
+          text run at (32,1) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (80,1) width 17: "03"
+          text run at (96,1) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (132,1) width 32: " fifth"
+      LayoutMenuList {SELECT} at (0,41) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 198x18
+            text run at (8,1) width 31: "fifth"
+            text run at (38,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (103,1) width 21: "03"
+            text run at (123,1) width 50 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (172,1) width 34: "First"
+      LayoutBlockFlow {DIV} at (0,64) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 27: "fifth"
+          text run at (27,1) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (78,1) width 17: "03"
+          text run at (94,1) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (135,1) width 29: "First"
+      LayoutMenuList {SELECT} at (0,82) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 198x18
+            text run at (8,1) width 198 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,105) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,123) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (8,1) size 198x18
+            text run at (8,1) width 198 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,146) size 352x18
+        LayoutText {#text} at (1,1) size 163x16
+          text run at (1,1) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+    LayoutBlockFlow {DIV} at (0,164) size 384x164
+      LayoutMenuList {SELECT} at (0,0) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (142,1) size 198x18
+            text run at (142,1) width 39: "First "
+            text run at (180,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (239,1) width 21: "03"
+            text run at (259,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (304,1) width 36: " fifth"
+      LayoutBlockFlow {DIV} at (0,23) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 33: "First "
+          text run at (220,1) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (267,1) width 18: "03"
+          text run at (284,1) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (320,1) width 31: " fifth"
+      LayoutMenuList {SELECT} at (0,41) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (142,1) size 198x18
+            text run at (142,1) width 32: "fifth"
+            text run at (173,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (237,1) width 21: "03"
+            text run at (257,1) width 50 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (306,1) width 34: "First"
+      LayoutBlockFlow {DIV} at (0,64) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 28: "fifth"
+          text run at (215,1) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (266,1) width 17: "03"
+          text run at (282,1) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (323,1) width 28: "First"
+      LayoutMenuList {SELECT} at (0,82) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (142,1) size 198x18
+            text run at (142,1) width 198 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,105) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,123) size 350x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x21
+          LayoutText (anonymous) at (142,1) size 198x18
+            text run at (142,1) width 198 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,146) size 352x18
+        LayoutText {#text} at (188,1) size 163x16
+          text run at (188,1) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.png
index da89f09..3ecf9020 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.txt
index 525bcd40..0c5d18d 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/select-writing-direction-natural-expected.txt
@@ -84,58 +84,58 @@
         LayoutBlockFlow {DIV} at (0,0) size 784x19
           LayoutMenuList {SELECT} at (222,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8: "A"
-                text run at (39,2) width 8 RTL: "\x{5D0}"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8: "A"
+                text run at (54,2) width 8 RTL: "\x{5D0}"
           LayoutText {#text} at (218,0) size 4x18
             text run at (218,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (148,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8 RTL: "\x{5D0}"
-                text run at (39,2) width 8: "A"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8 RTL: "\x{5D0}"
+                text run at (54,2) width 8: "A"
           LayoutText {#text} at (144,0) size 4x18
             text run at (144,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (74,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 9: "A"
-                text run at (36,2) width 11 RTL: "(\x{5D0}"
+              LayoutText (anonymous) at (43,2) size 19x13
+                text run at (43,2) width 9: "A"
+                text run at (51,2) width 11 RTL: "(\x{5D0}"
           LayoutText {#text} at (70,0) size 4x18
             text run at (70,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (0,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 8 RTL: "\x{5D0}"
-                text run at (35,2) width 9: "A"
-                text run at (43,2) width 4 RTL: "("
+              LayoutText (anonymous) at (43,2) size 19x13
+                text run at (43,2) width 8 RTL: "\x{5D0}"
+                text run at (50,2) width 9: "A"
+                text run at (58,2) width 4 RTL: "("
           LayoutText {#text} at (0,0) size 0x0
         LayoutBlockFlow {DIV} at (0,19) size 784x19
           LayoutMenuList {SELECT} at (714,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8: "A"
-                text run at (39,2) width 8 RTL: "\x{5D0}"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8: "A"
+                text run at (54,2) width 8 RTL: "\x{5D0}"
           LayoutText {#text} at (710,0) size 4x18
             text run at (710,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (640,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (32,2) size 15x13
-                text run at (32,2) width 8 RTL: "\x{5D0}"
-                text run at (39,2) width 8: "A"
+              LayoutText (anonymous) at (47,2) size 15x13
+                text run at (47,2) width 8 RTL: "\x{5D0}"
+                text run at (54,2) width 8: "A"
           LayoutText {#text} at (636,0) size 4x18
             text run at (636,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (566,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 9: "A"
-                text run at (36,2) width 11 RTL: "(\x{5D0}"
+              LayoutText (anonymous) at (43,2) size 19x13
+                text run at (43,2) width 9: "A"
+                text run at (51,2) width 11 RTL: "(\x{5D0}"
           LayoutText {#text} at (562,0) size 4x18
             text run at (562,0) width 4 RTL: " "
           LayoutMenuList {SELECT} at (492,1) size 70x18 [bgcolor=#F8F8F8]
             LayoutBlockFlow (anonymous) at (0,0) size 70x18
-              LayoutText (anonymous) at (28,2) size 19x13
-                text run at (28,2) width 8 RTL: "\x{5D0}"
-                text run at (35,2) width 9: "A"
-                text run at (43,2) width 4 RTL: "("
+              LayoutText (anonymous) at (43,2) size 19x13
+                text run at (43,2) width 8 RTL: "\x{5D0}"
+                text run at (50,2) width 9: "A"
+                text run at (58,2) width 4 RTL: "("
           LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/bidi-menulist-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/bidi-menulist-expected.png
deleted file mode 100644
index a17f1edd..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/bidi-menulist-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/bidi-menulist-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/bidi-menulist-expected.txt
deleted file mode 100644
index d82b1a8..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/bidi-menulist-expected.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x54
-        LayoutText {#text} at (0,0) size 458x18
-          text run at (0,0) width 458: "This tests that bidirectional text is correctly rendered in popup controls."
-        LayoutBR {BR} at (457,14) size 1x0
-        LayoutText {#text} at (0,18) size 773x36
-          text run at (0,18) width 773: "The order of the text below each popup button should match the order of the select's option text, and the order of the text"
-          text run at (0,36) width 124: "in the popup menu."
-      LayoutBlockFlow (anonymous) at (0,70) size 784x36
-        LayoutText {#text} at (0,0) size 286x18
-          text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
-        LayoutBR {BR} at (285,14) size 1x0
-        LayoutMenuList {SELECT} at (0,18) size 100x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 100x18
-            LayoutText (anonymous) at (16,2) size 61x13
-              text run at (16,2) width 43 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-              text run at (58,2) width 19: "abc"
-        LayoutBR {BR} at (100,31) size 0x0
-      LayoutBlockFlow {DIV} at (0,106) size 100x19
-        LayoutText {#text} at (0,1) size 82x18
-          text run at (0,1) width 23: "abc"
-          text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,125) size 784x54
-        LayoutBR {BR} at (0,0) size 0x18
-        LayoutText {#text} at (0,18) size 118x18
-          text run at (0,18) width 118: "2) text-align: right"
-        LayoutBR {BR} at (117,32) size 1x0
-        LayoutMenuList {SELECT} at (0,36) size 200x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 200x18
-            LayoutText (anonymous) at (8,2) size 61x13
-              text run at (8,2) width 19: "abc"
-              text run at (26,2) width 43 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (200,49) size 0x0
-      LayoutBlockFlow {DIV} at (0,179) size 200x19
-        LayoutText {#text} at (0,1) size 82x18
-          text run at (0,1) width 23: "abc"
-          text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,198) size 784x54
-        LayoutBR {BR} at (0,0) size 0x18
-        LayoutText {#text} at (0,18) size 72x18
-          text run at (0,18) width 72: "3) No style"
-        LayoutBR {BR} at (71,32) size 1x0
-        LayoutMenuList {SELECT} at (0,36) size 100x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 100x18
-            LayoutText (anonymous) at (8,2) size 61x13
-              text run at (8,2) width 19: "abc"
-              text run at (26,2) width 43 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (100,49) size 0x0
-      LayoutBlockFlow {DIV} at (0,252) size 100x19
-        LayoutText {#text} at (0,1) size 82x18
-          text run at (0,1) width 23: "abc"
-          text run at (22,1) width 60 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,271) size 784x18
-        LayoutBR {BR} at (0,0) size 0x18
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/menulist-width-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/menulist-width-rtl-expected.png
deleted file mode 100644
index 6bc4fa3..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/menulist-width-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/menulist-width-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/menulist-width-rtl-expected.txt
deleted file mode 100644
index f63e8a32..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/menulist-width-rtl-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x71
-  LayoutBlockFlow {HTML} at (0,0) size 800x71
-    LayoutBlockFlow {BODY} at (8,8) size 784x55
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 632x18
-          text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
-      LayoutBlockFlow {DIV} at (0,18) size 784x18
-        LayoutText {#text} at (685,0) size 99x16
-          text run at (685,0) width 99 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-      LayoutBlockFlow (anonymous) at (0,36) size 784x19
-        LayoutMenuList {SELECT} at (669,1) size 115x18 [bgcolor=#F8F8F8]
-          LayoutBlockFlow (anonymous) at (0,0) size 115x21
-            LayoutText (anonymous) at (8,2) size 84x13
-              text run at (8,2) width 84 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
deleted file mode 100644
index ee5e71bb..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
deleted file mode 100644
index d015cef0..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x530
-  LayoutBlockFlow {HTML} at (0,0) size 800x530
-    LayoutBlockFlow {BODY} at (8,16) size 784x506
-      LayoutBlockFlow {P} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 709x18
-          text run at (0,0) width 497: "Verify that the alignment and writing direction of each selected item matches "
-          text run at (496,0) width 213: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,34) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 198x18
-              text run at (8,1) width 38: "First "
-              text run at (45,1) width 61 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (105,1) width 21: "03"
-              text run at (125,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (170,1) width 36: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 32: "First "
-            text run at (41,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (89,10) width 17: "03"
-            text run at (105,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (141,10) width 32: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 198x18
-              text run at (8,1) width 31: "fifth"
-              text run at (38,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (103,1) width 21: "03"
-              text run at (123,1) width 50 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (172,1) width 34: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 27: "fifth"
-            text run at (36,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (87,10) width 17: "03"
-            text run at (103,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (144,10) width 29: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 198x18
-              text run at (8,1) width 198 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (8,1) size 198x18
-              text run at (8,1) width 198 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (10,10) size 163x16
-            text run at (10,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,270) size 784x236
-        LayoutMenuList {SELECT} at (0,0) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (284,1) size 198x18
-              text run at (284,1) width 39: "First "
-              text run at (322,1) width 60 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (381,1) width 21: "03"
-              text run at (401,1) width 46 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (446,1) width 36: " fifth"
-        LayoutBlockFlow {DIV} at (0,23) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 33: "First "
-            text run at (329,10) width 48 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (376,10) width 18: "03"
-            text run at (393,10) width 37 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (429,10) width 31: " fifth"
-        LayoutMenuList {SELECT} at (0,59) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (284,1) size 198x18
-              text run at (284,1) width 32: "fifth"
-              text run at (315,1) width 65 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (379,1) width 21: "03"
-              text run at (399,1) width 50 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (448,1) width 34: "First"
-        LayoutBlockFlow {DIV} at (0,82) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 28: "fifth"
-            text run at (324,10) width 52 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (375,10) width 17: "03"
-            text run at (391,10) width 42 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (432,10) width 28: "First"
-        LayoutMenuList {SELECT} at (0,118) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (284,1) size 198x18
-              text run at (284,1) width 198 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,141) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 163 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,177) size 500x23 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x21
-            LayoutText (anonymous) at (284,1) size 198x18
-              text run at (284,1) width 198 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,200) size 470x36
-          LayoutText {#text} at (297,10) size 163x16
-            text run at (297,10) width 163 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.png
index 9d246ab..1d4e71b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.txt
index 3e02910..b8d78db 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/text-overflow-input-expected.txt
@@ -32,7 +32,7 @@
           text run at (173,64) width 4: " "
         LayoutTextControl {INPUT} at (177,62) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 169x16
-            LayoutBlockFlow {DIV} at (0,0) size 156x16
+            LayoutBlockFlow {DIV} at (12,0) size 157x16
         LayoutText {#text} at (352,64) size 4x17
           text run at (352,64) width 4: " "
         LayoutTextControl {INPUT} at (356,62) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -40,7 +40,7 @@
           text run at (529,64) width 4: " "
         LayoutTextControl {INPUT} at (533,62) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 169x16
-            LayoutBlockFlow {DIV} at (0,0) size 156x16
+            LayoutBlockFlow {DIV} at (12,0) size 157x16
         LayoutText {#text} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,84) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutText {#text} at (0,0) size 0x0
@@ -70,7 +70,7 @@
           text run at (173,64) width 4: " "
         LayoutTextControl {INPUT} at (177,62) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 169x16
-            LayoutBlockFlow {DIV} at (0,0) size 156x16
+            LayoutBlockFlow {DIV} at (12,0) size 157x16
         LayoutText {#text} at (352,64) size 4x17
           text run at (352,64) width 4: " "
         LayoutTextControl {INPUT} at (356,62) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
@@ -78,7 +78,7 @@
           text run at (529,64) width 4: " "
         LayoutTextControl {INPUT} at (533,62) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 169x16
-            LayoutBlockFlow {DIV} at (0,0) size 156x16
+            LayoutBlockFlow {DIV} at (12,0) size 157x16
         LayoutText {#text} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,84) size 173x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutText {#text} at (0,0) size 0x0
@@ -134,20 +134,20 @@
       text run at (-148,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,115) size 169x16
   LayoutBlockFlow {DIV} at (2,3) size 169x16
-layer at (188,115) size 156x16 scrollX 161.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (3,3) size 156x16 [color=#A9A9A9]
-    LayoutText {#text} at (-161,0) size 317x16
-      text run at (-161,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (188,115) size 156x16
-  LayoutBlockFlow {DIV} at (0,0) size 156x16
+layer at (200,115) size 157x16 scrollX 160.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (15,3) size 157x16 [color=#A9A9A9]
+    LayoutText {#text} at (-160,0) size 317x16
+      text run at (-160,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (200,115) size 157x16
+  LayoutBlockFlow {DIV} at (0,0) size 157x16
 layer at (366,115) size 169x16 scrollX 148.00 scrollWidth 317
   LayoutBlockFlow {DIV} at (2,3) size 169x16
     LayoutText {#text} at (-148,0) size 317x16
       text run at (-148,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (544,115) size 156x16 scrollX 161.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (0,0) size 156x16
-    LayoutText {#text} at (-161,0) size 317x16
-      text run at (-161,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (556,115) size 157x16 scrollX 160.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (0,0) size 157x16
+    LayoutText {#text} at (-160,0) size 317x16
+      text run at (-160,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,137) size 169x16 scrollX 106.00 scrollWidth 275
   LayoutBlockFlow {DIV} at (2,3) size 169x16
     LayoutText {#text} at (-106,0) size 275x16
@@ -182,20 +182,20 @@
       text run at (-148,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,237) size 169x16
   LayoutBlockFlow {DIV} at (2,3) size 169x16
-layer at (188,237) size 156x16 scrollX 161.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (3,3) size 156x16 [color=#A9A9A9]
-    LayoutText {#text} at (-161,0) size 317x16
-      text run at (-161,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (188,237) size 156x16
-  LayoutBlockFlow {DIV} at (0,0) size 156x16
+layer at (200,237) size 157x16 scrollX 160.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (15,3) size 157x16 [color=#A9A9A9]
+    LayoutText {#text} at (-160,0) size 317x16
+      text run at (-160,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (200,237) size 157x16
+  LayoutBlockFlow {DIV} at (0,0) size 157x16
 layer at (366,237) size 169x16 scrollX 148.00 scrollWidth 317
   LayoutBlockFlow {DIV} at (2,3) size 169x16
     LayoutText {#text} at (-148,0) size 317x16
       text run at (-148,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
-layer at (544,237) size 156x16 scrollX 161.00 scrollWidth 317
-  LayoutBlockFlow {DIV} at (0,0) size 156x16
-    LayoutText {#text} at (-161,0) size 317x16
-      text run at (-161,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
+layer at (556,237) size 157x16 scrollX 160.00 scrollWidth 317
+  LayoutBlockFlow {DIV} at (0,0) size 157x16
+    LayoutText {#text} at (-160,0) size 317x16
+      text run at (-160,0) width 317: "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
 layer at (10,259) size 169x16 scrollX 106.00 scrollWidth 275
   LayoutBlockFlow {DIV} at (2,3) size 169x16
     LayoutText {#text} at (-106,0) size 275x16
@@ -224,15 +224,15 @@
   LayoutBlockFlow {DIV} at (157,3.50) size 9x9
 layer at (701,75) size 9x9 transparent
   LayoutBlockFlow {DIV} at (157,3.50) size 9x9
-layer at (345,119) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (157,3.50) size 9x9
-layer at (701,119) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (157,3.50) size 9x9
+layer at (188,119) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (544,119) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
 layer at (345,197) size 9x9 transparent
   LayoutBlockFlow {DIV} at (157,3.50) size 9x9
 layer at (701,197) size 9x9 transparent
   LayoutBlockFlow {DIV} at (157,3.50) size 9x9
-layer at (345,241) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (157,3.50) size 9x9
-layer at (701,241) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (157,3.50) size 9x9
+layer at (188,241) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (544,241) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.png
index 4ce1a93..e5783b9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.txt
index 68a78c4..26920f7d 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/color/input-appearance-color-expected.txt
@@ -146,4 +146,14 @@
         LayoutBlockFlow {INPUT} at (188,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #00FF00)]
           LayoutFlexibleBox {DIV} at (3,2) size 82x19
             LayoutBlockFlow {DIV} at (8,4) size 50x11 [bgcolor=#FF0000] [border: (1px solid #000000)]
+        LayoutText {#text} at (276,2) size 4x17
+          text run at (276,2) width 4: " "
+        LayoutBlockFlow {INPUT} at (280,0) size 44x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 38x19
+            LayoutBlockFlow {DIV} at (2,4) size 34x11 [bgcolor=#40E0D0] [border: (1px solid #777777)]
+        LayoutText {#text} at (324,2) size 4x17
+          text run at (324,2) width 4: " "
+        LayoutBlockFlow {INPUT} at (328,0) size 88x23 [bgcolor=#DDDDDD] [border: (1px solid #A9A9A9)]
+          LayoutFlexibleBox {DIV} at (3,2) size 82x19
+            LayoutBlockFlow {DIV} at (24,4) size 50x11 [bgcolor=#FF0000] [border: (1px solid #000000)]
         LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.png
index 3d8d2ece1..51ccc58 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.txt
index 6e545ca7..def686e0 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/placeholder-position-expected.txt
@@ -21,7 +21,7 @@
       LayoutBR {BR} at (391,38) size 0x0
       LayoutTextControl {INPUT} at (0,44) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (3,3) size 169x16
-          LayoutBlockFlow {DIV} at (0,0) size 156x16
+          LayoutBlockFlow {DIV} at (12,0) size 157x16
       LayoutBR {BR} at (175,60) size 0x0
       LayoutTextControl {INPUT} at (0,66) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
         LayoutFlexibleBox {DIV} at (3,3) size 169x16
@@ -83,12 +83,12 @@
       text run at (0,0) width 105: "\x{65E5}\x{672C}\x{8A9E}placeholder"
 layer at (224,33) size 169x16
   LayoutBlockFlow {DIV} at (2,3) size 169x16
-layer at (11,55) size 156x16
-  LayoutBlockFlow {DIV} at (3,3) size 156x16 [color=#A9A9A9]
-    LayoutText {#text} at (90,0) size 66x16
-      text run at (90,0) width 66: "placeholder"
-layer at (11,55) size 156x16
-  LayoutBlockFlow {DIV} at (0,0) size 156x16
+layer at (23,55) size 157x16
+  LayoutBlockFlow {DIV} at (15,3) size 157x16 [color=#A9A9A9]
+    LayoutText {#text} at (91,0) size 66x16
+      text run at (91,0) width 66: "placeholder"
+layer at (23,55) size 157x16
+  LayoutBlockFlow {DIV} at (0,0) size 157x16
 layer at (11,77) size 156x16
   LayoutBlockFlow {DIV} at (3,3) size 156x16 [color=#A9A9A9]
     LayoutText {#text} at (0,0) size 66x16
@@ -165,8 +165,8 @@
   LayoutBlockFlow {DIV} at (2,3) size 169x16
 layer at (168,15) size 9x9 transparent
   LayoutBlockFlow {DIV} at (157,3.50) size 9x9
-layer at (168,59) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (157,3.50) size 9x9
+layer at (11,59) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
 layer at (168,81) size 9x9 transparent
   LayoutBlockFlow {DIV} at (157,3.50) size 9x9
 layer at (8,334) size 173x36
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png
index 79fa70d..b4290cd 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt
index 55a95cf..c92da46 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt
@@ -18,45 +18,45 @@
       LayoutBlockFlow {P} at (0,34) size 784x66
         LayoutTextControl {INPUT} at (0,0) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 169x16
-            LayoutBlockFlow {DIV} at (0,0) size 156x16
+            LayoutBlockFlow {DIV} at (12,0) size 157x16
         LayoutText {#text} at (175,2) size 4x17
           text run at (175,2) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,22) size 245x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 239x16
-            LayoutBlockFlow {DIV} at (0,0) size 226x16
+            LayoutBlockFlow {DIV} at (12,0) size 227x16
         LayoutText {#text} at (245,24) size 4x17
           text run at (245,24) width 4: " "
         LayoutBR {BR} at (0,0) size 0x0
         LayoutTextControl {INPUT} at (0,44) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)]
           LayoutFlexibleBox {DIV} at (3,3) size 169x16
-            LayoutBlockFlow {DIV} at (0,0) size 156x16
+            LayoutBlockFlow {DIV} at (12,0) size 157x16
         LayoutText {#text} at (0,0) size 0x0
       LayoutBlockFlow {P} at (0,116) size 784x18
         LayoutText {#text} at (0,0) size 37x17
           text run at (0,0) width 37: "PASS"
-layer at (11,45) size 156x16
-  LayoutBlockFlow {DIV} at (0,0) size 156x16
-    LayoutText {#text} at (13,0) size 143x16
-      text run at (13,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
-      text run at (36,0) width 21: "she"
-      text run at (57,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
-      text run at (103,0) width 14: "he"
-      text run at (117,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (11,67) size 226x16
-  LayoutBlockFlow {DIV} at (0,0) size 226x16
-    LayoutText {#text} at (83,0) size 143x16
-      text run at (83,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
-      text run at (106,0) width 21: "she"
-      text run at (127,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
-      text run at (173,0) width 14: "he"
-      text run at (187,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
-layer at (11,89) size 156x16
-  LayoutBlockFlow {DIV} at (0,0) size 156x16
-layer at (168,49) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (157,3.50) size 9x9
-layer at (238,71) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (227,3.50) size 9x9
-layer at (168,93) size 9x9 transparent
-  LayoutBlockFlow {DIV} at (157,3.50) size 9x9
+layer at (23,45) size 157x16
+  LayoutBlockFlow {DIV} at (0,0) size 157x16
+    LayoutText {#text} at (14,0) size 143x16
+      text run at (14,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
+      text run at (37,0) width 21: "she"
+      text run at (58,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
+      text run at (104,0) width 14: "he"
+      text run at (118,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
+layer at (23,67) size 227x16
+  LayoutBlockFlow {DIV} at (0,0) size 227x16
+    LayoutText {#text} at (84,0) size 143x16
+      text run at (84,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}"
+      text run at (107,0) width 21: "she"
+      text run at (128,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} "
+      text run at (174,0) width 14: "he"
+      text run at (188,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} "
+layer at (23,89) size 157x16
+  LayoutBlockFlow {DIV} at (0,0) size 157x16
+layer at (11,49) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (11,71) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
+layer at (11,93) size 9x9 transparent
+  LayoutBlockFlow {DIV} at (0,3.50) size 9x9
 caret: position 0 of child 0 {DIV} of child 0 {DIV} of child 0 {DIV} of {#document-fragment} of child 9 {INPUT} of child 3 {P} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-rtl-expected.png
new file mode 100644
index 0000000..5a083da
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-rtl-expected.txt
new file mode 100644
index 0000000..461e372f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -0,0 +1,168 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x540
+  LayoutBlockFlow {HTML} at (0,0) size 800x540
+    LayoutBlockFlow {BODY} at (8,16) size 784x516
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 758x35
+          text run at (0,0) width 758: "This tests that bidirectional text is correctly rendered in popup controls. The order of the text below each popup button"
+          text run at (0,18) width 600: "should match the order of the select's option text, and the order of the text in the popup menu."
+      LayoutBlockFlow {DL} at (0,52) size 784x168
+        LayoutBlockFlow {DT} at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 286x17
+            text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
+        LayoutBlockFlow {DD} at (40,18) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 98x18
+                LayoutText (anonymous) at (31,1) size 63x16
+                  text run at (31,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+                  text run at (73,1) width 21: "abc"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 100x18
+            LayoutText {#text} at (31,0) size 69x17
+              text run at (31,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+              text run at (77,0) width 23: "abc"
+        LayoutBlockFlow {DT} at (0,56) size 784x18
+          LayoutText {#text} at (0,0) size 118x17
+            text run at (0,0) width 118: "2) text-align: right"
+        LayoutBlockFlow {DD} at (40,74) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 200x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 198x18
+                LayoutText (anonymous) at (4,1) size 63x16
+                  text run at (4,1) width 21: "abc"
+                  text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 200x18
+            LayoutText {#text} at (0,0) size 69x17
+              text run at (0,0) width 23: "abc"
+              text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+        LayoutBlockFlow {DT} at (0,112) size 784x18
+          LayoutText {#text} at (0,0) size 72x17
+            text run at (0,0) width 72: "3) No style"
+        LayoutBlockFlow {DD} at (40,130) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 98x18
+                LayoutText (anonymous) at (4,1) size 63x16
+                  text run at (4,1) width 21: "abc"
+                  text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 100x18
+            LayoutText {#text} at (0,0) size 69x17
+              text run at (0,0) width 23: "abc"
+              text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+      LayoutBlockFlow {HR} at (0,236) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {DIV} at (0,246) size 784x54
+        LayoutBlockFlow (anonymous) at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 632x17
+            text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
+        LayoutBlockFlow {DIV} at (0,18) size 784x16
+          LayoutText {#text} at (0,0) size 101x16
+            text run at (0,0) width 101 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+        LayoutBlockFlow (anonymous) at (0,34) size 784x20
+          LayoutMenuList {SELECT} at (0,0) size 115x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+            LayoutBlockFlow (anonymous) at (1,1) size 113x18
+              LayoutText (anonymous) at (4,1) size 82x16
+                text run at (4,1) width 82 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+          LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {HR} at (0,308) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {P} at (0,326) size 784x18
+        LayoutText {#text} at (0,0) size 709x17
+          text run at (0,0) width 709: "Verify that the alignment and writing direction of each selected item matches the one below the pop-up button."
+layer at (8,376) size 784x156
+  LayoutBlockFlow {DIV} at (0,360) size 784x156
+    LayoutMultiColumnSet (anonymous) at (0,0) size 784x156
+layer at (8,376) size 384x312 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
+  LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x312
+    LayoutBlockFlow {DIV} at (0,0) size 384x156
+      LayoutMenuList {SELECT} at (0,0) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 36: "First "
+            text run at (39,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (92,1) width 19: "03"
+            text run at (110,1) width 41 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (150,1) width 31: " fifth"
+      LayoutBlockFlow {DIV} at (0,21) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 27: "First "
+          text run at (28,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (66,1) width 12: "03"
+          text run at (78,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (106,1) width 25: " fifth"
+      LayoutMenuList {SELECT} at (0,39) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 26: "fifth"
+            text run at (29,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (87,1) width 19: "03"
+            text run at (105,1) width 45 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (149,1) width 32: "First"
+      LayoutBlockFlow {DIV} at (0,60) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 22: "fifth"
+          text run at (23,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (64,1) width 12: "03"
+          text run at (76,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (107,1) width 24: "First"
+      LayoutMenuList {SELECT} at (0,78) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 177 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,99) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,117) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 177 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,138) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+    LayoutBlockFlow {DIV} at (0,156) size 384x156
+      LayoutMenuList {SELECT} at (0,0) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 36: "First "
+            text run at (202,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (255,1) width 19: "03"
+            text run at (273,1) width 41 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (313,1) width 31: " fifth"
+      LayoutBlockFlow {DIV} at (0,21) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 27: "First "
+          text run at (248,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (286,1) width 12: "03"
+          text run at (298,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (326,1) width 25: " fifth"
+      LayoutMenuList {SELECT} at (0,39) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 26: "fifth"
+            text run at (192,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (250,1) width 19: "03"
+            text run at (268,1) width 45 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (312,1) width 32: "First"
+      LayoutBlockFlow {DIV} at (0,60) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 22: "fifth"
+          text run at (243,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (284,1) width 12: "03"
+          text run at (296,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (327,1) width 24: "First"
+      LayoutMenuList {SELECT} at (0,78) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 177 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,99) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,117) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 177 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,138) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/bidi-menulist-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/bidi-menulist-expected.png
deleted file mode 100644
index 15d0887..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/bidi-menulist-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/bidi-menulist-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/bidi-menulist-expected.txt
deleted file mode 100644
index 526ec6a..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/bidi-menulist-expected.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x54
-        LayoutText {#text} at (0,0) size 458x17
-          text run at (0,0) width 458: "This tests that bidirectional text is correctly rendered in popup controls."
-        LayoutBR {BR} at (457,14) size 1x0
-        LayoutText {#text} at (0,18) size 773x35
-          text run at (0,18) width 773: "The order of the text below each popup button should match the order of the select's option text, and the order of the text"
-          text run at (0,36) width 124: "in the popup menu."
-      LayoutBlockFlow (anonymous) at (0,70) size 784x37
-        LayoutText {#text} at (0,0) size 286x17
-          text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
-        LayoutBR {BR} at (285,14) size 1x0
-        LayoutMenuList {SELECT} at (0,18) size 100x19 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 98x17
-            LayoutText (anonymous) at (29,1) size 65x15
-              text run at (29,1) width 44 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-              text run at (73,1) width 21: "abc"
-        LayoutBR {BR} at (100,32) size 0x0
-      LayoutBlockFlow {DIV} at (0,107) size 100x18
-        LayoutText {#text} at (0,0) size 69x17
-          text run at (0,0) width 23: "abc"
-          text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,125) size 784x55
-        LayoutBR {BR} at (0,0) size 0x17
-        LayoutText {#text} at (0,18) size 118x17
-          text run at (0,18) width 118: "2) text-align: right"
-        LayoutBR {BR} at (117,32) size 1x0
-        LayoutMenuList {SELECT} at (0,36) size 200x19 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 198x17
-            LayoutText (anonymous) at (4,1) size 65x15
-              text run at (4,1) width 21: "abc"
-              text run at (25,1) width 44 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (200,50) size 0x0
-      LayoutBlockFlow {DIV} at (0,180) size 200x18
-        LayoutText {#text} at (0,0) size 69x17
-          text run at (0,0) width 23: "abc"
-          text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,198) size 784x55
-        LayoutBR {BR} at (0,0) size 0x17
-        LayoutText {#text} at (0,18) size 72x17
-          text run at (0,18) width 72: "3) No style"
-        LayoutBR {BR} at (71,32) size 1x0
-        LayoutMenuList {SELECT} at (0,36) size 100x19 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 98x17
-            LayoutText (anonymous) at (4,1) size 65x15
-              text run at (4,1) width 21: "abc"
-              text run at (25,1) width 44 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-        LayoutBR {BR} at (100,50) size 0x0
-      LayoutBlockFlow {DIV} at (0,253) size 100x18
-        LayoutText {#text} at (0,0) size 69x17
-          text run at (0,0) width 23: "abc"
-          text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
-      LayoutBlockFlow (anonymous) at (0,271) size 784x18
-        LayoutBR {BR} at (0,0) size 0x17
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/menulist-width-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/menulist-width-rtl-expected.png
deleted file mode 100644
index 2855ffd..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/menulist-width-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/menulist-width-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/menulist-width-rtl-expected.txt
deleted file mode 100644
index f8bfa6c..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/menulist-width-rtl-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x69
-  LayoutBlockFlow {HTML} at (0,0) size 800x69
-    LayoutBlockFlow {BODY} at (8,8) size 784x53
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 632x17
-          text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
-      LayoutBlockFlow {DIV} at (0,18) size 784x16
-        LayoutText {#text} at (683,0) size 101x16
-          text run at (683,0) width 101 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-      LayoutBlockFlow (anonymous) at (0,34) size 784x19
-        LayoutMenuList {SELECT} at (665,0) size 119x19 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 117x17
-            LayoutText (anonymous) at (18,1) size 95x15
-              text run at (18,1) width 95 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
deleted file mode 100644
index aff07e5..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
deleted file mode 100644
index d2c05d9..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/fast/text/international/pop-up-button-text-alignment-and-direction-expected.txt
+++ /dev/null
@@ -1,99 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x514
-  LayoutBlockFlow {HTML} at (0,0) size 800x514
-    LayoutBlockFlow {BODY} at (8,16) size 784x490
-      LayoutBlockFlow {P} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 709x17
-          text run at (0,0) width 497: "Verify that the alignment and writing direction of each selected item matches "
-          text run at (496,0) width 213: "the one below the pop-up button."
-      LayoutBlockFlow {DIV} at (0,34) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (4,1) size 177x17
-              text run at (4,1) width 36: "First "
-              text run at (39,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (92,1) width 19: "03"
-              text run at (110,1) width 41 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (150,1) width 31: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
-          LayoutText {#text} at (10,10) size 133x15
-            text run at (10,10) width 27: "First "
-            text run at (37,10) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (75,10) width 14: "03"
-            text run at (89,10) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (117,10) width 26: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (4,1) size 177x17
-              text run at (4,1) width 26: "fifth"
-              text run at (29,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (87,1) width 19: "03"
-              text run at (105,1) width 45 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (149,1) width 32: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
-          LayoutText {#text} at (10,10) size 133x15
-            text run at (10,10) width 23: "fifth"
-            text run at (33,10) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (74,10) width 14: "03"
-            text run at (88,10) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (119,10) width 24: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (4,1) size 177x17
-              text run at (4,1) width 177 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
-          LayoutText {#text} at (10,10) size 133x15
-            text run at (10,10) width 133 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (4,1) size 177x17
-              text run at (4,1) width 177 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
-          LayoutText {#text} at (10,10) size 133x15
-            text run at (10,10) width 133 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-      LayoutBlockFlow {DIV} at (0,262) size 784x228
-        LayoutMenuList {SELECT} at (0,0) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (317,1) size 177x17
-              text run at (317,1) width 36: "First "
-              text run at (352,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-              text run at (405,1) width 19: "03"
-              text run at (423,1) width 41 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (463,1) width 31: " fifth"
-        LayoutBlockFlow {DIV} at (0,21) size 470x36
-          LayoutText {#text} at (327,10) size 133x15
-            text run at (327,10) width 27: "First "
-            text run at (354,10) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
-            text run at (392,10) width 14: "03"
-            text run at (406,10) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (434,10) width 26: " fifth"
-        LayoutMenuList {SELECT} at (0,57) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (317,1) size 177x17
-              text run at (317,1) width 26: "fifth"
-              text run at (342,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-              text run at (400,1) width 19: "03"
-              text run at (418,1) width 45 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-              text run at (462,1) width 32: "First"
-        LayoutBlockFlow {DIV} at (0,78) size 470x36
-          LayoutText {#text} at (327,10) size 133x15
-            text run at (327,10) width 23: "fifth"
-            text run at (350,10) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
-            text run at (391,10) width 14: "03"
-            text run at (405,10) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
-            text run at (436,10) width 24: "First"
-        LayoutMenuList {SELECT} at (0,114) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (317,1) size 177x17
-              text run at (317,1) width 177 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,135) size 470x36
-          LayoutText {#text} at (327,10) size 133x15
-            text run at (327,10) width 133 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutMenuList {SELECT} at (0,171) size 500x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 498x20
-            LayoutText (anonymous) at (317,1) size 177x17
-              text run at (317,1) width 177 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
-        LayoutBlockFlow {DIV} at (0,192) size 470x36
-          LayoutText {#text} at (327,10) size 133x15
-            text run at (327,10) width 133 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/select/menulist-appearance-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/select/menulist-appearance-rtl-expected.png
new file mode 100644
index 0000000..507c207b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/select/menulist-appearance-rtl-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/select/menulist-appearance-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/select/menulist-appearance-rtl-expected.txt
new file mode 100644
index 0000000..a397a4f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/select/menulist-appearance-rtl-expected.txt
@@ -0,0 +1,168 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x540
+  LayoutBlockFlow {HTML} at (0,0) size 800x540
+    LayoutBlockFlow {BODY} at (8,16) size 784x516
+      LayoutBlockFlow {P} at (0,0) size 784x36
+        LayoutText {#text} at (0,0) size 758x35
+          text run at (0,0) width 758: "This tests that bidirectional text is correctly rendered in popup controls. The order of the text below each popup button"
+          text run at (0,18) width 600: "should match the order of the select's option text, and the order of the text in the popup menu."
+      LayoutBlockFlow {DL} at (0,52) size 784x168
+        LayoutBlockFlow {DT} at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 286x17
+            text run at (0,0) width 286: "1) direction: rtl; -webkit-rtl-ordering: logical"
+        LayoutBlockFlow {DD} at (40,18) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 98x18
+                LayoutText (anonymous) at (31,1) size 63x16
+                  text run at (31,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+                  text run at (73,1) width 21: "abc"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 100x18
+            LayoutText {#text} at (31,0) size 69x17
+              text run at (31,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+              text run at (77,0) width 23: "abc"
+        LayoutBlockFlow {DT} at (0,56) size 784x18
+          LayoutText {#text} at (0,0) size 118x17
+            text run at (0,0) width 118: "2) text-align: right"
+        LayoutBlockFlow {DD} at (40,74) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 200x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 198x18
+                LayoutText (anonymous) at (4,1) size 63x16
+                  text run at (4,1) width 21: "abc"
+                  text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 200x18
+            LayoutText {#text} at (0,0) size 69x17
+              text run at (0,0) width 23: "abc"
+              text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+        LayoutBlockFlow {DT} at (0,112) size 784x18
+          LayoutText {#text} at (0,0) size 72x17
+            text run at (0,0) width 72: "3) No style"
+        LayoutBlockFlow {DD} at (40,130) size 744x38
+          LayoutBlockFlow (anonymous) at (0,0) size 744x20
+            LayoutMenuList {SELECT} at (0,0) size 100x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+              LayoutBlockFlow (anonymous) at (1,1) size 98x18
+                LayoutText (anonymous) at (4,1) size 63x16
+                  text run at (4,1) width 21: "abc"
+                  text run at (25,1) width 42 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+            LayoutText {#text} at (0,0) size 0x0
+          LayoutBlockFlow {DIV} at (0,20) size 100x18
+            LayoutText {#text} at (0,0) size 69x17
+              text run at (0,0) width 23: "abc"
+              text run at (22,0) width 47 RTL: "\x{5D0}\x{5E4}\x{5E8}\x{5E1}\x{5DE}\x{5D5}\x{5DF}"
+      LayoutBlockFlow {HR} at (0,236) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {DIV} at (0,246) size 784x54
+        LayoutBlockFlow (anonymous) at (0,0) size 784x18
+          LayoutText {#text} at (0,0) size 632x17
+            text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
+        LayoutBlockFlow {DIV} at (0,18) size 784x16
+          LayoutText {#text} at (0,0) size 87x16
+            text run at (0,0) width 87 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+        LayoutBlockFlow (anonymous) at (0,34) size 784x20
+          LayoutMenuList {SELECT} at (0,0) size 115x20 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+            LayoutBlockFlow (anonymous) at (1,1) size 113x18
+              LayoutText (anonymous) at (4,1) size 82x16
+                text run at (4,1) width 82 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
+          LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {HR} at (0,308) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow {P} at (0,326) size 784x18
+        LayoutText {#text} at (0,0) size 709x17
+          text run at (0,0) width 709: "Verify that the alignment and writing direction of each selected item matches the one below the pop-up button."
+layer at (8,376) size 784x156
+  LayoutBlockFlow {DIV} at (0,360) size 784x156
+    LayoutMultiColumnSet (anonymous) at (0,0) size 784x156
+layer at (8,376) size 384x312 backgroundClip at (0,0) size 800x600 clip at (0,0) size 800x600
+  LayoutMultiColumnFlowThread (anonymous) at (0,0) size 384x312
+    LayoutBlockFlow {DIV} at (0,0) size 384x156
+      LayoutMenuList {SELECT} at (0,0) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 36: "First "
+            text run at (39,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (92,1) width 19: "03"
+            text run at (110,1) width 41 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (150,1) width 31: " fifth"
+      LayoutBlockFlow {DIV} at (0,21) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 27: "First "
+          text run at (28,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (66,1) width 12: "03"
+          text run at (78,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (106,1) width 25: " fifth"
+      LayoutMenuList {SELECT} at (0,39) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 26: "fifth"
+            text run at (29,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (87,1) width 19: "03"
+            text run at (105,1) width 45 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (149,1) width 32: "First"
+      LayoutBlockFlow {DIV} at (0,60) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 22: "fifth"
+          text run at (23,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (64,1) width 12: "03"
+          text run at (76,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (107,1) width 24: "First"
+      LayoutMenuList {SELECT} at (0,78) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 177 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,99) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,117) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (4,1) size 177x17
+            text run at (4,1) width 177 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,138) size 352x18
+        LayoutText {#text} at (1,1) size 130x15
+          text run at (1,1) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+    LayoutBlockFlow {DIV} at (0,156) size 384x156
+      LayoutMenuList {SELECT} at (0,0) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 36: "First "
+            text run at (202,1) width 54 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+            text run at (255,1) width 19: "03"
+            text run at (273,1) width 41 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (313,1) width 31: " fifth"
+      LayoutBlockFlow {DIV} at (0,21) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 27: "First "
+          text run at (248,1) width 38 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA}"
+          text run at (286,1) width 12: "03"
+          text run at (298,1) width 28 RTL: "\x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (326,1) width 25: " fifth"
+      LayoutMenuList {SELECT} at (0,39) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 26: "fifth"
+            text run at (192,1) width 59 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+            text run at (250,1) width 19: "03"
+            text run at (268,1) width 45 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+            text run at (312,1) width 32: "First"
+      LayoutBlockFlow {DIV} at (0,60) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 22: "fifth"
+          text run at (243,1) width 41 RTL: ") \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} "
+          text run at (284,1) width 12: "03"
+          text run at (296,1) width 31 RTL: " \x{5E9}\x{5E0}\x{5D9}\x{5D4} ("
+          text run at (327,1) width 24: "First"
+      LayoutMenuList {SELECT} at (0,78) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 177 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,99) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 130 LTR override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutMenuList {SELECT} at (0,117) size 350x21 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
+        LayoutBlockFlow (anonymous) at (1,1) size 348x20
+          LayoutText (anonymous) at (167,1) size 177x17
+            text run at (167,1) width 177 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
+      LayoutBlockFlow {DIV} at (0,138) size 352x18
+        LayoutText {#text} at (221,1) size 130x15
+          text run at (221,1) width 130 RTL override: "First \x{5E9}\x{5E0}\x{5D9}\x{5D4} (03) \x{5E8}\x{5D1}\x{5D9}\x{5E2}\x{5D9}\x{5EA} fifth"
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/menulist-width-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/menulist-width-rtl-expected.png
deleted file mode 100644
index 3372ce5..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/menulist-width-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/menulist-width-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/menulist-width-rtl-expected.txt
deleted file mode 100644
index 8a43ee50..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/menulist-width-rtl-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x69
-  LayoutBlockFlow {HTML} at (0,0) size 800x69
-    LayoutBlockFlow {BODY} at (8,8) size 784x53
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 632x17
-          text run at (0,0) width 632: "The following line and the SELECT element should have same text, and no characters are lacking."
-      LayoutBlockFlow {DIV} at (0,18) size 784x16
-        LayoutText {#text} at (697,0) size 87x16
-          text run at (697,0) width 87 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-      LayoutBlockFlow (anonymous) at (0,34) size 784x19
-        LayoutMenuList {SELECT} at (665,0) size 119x19 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)]
-          LayoutBlockFlow (anonymous) at (1,1) size 117x17
-            LayoutText (anonymous) at (18,1) size 95x15
-              text run at (18,1) width 95 RTL: "\x{627}\x{644}\x{627}\x{642}\x{62A}\x{631}\x{627}\x{62D}\x{627}\x{62A} / \x{627}\x{644}\x{634}\x{643}\x{627}\x{648}\x{64A}"
-        LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
deleted file mode 100644
index a73e732..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/fast/text/international/pop-up-button-text-alignment-and-direction-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/effect-of-keyframeeffect-on-getComputedTiming.html b/third_party/WebKit/LayoutTests/web-animations-api/effect-of-keyframeeffect-on-getComputedTiming.html
index dd4b79c..77d15b5d 100644
--- a/third_party/WebKit/LayoutTests/web-animations-api/effect-of-keyframeeffect-on-getComputedTiming.html
+++ b/third_party/WebKit/LayoutTests/web-animations-api/effect-of-keyframeeffect-on-getComputedTiming.html
@@ -66,7 +66,7 @@
 
 test(function() {
   var timing = new KeyframeEffect(element, keyframes).timing;
-  for (var attr of ['delay', 'endDelay', 'iterationStart', 'playbackRate']) {
+  for (var attr of ['delay', 'endDelay', 'iterationStart']) {
     assert_throws(new TypeError, function() { timing[attr] = NaN; }, attr);
     assert_throws(new TypeError, function() { timing[attr] = Infinity; }, attr);
   }
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index c0fe778b0..e777201 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -48,7 +48,6 @@
     getter fill
     getter iterationStart
     getter iterations
-    getter playbackRate
     method constructor
     setter delay
     setter direction
@@ -58,7 +57,6 @@
     setter fill
     setter iterationStart
     setter iterations
-    setter playbackRate
 interface AnimationEvent : Event
     attribute @@toStringTag
     getter animationName
@@ -72,12 +70,9 @@
 interface AnimationTimeline
     attribute @@toStringTag
     getter currentTime
-    getter playbackRate
     method constructor
     method getAnimations
-    method play
     setter currentTime
-    setter playbackRate
 interface AppBannerPromptResult
     attribute @@toStringTag
     getter outcome
diff --git a/third_party/WebKit/LayoutTests/webshare/resources/mock-share-service.js b/third_party/WebKit/LayoutTests/webshare/resources/mock-share-service.js
index 2ce703f3..642561c7 100644
--- a/third_party/WebKit/LayoutTests/webshare/resources/mock-share-service.js
+++ b/third_party/WebKit/LayoutTests/webshare/resources/mock-share-service.js
@@ -64,3 +64,16 @@
     return Promise.race([func(t, mock), mockPromise]);
   }), name, properties);
 }
+
+// Copied from resources/bluetooth/bluetooth-helpers.js.
+function callWithKeyDown(functionCalledOnKeyPress) {
+  return new Promise(resolve => {
+    function onKeyPress() {
+      document.removeEventListener('keypress', onKeyPress, false);
+      resolve(functionCalledOnKeyPress());
+    }
+    document.addEventListener('keypress', onKeyPress, false);
+
+    eventSender.keyDown(' ', []);
+  });
+}
diff --git a/third_party/WebKit/LayoutTests/webshare/share-arity.html b/third_party/WebKit/LayoutTests/webshare/share-arity.html
index 6a8af68..a99943b 100644
--- a/third_party/WebKit/LayoutTests/webshare/share-arity.html
+++ b/third_party/WebKit/LayoutTests/webshare/share-arity.html
@@ -6,17 +6,17 @@
 <script>
 
 share_test((t, mock) => {
-  return promise_rejects(t, new TypeError(), navigator.share());
+  return callWithKeyDown(() => promise_rejects(t, new TypeError(), navigator.share()));
 }, '0 arguments (promise rejection)');
 
 share_test((t, mock) => {
   mock.pushShareResult('the title', 'the message', null);
-  return navigator.share({title: 'the title', text: 'the message', unused: 'unexpected field'});
+  return callWithKeyDown(() => navigator.share({title: 'the title', text: 'the message', unused: 'unexpected field'}));
 }, 'extra ShareData field (extra field ignored)');
 
 share_test((t, mock) => {
   mock.pushShareResult('the title', 'the message', null);
-  return navigator.share({title: 'the title', text: 'the message'}, 'more than required');
+  return callWithKeyDown(() => navigator.share({title: 'the title', text: 'the message'}, 'more than required'));
 }, '2 arguments (extra argument ignored)');
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/webshare/share-error.html b/third_party/WebKit/LayoutTests/webshare/share-error.html
index 267f0e4..cc6474f1 100644
--- a/third_party/WebKit/LayoutTests/webshare/share-error.html
+++ b/third_party/WebKit/LayoutTests/webshare/share-error.html
@@ -7,9 +7,9 @@
 
 share_test((t, mock) => {
   mock.pushShareResult('the title', 'the message', 'error from browser');
-  return promise_rejects(
+  return callWithKeyDown(() => promise_rejects(
       t, new DOMException('error from browser', 'AbortError'),
-      navigator.share({title: 'the title', text: 'the message'}));
+      navigator.share({title: 'the title', text: 'the message'})));
 }, 'share with browser-side error');
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/webshare/share-success.html b/third_party/WebKit/LayoutTests/webshare/share-success.html
index 770b349f..79000b5 100644
--- a/third_party/WebKit/LayoutTests/webshare/share-success.html
+++ b/third_party/WebKit/LayoutTests/webshare/share-success.html
@@ -7,13 +7,13 @@
 
 share_test((t, mock) => {
   mock.pushShareResult('the title', 'the message', null);
-  return navigator.share({title: 'the title', text: 'the message',
-                          url: 'the URL'});
+  return callWithKeyDown(() => navigator.share(
+        {title: 'the title', text: 'the message', url: 'the URL'}));
 }, 'successful share');
 
 share_test((t, mock) => {
   mock.pushShareResult('', '', null);
-  return navigator.share({});
+  return callWithKeyDown(() => navigator.share({}));
 }, 'successful share with empty ShareData');
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/webshare/share-types.html b/third_party/WebKit/LayoutTests/webshare/share-types.html
index 8c49cb15..64d8229b 100644
--- a/third_party/WebKit/LayoutTests/webshare/share-types.html
+++ b/third_party/WebKit/LayoutTests/webshare/share-types.html
@@ -7,7 +7,7 @@
 
 share_test((t, mock) => {
   mock.pushShareResult('384957', '[object Object]', null);
-  return navigator.share({title: 384957, text: {}});
+  return callWithKeyDown(() => navigator.share({title: 384957, text: {}}));
 }, 'share of types other than string (expect implicitly converted to string)');
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/webshare/share-without-user-gesture.html b/third_party/WebKit/LayoutTests/webshare/share-without-user-gesture.html
new file mode 100644
index 0000000..d69adc8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/webshare/share-without-user-gesture.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/mojo-helpers.js"></script>
+<script src="resources/mock-share-service.js"></script>
+<script>
+
+share_test((t, mock) => {
+  return promise_rejects(
+      t, new DOMException('Must be handling a user gesture to perform a share request.', 'SecurityError'),
+      navigator.share({title: 'the title', text: 'the message'}));
+}, 'share without a user gesture');
+
+</script>
diff --git a/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.cpp b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.cpp
new file mode 100644
index 0000000..57ecd06
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.cpp
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "bindings/core/v8/GeneratedCodeHelper.h"
+
+#include "bindings/core/v8/V8Binding.h"
+
+namespace blink {
+
+void v8ConstructorAttributeGetter(v8::Local<v8::Name> propertyName, const v8::PropertyCallbackInfo<v8::Value>& info)
+{
+    v8::Local<v8::Value> data = info.Data();
+    DCHECK(data->IsExternal());
+    V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext());
+    if (!perContextData)
+        return;
+    v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::unwrap(data)));
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h
new file mode 100644
index 0000000..1f09d19
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/GeneratedCodeHelper.h
@@ -0,0 +1,23 @@
+// 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.
+
+// This file is for functions that are used only by generated code.
+// CAUTION:
+// All functions defined in this file should be used by generated code only.
+// If you want to use them from hand-written code, please find appropriate
+// location and move them to that location.
+
+#ifndef GeneratedCodeHelper_h
+#define GeneratedCodeHelper_h
+
+#include "core/CoreExport.h"
+#include <v8.h>
+
+namespace blink {
+
+CORE_EXPORT void v8ConstructorAttributeGetter(v8::Local<v8::Name> propertyName, const v8::PropertyCallbackInfo<v8::Value>&);
+
+} // namespace blink
+
+#endif // GeneratedCodeHelper_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
index 0c3bb65..a26b1ac 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
@@ -82,12 +82,12 @@
 }
 
 bool ScriptCustomElementDefinitionBuilder::valueForName(
-    const v8::Local<v8::Object>& object, const String& name,
+    const v8::Local<v8::Object>& object, const StringView& name,
     v8::Local<v8::Value>& value) const
 {
     v8::Isolate* isolate = m_scriptState->isolate();
     v8::Local<v8::Context> context = m_scriptState->context();
-    v8::Local<v8::String> nameString = v8String(isolate, name);
+    v8::Local<v8::String> nameString = v8AtomicString(isolate, name);
     v8::TryCatch tryCatch(isolate);
     if (!v8Call(object->Get(context, nameString), value, tryCatch)) {
         m_exceptionState.rethrowV8Exception(tryCatch.Exception());
@@ -112,7 +112,7 @@
     return true;
 }
 
-bool ScriptCustomElementDefinitionBuilder::callableForName(const String& name,
+bool ScriptCustomElementDefinitionBuilder::callableForName(const StringView& name,
     v8::Local<v8::Function>& callback) const
 {
     v8::Local<v8::Value> value;
@@ -123,7 +123,8 @@
         return true;
     if (!value->IsFunction()) {
         m_exceptionState.throwTypeError(
-            String::format("\"%s\" is not a callable object", name.ascii().data()));
+            String::format("\"%s\" is not a callable object",
+                name.toString().ascii().data()));
         return false;
     }
     callback = value.As<v8::Function>();
@@ -132,9 +133,8 @@
 
 bool ScriptCustomElementDefinitionBuilder::retrieveObservedAttributes()
 {
-    const String kObservedAttributes = "observedAttributes";
     v8::Local<v8::Value> observedAttributesValue;
-    if (!valueForName(m_constructor, kObservedAttributes, observedAttributesValue))
+    if (!valueForName(m_constructor, "observedAttributes", observedAttributesValue))
         return false;
     if (observedAttributesValue->IsUndefined())
         return true;
@@ -154,14 +154,10 @@
 {
     // Spec requires to use values of these properties at the point
     // CustomElementDefinition is built, even if JS changes them afterwards.
-    const String kConnectedCallback = "connectedCallback";
-    const String kDisconnectedCallback = "disconnectedCallback";
-    const String kAdoptedCallback = "adoptedCallback";
-    const String kAttributeChangedCallback = "attributeChangedCallback";
-    return callableForName(kConnectedCallback, m_connectedCallback)
-        && callableForName(kDisconnectedCallback, m_disconnectedCallback)
-        && callableForName(kAdoptedCallback, m_adoptedCallback)
-        && callableForName(kAttributeChangedCallback, m_attributeChangedCallback)
+    return callableForName("connectedCallback", m_connectedCallback)
+        && callableForName("disconnectedCallback", m_disconnectedCallback)
+        && callableForName("adoptedCallback", m_adoptedCallback)
+        && callableForName("attributeChangedCallback", m_attributeChangedCallback)
         && (m_attributeChangedCallback.IsEmpty() || retrieveObservedAttributes());
 }
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h
index 695adca..9f75eee 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.h
@@ -15,6 +15,7 @@
 #include "wtf/RefPtr.h"
 #include "wtf/text/AtomicString.h"
 #include "wtf/text/AtomicStringHash.h"
+#include "wtf/text/StringView.h"
 
 namespace blink {
 
@@ -57,8 +58,8 @@
     HashSet<AtomicString> m_observedAttributes;
     ExceptionState& m_exceptionState;
 
-    bool valueForName(const v8::Local<v8::Object>&, const String&, v8::Local<v8::Value>&) const;
-    bool callableForName(const String&, v8::Local<v8::Function>&) const;
+    bool valueForName(const v8::Local<v8::Object>&, const StringView&, v8::Local<v8::Value>&) const;
+    bool callableForName(const StringView&, v8::Local<v8::Function>&) const;
     bool retrieveObservedAttributes();
 };
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp
index cb45b39..455e8b3 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.cpp
@@ -938,16 +938,6 @@
     return frame->script().isolate();
 }
 
-void v8ConstructorAttributeGetter(v8::Local<v8::Name> propertyName, const v8::PropertyCallbackInfo<v8::Value>& info)
-{
-    v8::Local<v8::Value> data = info.Data();
-    ASSERT(data->IsExternal());
-    V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext());
-    if (!perContextData)
-        return;
-    v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::unwrap(data)));
-}
-
 v8::Local<v8::Value> freezeV8Object(v8::Local<v8::Value> value, v8::Isolate* isolate)
 {
     value.As<v8::Object>()->SetIntegrityLevel(isolate->GetCurrentContext(), v8::IntegrityLevel::kFrozen).ToChecked();
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
index dd3ff13..35a426b5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
@@ -961,8 +961,6 @@
     v8::Isolate* m_isolate;
 };
 
-// Callback functions used by generated code.
-CORE_EXPORT void v8ConstructorAttributeGetter(v8::Local<v8::Name> propertyName, const v8::PropertyCallbackInfo<v8::Value>&);
 
 typedef void (*InstallTemplateFunction)(v8::Isolate*, const DOMWrapperWorld&, v8::Local<v8::FunctionTemplate> interfaceTemplate);
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8DOMConfiguration.cpp b/third_party/WebKit/Source/bindings/core/v8/V8DOMConfiguration.cpp
index 7886f5d..5a986f7 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8DOMConfiguration.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8DOMConfiguration.cpp
@@ -28,6 +28,7 @@
 
 #include "bindings/core/v8/V8DOMConfiguration.h"
 
+#include "bindings/core/v8/GeneratedCodeHelper.h" // just for DCHECK
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8PerContextData.h"
 #include "platform/TraceEvent.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ObjectConstructor.h b/third_party/WebKit/Source/bindings/core/v8/V8ObjectConstructor.h
index 3f5b31d..b9d64bf 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ObjectConstructor.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ObjectConstructor.h
@@ -51,7 +51,6 @@
 
     ConstructorMode(v8::Isolate* isolate)
         : m_isolate(isolate)
-        , m_microtaskSuppression(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks)
     {
         V8PerIsolateData* data = V8PerIsolateData::from(m_isolate);
         m_previous = data->m_constructorMode;
@@ -72,7 +71,6 @@
 private:
     v8::Isolate* m_isolate;
     bool m_previous;
-    v8::MicrotasksScope m_microtaskSuppression;
 };
 
 class CORE_EXPORT V8ObjectConstructor {
diff --git a/third_party/WebKit/Source/bindings/core/v8/v8.gypi b/third_party/WebKit/Source/bindings/core/v8/v8.gypi
index 0839dd3d2..4dd67ec2 100644
--- a/third_party/WebKit/Source/bindings/core/v8/v8.gypi
+++ b/third_party/WebKit/Source/bindings/core/v8/v8.gypi
@@ -42,6 +42,8 @@
             'ExceptionState.h',
             'ExceptionStatePlaceholder.cpp',
             'ExceptionStatePlaceholder.h',
+            'GeneratedCodeHelper.cpp',
+            'GeneratedCodeHelper.h',
             'IDLDictionaryBase.cpp',
             'IDLDictionaryBase.h',
             'Iterable.h',
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
index 6554ffe..be83d478 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -50,6 +50,7 @@
 
 
 INTERFACE_H_INCLUDES = frozenset([
+    'bindings/core/v8/GeneratedCodeHelper.h',
     'bindings/core/v8/ScriptWrappable.h',
     'bindings/core/v8/ToV8.h',
     'bindings/core/v8/V8Binding.h',
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h
index f66aeac3..25cd686 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBuffer.h
@@ -7,6 +7,7 @@
 #ifndef V8ArrayBuffer_h
 #define V8ArrayBuffer_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h
index 9e891a16c..500569b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8ArrayBufferView.h
@@ -7,6 +7,7 @@
 #ifndef V8ArrayBufferView_h
 #define V8ArrayBufferView_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h
index ebdaa4b..6690751 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8DataView.h
@@ -7,6 +7,7 @@
 #ifndef V8DataView_h
 #define V8DataView_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8ArrayBufferView.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h
index 29a4f2a..1829df6 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.h
@@ -7,6 +7,7 @@
 #ifndef V8SVGTestInterface_h
 #define V8SVGTestInterface_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.h
index 70c8a05..22ea877 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.h
@@ -7,6 +7,7 @@
 #ifndef V8TestException_h
 #define V8TestException_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h
index 33ab16dd..bb5645f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.h
@@ -7,6 +7,7 @@
 #ifndef V8TestIntegerIndexed_h
 #define V8TestIntegerIndexed_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h
index 57a2b68..b1a74de0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.h
@@ -7,6 +7,7 @@
 #ifndef V8TestIntegerIndexedGlobal_h
 #define V8TestIntegerIndexedGlobal_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h
index 946a35e..244898b8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.h
@@ -7,6 +7,7 @@
 #ifndef V8TestIntegerIndexedPrimaryGlobal_h
 #define V8TestIntegerIndexedPrimaryGlobal_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
index 7d368b9..3e85ac4e0 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterface_h
 #define V8TestInterface_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/StringOrDouble.h"
 #include "bindings/core/v8/ToV8.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
index 4b24b8f..0bf6635 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterface2_h
 #define V8TestInterface2_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h
index 708c9188..1f23639 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterface3_h
 #define V8TestInterface3_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h
index 836eaee..73a166aaf 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceCheckSecurity_h
 #define V8TestInterfaceCheckSecurity_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h
index bfa11e6..61cfb3e8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceConstructor_h
 #define V8TestInterfaceConstructor_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/LongOrTestDictionary.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h
index bebd919..fa3ced7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceConstructor2_h
 #define V8TestInterfaceConstructor2_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h
index 3df4c99..4b82d03 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceConstructor3_h
 #define V8TestInterfaceConstructor3_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h
index c16efa5..5a93b58 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceConstructor4_h
 #define V8TestInterfaceConstructor4_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h
index 66390fd..951e2b51 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceCustomConstructor_h
 #define V8TestInterfaceCustomConstructor_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h
index d0decd9..824db7f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceDocument_h
 #define V8TestInterfaceDocument_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h
index 281c88cfc..79c42e7b1 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceEmpty_h
 #define V8TestInterfaceEmpty_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h
index cf723e5..d963c0a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceEventInitConstructor_h
 #define V8TestInterfaceEventInitConstructor_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h
index 78ed2da..835332d 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceEventTarget_h
 #define V8TestInterfaceEventTarget_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h
index 1fd97f58..3c166544 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceGarbageCollected_h
 #define V8TestInterfaceGarbageCollected_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h
index ead51a45..76064ba 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceNamedConstructor_h
 #define V8TestInterfaceNamedConstructor_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h
index 44f5fd3..d83ea250 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceNamedConstructor2_h
 #define V8TestInterfaceNamedConstructor2_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h
index 37854b6..68eb4d7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceNode_h
 #define V8TestInterfaceNode_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h
index 7ce26df..657cf71 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceOriginTrialEnabled_h
 #define V8TestInterfaceOriginTrialEnabled_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h
index 3ef0bfa..b44c8a8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfaceSecureContext_h
 #define V8TestInterfaceSecureContext_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h
index f1004b18..d051b42 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.h
@@ -7,6 +7,7 @@
 #ifndef V8TestNode_h
 #define V8TestNode_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h
index e88e2b78..784230e7c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.h
@@ -10,6 +10,7 @@
 #include "bindings/core/v8/ArrayBufferOrArrayBufferViewOrDictionary.h"
 #include "bindings/core/v8/BooleanOrStringOrUnrestrictedDouble.h"
 #include "bindings/core/v8/DoubleOrString.h"
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/StringOrArrayBufferOrArrayBufferView.h"
 #include "bindings/core/v8/StringOrDouble.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h
index 25ecde1..430112e 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.h
@@ -7,6 +7,7 @@
 #ifndef V8TestSpecialOperations_h
 #define V8TestSpecialOperations_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/NodeOrNodeList.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h
index 08c7959..03a640ee 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.h
@@ -7,6 +7,7 @@
 #ifndef V8TestSpecialOperationsNotEnumerable_h
 #define V8TestSpecialOperationsNotEnumerable_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h
index f0d1846d..423b3faf 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.h
@@ -7,6 +7,7 @@
 #ifndef V8TestTypedefs_h
 #define V8TestTypedefs_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/StringOrDouble.h"
 #include "bindings/core/v8/TestInterfaceOrTestInterfaceEmpty.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h
index a7496b2..b226bbd 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8Uint8ClampedArray.h
@@ -7,6 +7,7 @@
 #ifndef V8Uint8ClampedArray_h
 #define V8Uint8ClampedArray_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8ArrayBufferView.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.h
index c2ad05a..5e2182c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterface2Partial_h
 #define V8TestInterface2Partial_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h
index 1686173..90d59bc 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.h
@@ -8,6 +8,7 @@
 #define V8TestInterface5_h
 
 #include "bindings/core/v8/DoubleOrString.h"
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.h b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.h
index 9a50bb5d..1b84b57 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.h
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.h
@@ -7,6 +7,7 @@
 #ifndef V8TestInterfacePartial_h
 #define V8TestInterfacePartial_h
 
+#include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/ScriptWrappable.h"
 #include "bindings/core/v8/ToV8.h"
 #include "bindings/core/v8/V8Binding.h"
diff --git a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl
index 4e44a08..f7a525b 100644
--- a/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl
+++ b/third_party/WebKit/Source/core/animation/AnimationEffectTiming.idl
@@ -14,8 +14,6 @@
     [RaisesException=Setter] attribute double iterationStart;
     [RaisesException=Setter] attribute unrestricted double iterations;
     [RaisesException=Setter] attribute (unrestricted double or DOMString) duration;
-    // TODO(dstockwell): playbackRate has been removed from level 1.
-    attribute double playbackRate;
     attribute DOMString direction;
     [RaisesException=Setter] attribute DOMString easing;
 };
diff --git a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
index 1358343e..d43ebba4 100644
--- a/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
+++ b/third_party/WebKit/Source/core/animation/AnimationTimeline.idl
@@ -4,14 +4,11 @@
 
 // http://www.w3.org/TR/web-animations/#the-animationtimeline-interface
 
-// TODO(dstockwell): This interface has several changes in the latest spec:
-// https://w3c.github.io/web-animations/#the-animationtimeline-interface
-
 [
     RuntimeEnabled=WebAnimationsAPI,
 ] interface AnimationTimeline {
     attribute double? currentTime;
-    attribute double playbackRate;
-    Animation play(AnimationEffectReadOnly source);
+
+    // TODO(crbug.com/624639): Move getAnimations() to DocumentAnimatable
     sequence<Animation> getAnimations();
 };
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
index b679ca8..18afe756 100644
--- a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
@@ -434,7 +434,7 @@
 void addCompositorKeyframeWithTimingFunction(PlatformAnimationCurveType& curve, const PlatformAnimationKeyframeType& keyframe, const TimingFunction* timingFunction)
 {
     if (!timingFunction) {
-        curve.addCubicBezierKeyframe(keyframe, CubicBezierTimingFunction::EaseType::EASE);
+        curve.addCubicBezierKeyframe(keyframe, *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE));
         return;
     }
 
@@ -445,16 +445,13 @@
 
     case TimingFunction::Type::CUBIC_BEZIER: {
         const CubicBezierTimingFunction& cubic = toCubicBezierTimingFunction(*timingFunction);
-        if (cubic.getEaseType() == CubicBezierTimingFunction::EaseType::CUSTOM)
-            curve.addCubicBezierKeyframe(keyframe, cubic.x1(), cubic.y1(), cubic.x2(), cubic.y2());
-        else
-            curve.addCubicBezierKeyframe(keyframe, cubic.getEaseType());
+        curve.addCubicBezierKeyframe(keyframe, cubic);
         break;
     }
 
     case TimingFunction::Type::STEPS: {
         const StepsTimingFunction& steps = toStepsTimingFunction(*timingFunction);
-        curve.addStepsKeyframe(keyframe, steps.numberOfSteps(), steps.getStepPosition());
+        curve.addStepsKeyframe(keyframe, steps);
         break;
     }
 
@@ -478,16 +475,13 @@
 
     case TimingFunction::Type::CUBIC_BEZIER: {
         const CubicBezierTimingFunction& cubic = toCubicBezierTimingFunction(*timingFunction);
-        if (cubic.getEaseType() == CubicBezierTimingFunction::EaseType::CUSTOM)
-            curve.setCubicBezierTimingFunction(cubic.x1(), cubic.y1(), cubic.x2(), cubic.y2());
-        else
-            curve.setCubicBezierTimingFunction(cubic.getEaseType());
+        curve.setCubicBezierTimingFunction(cubic);
         break;
     }
 
     case TimingFunction::Type::STEPS: {
         const StepsTimingFunction& steps = toStepsTimingFunction(*timingFunction);
-        curve.setStepsTimingFunction(steps.numberOfSteps(), steps.getStepPosition());
+        curve.setStepsTimingFunction(steps);
         break;
     }
 
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi
index 40b1340..ea144c1 100644
--- a/third_party/WebKit/Source/core/core.gypi
+++ b/third_party/WebKit/Source/core/core.gypi
@@ -543,6 +543,8 @@
             'layout/api/SelectionState.h',
             'layout/ng/LayoutNGBlockFlow.cpp',
             'layout/ng/LayoutNGBlockFlow.h',
+            'layout/ng/NGBlockLayoutAlgorithm.cpp',
+            'layout/ng/NGBlockLayoutAlgorithm.h',
             'layout/ng/NGConstraintSpace.cpp',
             'layout/ng/NGConstraintSpace.h',
             'layout/ng/NGFragment.cpp',
@@ -4078,6 +4080,7 @@
             'dom/shadow/FlatTreeTraversalTest.cpp',
             'editing/EditingCommandTest.cpp',
             'editing/EditingStrategyTest.cpp',
+            'editing/EditingStyleTest.cpp',
             'editing/EditingTestBase.cpp',
             'editing/EditingTestBase.h',
             'editing/EditingUtilitiesTest.cpp',
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
index 3b86029..72ace2c4 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -141,17 +141,6 @@
     return value.value();
 }
 
-String StylePropertySerializer::StylePropertySetForSerializer::getPropertyValue(CSSPropertyID propertyID) const
-{
-    if (!hasExpandedAllProperty())
-        return m_propertySet->getPropertyValue(propertyID);
-
-    const CSSValue* value = getPropertyCSSValue(propertyID);
-    if (!value)
-        return String();
-    return value->cssText();
-}
-
 bool StylePropertySerializer::StylePropertySetForSerializer::isPropertyImplicit(CSSPropertyID propertyID) const
 {
     int index = findPropertyIndex(propertyID);
@@ -161,15 +150,6 @@
     return value.isImplicit();
 }
 
-bool StylePropertySerializer::StylePropertySetForSerializer::propertyIsImportant(CSSPropertyID propertyID) const
-{
-    int index = findPropertyIndex(propertyID);
-    if (index == -1)
-        return false;
-    StylePropertySerializer::PropertyValueForSerializer value = propertyAt(index);
-    return value.isImportant();
-}
-
 StylePropertySerializer::StylePropertySerializer(const StylePropertySet& properties)
     : m_propertySet(properties)
 {
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.h b/third_party/WebKit/Source/core/css/StylePropertySerializer.h
index b2a7881..457df8d 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySerializer.h
+++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.h
@@ -109,9 +109,7 @@
         bool shouldProcessPropertyAt(unsigned index) const;
         int findPropertyIndex(CSSPropertyID) const;
         const CSSValue* getPropertyCSSValue(CSSPropertyID) const;
-        String getPropertyValue(CSSPropertyID) const;
         bool isPropertyImplicit(CSSPropertyID) const;
-        bool propertyIsImportant(CSSPropertyID) const;
 
         DECLARE_TRACE();
 
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.cpp b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
index 1671630d..a3bcaea4 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySet.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
@@ -290,6 +290,8 @@
 
 bool MutableStylePropertySet::setProperty(CSSPropertyID unresolvedProperty, const String& value, bool important, StyleSheetContents* contextStyleSheet)
 {
+    DCHECK_GE(unresolvedProperty, firstCSSProperty);
+
     // Setting the value to an empty string just removes the property in both IE and Gecko.
     // Setting it to null seems to produce less consistent results, but we treat it just the same.
     if (value.isEmpty())
diff --git a/third_party/WebKit/Source/core/css/html.css b/third_party/WebKit/Source/core/css/html.css
index f078286..52d3407 100644
--- a/third_party/WebKit/Source/core/css/html.css
+++ b/third_party/WebKit/Source/core/css/html.css
@@ -688,8 +688,8 @@
 }
 
 input[type="color" i][list]::-webkit-color-swatch-wrapper {
-    padding-left: 8px;
-    padding-right: 24px;
+    -webkit-padding-start: 8px;
+    -webkit-padding-end: 24px;
 }
 
 input[type="color" i][list]::-webkit-color-swatch {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
index ac95dbbf..282bc3a 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
+++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizer.cpp
@@ -364,86 +364,47 @@
     return CSSParserToken(DelimiterToken, cc);
 }
 
-static NumericSign getSign(CSSTokenizerInputStream& input, unsigned& offset)
-{
-    UChar next = input.peekWithoutReplacement(0);
-    if (next == '+') {
-        ++offset;
-        return PlusSign;
-    }
-    if (next == '-') {
-        ++offset;
-        return MinusSign;
-    }
-    return NoSign;
-}
-
-static double getInteger(CSSTokenizerInputStream& input, unsigned& offset)
-{
-    unsigned intStartPos = offset;
-    offset = input.skipWhilePredicate<isASCIIDigit>(offset);
-    unsigned intEndPos = offset;
-    return input.getDouble(intStartPos, intEndPos);
-}
-
-static double getFraction(CSSTokenizerInputStream& input, unsigned& offset)
-{
-    if (input.peekWithoutReplacement(offset) != '.'
-        || !isASCIIDigit(input.peekWithoutReplacement(offset + 1)))
-        return 0;
-    unsigned startOffset = offset;
-    offset = input.skipWhilePredicate<isASCIIDigit>(offset + 1);
-    return input.getDouble(startOffset, offset);
-}
-
-static double getExponent(CSSTokenizerInputStream& input, unsigned& offset, int& sign)
-{
-    unsigned exponentStartPos = 0;
-    unsigned exponentEndPos = 0;
-    UChar next = input.peekWithoutReplacement(offset);
-    if (next != 'E' && next != 'e')
-        return 0;
-    int offsetBeforeExponent = offset;
-    ++offset;
-    next = input.peekWithoutReplacement(offset);
-    if (next == '+') {
-        ++offset;
-    } else if (next =='-') {
-        sign = -1;
-        ++offset;
-    }
-    exponentStartPos = offset;
-    offset = input.skipWhilePredicate<isASCIIDigit>(offset);
-    exponentEndPos = offset;
-    if (exponentEndPos == exponentStartPos)
-        offset = offsetBeforeExponent;
-    return input.getDouble(exponentStartPos, exponentEndPos);
-}
-
 // This method merges the following spec sections for efficiency
 // http://www.w3.org/TR/css3-syntax/#consume-a-number
 // http://www.w3.org/TR/css3-syntax/#convert-a-string-to-a-number
 CSSParserToken CSSTokenizer::consumeNumber()
 {
     ASSERT(nextCharsAreNumber());
+
     NumericValueType type = IntegerValueType;
-    double value = 0;
-    unsigned offset = 0;
-    int exponentSign = 1;
-    NumericSign sign = getSign(m_input, offset);
-    double integerPart = getInteger(m_input, offset);
-    unsigned integerPartEndOffset = offset;
+    NumericSign sign = NoSign;
+    unsigned numberLength = 0;
 
-    double fractionPart = getFraction(m_input, offset);
-    double exponentPart = getExponent(m_input, offset, exponentSign);
-    double exponent = pow(10, (float)exponentSign * (double)exponentPart);
-    value = ((double)integerPart + fractionPart) * exponent;
-    if (sign == MinusSign)
-        value = -value;
+    UChar next = m_input.peekWithoutReplacement(0);
+    if (next == '+') {
+        ++numberLength;
+        sign = PlusSign;
+    } else if (next == '-') {
+        ++numberLength;
+        sign = MinusSign;
+    }
 
-    m_input.advance(offset);
-    if (offset != integerPartEndOffset)
+    numberLength = m_input.skipWhilePredicate<isASCIIDigit>(numberLength);
+    next = m_input.peekWithoutReplacement(numberLength);
+    if (next == '.' && isASCIIDigit(m_input.peekWithoutReplacement(numberLength + 1))) {
         type = NumberValueType;
+        numberLength = m_input.skipWhilePredicate<isASCIIDigit>(numberLength + 2);
+        next = m_input.peekWithoutReplacement(numberLength);
+    }
+
+    if (next == 'E' || next == 'e') {
+        next = m_input.peekWithoutReplacement(numberLength + 1);
+        if (isASCIIDigit(next)) {
+            type = NumberValueType;
+            numberLength = m_input.skipWhilePredicate<isASCIIDigit>(numberLength + 1);
+        } else if ((next == '+' || next == '-') && isASCIIDigit(m_input.peekWithoutReplacement(numberLength + 2))) {
+            type = NumberValueType;
+            numberLength = m_input.skipWhilePredicate<isASCIIDigit>(numberLength + 3);
+        }
+    }
+
+    double value = m_input.getDouble(0, numberLength);
+    m_input.advance(numberLength);
 
     return CSSParserToken(NumberToken, value, type, sign);
 }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSTokenizerInputStream.h b/third_party/WebKit/Source/core/css/parser/CSSTokenizerInputStream.h
index ededc8b1..18c9e80b 100644
--- a/third_party/WebKit/Source/core/css/parser/CSSTokenizerInputStream.h
+++ b/third_party/WebKit/Source/core/css/parser/CSSTokenizerInputStream.h
@@ -50,8 +50,15 @@
     template<bool characterPredicate(UChar)>
     unsigned skipWhilePredicate(unsigned offset)
     {
-        while ((m_offset + offset) < m_stringLength && characterPredicate((*m_string)[m_offset + offset]))
-            ++offset;
+        if (m_string->is8Bit()) {
+            const LChar* characters8 = m_string->characters8();
+            while ((m_offset + offset) < m_stringLength && characterPredicate(characters8[m_offset + offset]))
+                ++offset;
+        } else {
+            const UChar* characters16 = m_string->characters16();
+            while ((m_offset + offset) < m_stringLength && characterPredicate(characters16[m_offset + offset]))
+                ++offset;
+        }
         return offset;
     }
 
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index cb25b3e..b160cb46 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -1431,12 +1431,14 @@
 }
 
 template <CSSPropertyPriority priority>
-void StyleResolver::applyPropertiesForApplyAtRule(StyleResolverState& state, const CSSValue& value, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
+void StyleResolver::applyPropertiesForApplyAtRule(StyleResolverState& state, const CSSValue& value, bool isImportant, PropertyWhitelistType propertyWhitelistType)
 {
+    state.style()->setHasVariableReferenceFromNonInheritedProperty();
     if (!state.style()->variables())
         return;
     const String& name = toCSSCustomIdentValue(value).value();
     const StylePropertySet* propertySet = state.customPropertySetForApplyAtRule(name);
+    bool inheritedOnly = false;
     if (propertySet)
         applyProperties<priority>(state, propertySet, isImportant, inheritedOnly, propertyWhitelistType);
 }
@@ -1450,7 +1452,8 @@
         CSSPropertyID property = current.id();
 
         if (property == CSSPropertyApplyAtRule) {
-            applyPropertiesForApplyAtRule<priority>(state, current.value(), isImportant, inheritedOnly, propertyWhitelistType);
+            DCHECK(!inheritedOnly);
+            applyPropertiesForApplyAtRule<priority>(state, current.value(), isImportant, propertyWhitelistType);
             continue;
         }
 
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
index e6149fb..98f0863 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.h
@@ -208,7 +208,7 @@
     template <CSSPropertyPriority priority>
     void applyAllProperty(StyleResolverState&, const CSSValue&, bool inheritedOnly, PropertyWhitelistType);
     template <CSSPropertyPriority priority>
-    void applyPropertiesForApplyAtRule(StyleResolverState&, const CSSValue&, bool isImportant, bool inheritedOnly, PropertyWhitelistType);
+    void applyPropertiesForApplyAtRule(StyleResolverState&, const CSSValue&, bool isImportant, PropertyWhitelistType);
 
     bool pseudoStyleForElementInternal(Element&, const PseudoStyleRequest&, const ComputedStyle* parentStyle, StyleResolverState&);
     bool hasAuthorBackground(const StyleResolverState&);
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 289c6b57..499b9ea 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -95,6 +95,7 @@
 #include "core/frame/ScrollToOptions.h"
 #include "core/frame/Settings.h"
 #include "core/frame/UseCounter.h"
+#include "core/frame/VisualViewport.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/html/ClassList.h"
 #include "core/html/HTMLCanvasElement.h"
@@ -1015,6 +1016,20 @@
     return view->contentsToViewport(result);
 }
 
+IntRect Element::visibleBoundsInVisualViewport() const
+{
+    if (!layoutObject() || !document().page())
+        return IntRect();
+    // TODO(tkent): Can we check invisibility by scrollable non-frame elements?
+
+    IntSize viewportSize = document().page()->frameHost().visualViewport().size();
+    IntRect rect(0, 0, viewportSize.width(), viewportSize.height());
+    // We don't use absoluteBoundingBoxRect() because it can return an IntRect
+    // larger the actual size by 1px. crbug.com/470503
+    rect.intersect(document().view()->contentsToViewport(roundedIntRect(layoutObject()->absoluteBoundingBoxFloatRect())));
+    return rect;
+}
+
 ClientRectList* Element::getClientRects()
 {
     document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(this);
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h
index 673c4e4..b35cb50 100644
--- a/third_party/WebKit/Source/core/dom/Element.h
+++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -220,6 +220,10 @@
     virtual void scrollTo(const ScrollToOptions&);
 
     IntRect boundsInViewport() const;
+    // Returns an intersection rectangle of the bounds rectangle and the
+    // viewport rectangle, in the visual viewport coordinate. This function is
+    // used to show popups beside this element.
+    IntRect visibleBoundsInVisualViewport() const;
 
     ClientRectList* getClientRects();
     ClientRect* getBoundingClientRect();
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
index 163cbfb..edca536 100644
--- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp
+++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -1180,7 +1180,7 @@
         }
 
         if (mode == OverrideValues || (mode == DoNotOverrideValues && !value))
-            m_mutableStyle->setProperty(property.id(), property.value().cssText(), property.isImportant());
+            m_mutableStyle->setProperty(property.toCSSProperty());
     }
 }
 
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.h b/third_party/WebKit/Source/core/editing/EditingStyle.h
index c5215dc..0c397e9 100644
--- a/third_party/WebKit/Source/core/editing/EditingStyle.h
+++ b/third_party/WebKit/Source/core/editing/EditingStyle.h
@@ -34,6 +34,7 @@
 
 #include "core/CSSPropertyNames.h"
 #include "core/CSSValueKeywords.h"
+#include "core/CoreExport.h"
 #include "core/editing/Position.h"
 #include "core/editing/VisibleSelection.h"
 #include "core/editing/WritingDirection.h"
@@ -57,7 +58,7 @@
 class ComputedStyle;
 class StylePropertySet;
 
-class EditingStyle final : public GarbageCollected<EditingStyle> {
+class CORE_EXPORT EditingStyle final : public GarbageCollected<EditingStyle> {
 public:
 
     enum PropertiesToInclude { AllProperties, OnlyEditingInheritableProperties, EditingPropertiesInEffect };
diff --git a/third_party/WebKit/Source/core/editing/EditingStyleTest.cpp b/third_party/WebKit/Source/core/editing/EditingStyleTest.cpp
new file mode 100644
index 0000000..1e08e2e
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/EditingStyleTest.cpp
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/editing/EditingStyle.h"
+
+#include "core/css/StylePropertySet.h"
+#include "core/dom/Document.h"
+#include "core/editing/EditingTestBase.h"
+#include "core/html/HTMLBodyElement.h"
+#include "core/html/HTMLDivElement.h"
+#include "core/html/HTMLHeadElement.h"
+#include "core/html/HTMLHtmlElement.h"
+
+namespace blink {
+
+class EditingStyleTest : public EditingTestBase {
+};
+
+TEST_F(EditingStyleTest, mergeInlineStyleOfElement)
+{
+    setBodyContent(
+        "<span id=s1 style='--A:var(---B)'>1</span>"
+        "<span id=s2 style='float:var(--C)'>2</span>");
+    updateAllLifecyclePhases();
+
+    EditingStyle* editingStyle = EditingStyle::create(
+        toHTMLElement(document().getElementById("s2")));
+    editingStyle->mergeInlineStyleOfElement(
+        toHTMLElement(document().getElementById("s1")),
+        EditingStyle::OverrideValues);
+
+    EXPECT_FALSE(editingStyle->style()->hasProperty(CSSPropertyFloat))
+        << "Don't merge a property with unresolved value";
+    EXPECT_EQ(
+        "var(---B)",
+        editingStyle->style()->getPropertyValue(AtomicString("--A")))
+        << "Keep unresolved value on merging style";
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
index e36cea4..c093057 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -500,7 +500,7 @@
     if (range.isNull())
         return false;
 
-    return frame().selection().setSelectedRange(range, VP_DEFAULT_AFFINITY, SelectionDirectionalMode::NonDirectional, FrameSelection::CloseTyping);
+    return frame().selection().setSelectedRange(range, VP_DEFAULT_AFFINITY, SelectionDirectionalMode::NonDirectional, NotUserTriggered);
 }
 
 bool InputMethodController::setEditableSelectionOffsets(const PlainTextRange& selectionOffsets)
diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
index 0d41845..8f50a34 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
@@ -7,6 +7,7 @@
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
 #include "core/dom/Range.h"
+#include "core/editing/Editor.h"
 #include "core/editing/FrameSelection.h"
 #include "core/events/MouseEvent.h"
 #include "core/frame/FrameView.h"
@@ -379,6 +380,25 @@
     EXPECT_EQ(3u, controller().getSelectionOffsets().end());
 }
 
+TEST_F(InputMethodControllerTest, InsertLineBreakWhileComposingText)
+{
+    Element* div = insertHTMLElement(
+        "<div id='sample' contenteditable='true'></div>",
+        "sample");
+
+    Vector<CompositionUnderline> underlines;
+    underlines.append(CompositionUnderline(0, 5, Color(255, 0, 0), false, 0));
+    controller().setComposition("hello", underlines, 5, 5);
+    EXPECT_STREQ("hello", div->innerText().utf8().data());
+    EXPECT_EQ(5u, controller().getSelectionOffsets().start());
+    EXPECT_EQ(5u, controller().getSelectionOffsets().end());
+
+    frame().editor().insertLineBreak();
+    EXPECT_STREQ("\n\n", div->innerText().utf8().data());
+    EXPECT_EQ(1u, controller().getSelectionOffsets().start());
+    EXPECT_EQ(1u, controller().getSelectionOffsets().end());
+}
+
 TEST_F(InputMethodControllerTest, CompositionInputEventIsComposing)
 {
     document().settings()->setScriptEnabled(true);
diff --git a/third_party/WebKit/Source/core/events/EventTarget.cpp b/third_party/WebKit/Source/core/events/EventTarget.cpp
index 90bcd0a..b1aea0a 100644
--- a/third_party/WebKit/Source/core/events/EventTarget.cpp
+++ b/third_party/WebKit/Source/core/events/EventTarget.cpp
@@ -566,8 +566,7 @@
 
     if (checkTypeThenUseCount(event, EventTypeNames::beforeunload, UseCounter::DocumentBeforeUnloadFired)) {
         if (LocalDOMWindow* executingWindow = this->executingWindow()) {
-            // TODO(mustaq): Is the |if| condition correct? crbug.com/635029
-            if (executingWindow->top())
+            if (executingWindow != executingWindow->top())
                 UseCounter::count(executingWindow->document(), UseCounter::SubFrameBeforeUnloadFired);
         }
     } else if (checkTypeThenUseCount(event, EventTypeNames::unload, UseCounter::DocumentUnloadFired)) {
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSourceList.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSourceList.cpp
index 698ae97..00180ad 100644
--- a/third_party/WebKit/Source/core/frame/csp/CSPSourceList.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/CSPSourceList.cpp
@@ -47,15 +47,16 @@
 
 bool CSPSourceList::matches(const KURL& url, ResourceRequest::RedirectStatus redirectStatus) const
 {
-    // The CSP spec specifically states that data:, blob:, and filesystem URLs
-    // should not be captured by a '*" source
-    // (http://www.w3.org/TR/CSP2/#source-list-guid-matching). Thus, in the
-    // case of a full wildcard, data:, blob:, and filesystem: URLs are
+    // The CSP spec specifically states that only http:, https:, ws: and wss: should
+    // be captured by a '*" source.
+    // (https://w3c.github.io/webappsec-csp/#match-url-to-source-expression). Thus,
+    // in the case of a full wildcard, URLs with any other schemes are
     // explicitly checked for in the source list before allowing them through.
     if (m_allowStar) {
-        if (url.protocolIs("blob") || url.protocolIs("data") || url.protocolIs("filesystem"))
-            return hasSourceMatchInList(url, redirectStatus);
-        return true;
+        if (url.protocolIsInHTTPFamily() || url.protocolIs("ws") || url.protocolIs("wss"))
+            return true;
+
+        return hasSourceMatchInList(url, redirectStatus);
     }
 
     KURL effectiveURL = m_policy->selfMatchesInnerURL() && SecurityOrigin::shouldUseInnerURL(url) ? SecurityOrigin::extractInnerURL(url) : url;
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSourceListTest.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSourceListTest.cpp
index 8b3bd3c..4860ab0 100644
--- a/third_party/WebKit/Source/core/frame/csp/CSPSourceListTest.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/CSPSourceListTest.cpp
@@ -89,6 +89,8 @@
     EXPECT_FALSE(sourceList.matches(KURL(base, "data:https://example.test/")));
     EXPECT_FALSE(sourceList.matches(KURL(base, "blob:https://example.test/")));
     EXPECT_FALSE(sourceList.matches(KURL(base, "filesystem:https://example.test/")));
+    EXPECT_FALSE(sourceList.matches(KURL(base, "file:///etc/hosts")));
+    EXPECT_FALSE(sourceList.matches(KURL(base, "applewebdata://example.test/")));
 }
 
 TEST_F(CSPSourceListTest, BasicMatchingSelf)
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
index 7ca8bc14..a3ad40d6 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -1822,18 +1822,6 @@
     return element.computedStyle() ? element.computedStyle() : element.ensureComputedStyle();
 }
 
-IntRect HTMLSelectElement::elementRectRelativeToViewport() const
-{
-    if (!layoutObject())
-        return IntRect();
-    // Initialize with this frame rectangle relative to the viewport.
-    IntRect rect = document().view()->convertToRootFrame(document().view()->boundsRect());
-    // We don't use absoluteBoundingBoxRect() because it can return an IntRect
-    // larger the actual size by 1px.
-    rect.intersect(document().view()->contentsToViewport(roundedIntRect(layoutObject()->absoluteBoundingBoxFloatRect())));
-    return rect;
-}
-
 LayoutUnit HTMLSelectElement::clientPaddingLeft() const
 {
     if (layoutObject() && layoutObject()->isMenuList())
@@ -1920,12 +1908,8 @@
         return;
     if (!layoutObject() || !layoutObject()->isMenuList())
         return;
-    // Disable visibility check on Android.  elementRectRelativeToViewport()
-    // doesn't work well on Android WebView.  crbug.com/632561
-#if !OS(ANDROID)
-    if (elementRectRelativeToViewport().isEmpty())
+    if (visibleBoundsInVisualViewport().isEmpty())
         return;
-#endif
 
     if (!m_popup)
         m_popup = document().frameHost()->chromeClient().openPopupMenu(*document().frame(), *this);
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
index 08d0bb72..502e4e1 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -144,7 +144,6 @@
     // itemComputedStyle() returns nullptr only if the owner Document is not
     // active.  So, It returns a valid object when we open a popup.
     const ComputedStyle* itemComputedStyle(Element&) const;
-    IntRect elementRectRelativeToViewport() const;
     // Text starting offset in LTR.
     LayoutUnit clientPaddingLeft() const;
     // Text starting offset in RTL.
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp
index 135cbe1..b14fd976 100644
--- a/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp
@@ -133,13 +133,13 @@
     EXPECT_EQ(nullptr, toHTMLSelectElement(element)->optionToBeShown());
 }
 
-TEST_F(HTMLSelectElementTest, ElementRectRelativeToViewport)
+TEST_F(HTMLSelectElementTest, VisibleBoundsInVisualViewport)
 {
     document().documentElement()->setInnerHTML("<select style='position:fixed; top:12.3px; height:24px; -webkit-appearance:none;'><option>o1</select>", ASSERT_NO_EXCEPTION);
     document().view()->updateAllLifecyclePhases();
     HTMLSelectElement* select = toHTMLSelectElement(document().body()->firstChild());
     ASSERT(select);
-    IntRect bounds = select->elementRectRelativeToViewport();
+    IntRect bounds = select->visibleBoundsInVisualViewport();
     EXPECT_EQ(24, bounds.height());
 }
 
diff --git a/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp b/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp
index 80fb277..3713320 100644
--- a/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp
+++ b/third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp
@@ -119,13 +119,11 @@
 
 static bool startsOpeningScriptTagAt(const String& string, size_t start)
 {
-    return start + 6 < string.length() && string[start] == '<'
-        && WTF::toASCIILowerUnchecked(string[start + 1]) == 's'
-        && WTF::toASCIILowerUnchecked(string[start + 2]) == 'c'
-        && WTF::toASCIILowerUnchecked(string[start + 3]) == 'r'
-        && WTF::toASCIILowerUnchecked(string[start + 4]) == 'i'
-        && WTF::toASCIILowerUnchecked(string[start + 5]) == 'p'
-        && WTF::toASCIILowerUnchecked(string[start + 6]) == 't';
+    if (start + 6 >= string.length())
+        return false;
+    // TODO(esprehn): StringView should probably have startsWith.
+    StringView script("<script");
+    return equalIgnoringASCIICase(StringView(string, start, script.length()), script);
 }
 
 // If other files need this, we should move this to core/html/parser/HTMLParserIdioms.h
diff --git a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
index 842318f..04556f88 100644
--- a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
@@ -98,8 +98,10 @@
         innerStyle.setAlignSelfPosition(ItemPositionFlexStart);
     }
 
-    innerStyle.setPaddingLeft(Length(LayoutTheme::theme().popupInternalPaddingLeft(styleRef()), Fixed));
-    innerStyle.setPaddingRight(Length(LayoutTheme::theme().popupInternalPaddingRight(styleRef()), Fixed));
+    Length paddingStart = Length(LayoutTheme::theme().popupInternalPaddingStart(styleRef()), Fixed);
+    Length paddingEnd = Length(LayoutTheme::theme().popupInternalPaddingEnd(styleRef()), Fixed);
+    innerStyle.setPaddingLeft(styleRef().direction() == LTR ? paddingStart : paddingEnd);
+    innerStyle.setPaddingRight(styleRef().direction() == LTR ? paddingEnd : paddingStart);
     innerStyle.setPaddingTop(Length(LayoutTheme::theme().popupInternalPaddingTop(styleRef()), Fixed));
     innerStyle.setPaddingBottom(Length(LayoutTheme::theme().popupInternalPaddingBottom(styleRef()), Fixed));
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 41dba4e..6ec3f1e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -66,6 +66,7 @@
 #include "core/layout/LayoutTableRow.h"
 #include "core/layout/LayoutTheme.h"
 #include "core/layout/LayoutView.h"
+#include "core/layout/ng/LayoutNGBlockFlow.h"
 #include "core/page/AutoscrollController.h"
 #include "core/page/Page.h"
 #include "core/paint/ObjectPaintProperties.h"
@@ -187,6 +188,8 @@
         return new LayoutInline(element);
     case BLOCK:
     case INLINE_BLOCK:
+        if (RuntimeEnabledFeatures::layoutNGEnabled())
+            return new LayoutNGBlockFlow(element);
         return new LayoutBlockFlow(element);
     case LIST_ITEM:
         return new LayoutListItem(element);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTheme.h b/third_party/WebKit/Source/core/layout/LayoutTheme.h
index 84ad07a9..b86c70a 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTheme.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTheme.h
@@ -146,8 +146,8 @@
 
     virtual void adjustSliderThumbSize(ComputedStyle&) const;
 
-    virtual int popupInternalPaddingLeft(const ComputedStyle&) const { return 0; }
-    virtual int popupInternalPaddingRight(const ComputedStyle&) const { return 0; }
+    virtual int popupInternalPaddingStart(const ComputedStyle&) const { return 0; }
+    virtual int popupInternalPaddingEnd(const ComputedStyle&) const { return 0; }
     virtual int popupInternalPaddingTop(const ComputedStyle&) const { return 0; }
     virtual int popupInternalPaddingBottom(const ComputedStyle&) const { return 0; }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp
index 4e581c6..18b4856 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.cpp
@@ -37,15 +37,6 @@
 
 namespace blink {
 
-enum PaddingType {
-    TopPadding,
-    RightPadding,
-    BottomPadding,
-    LeftPadding
-};
-
-static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
-
 // These values all match Safari/Win.
 static const float defaultControlFontPixelSize = 13;
 static const float defaultCancelButtonSize = 9;
@@ -340,24 +331,27 @@
     adjustMenuListStyle(style, e);
 }
 
-int LayoutThemeDefault::popupInternalPaddingLeft(const ComputedStyle& style) const
+// The following internal paddings are in addition to the user-supplied padding.
+// Matches the Firefox behavior.
+
+int LayoutThemeDefault::popupInternalPaddingStart(const ComputedStyle& style) const
 {
-    return menuListInternalPadding(style, LeftPadding);
+    return menuListInternalPadding(style, 4);
 }
 
-int LayoutThemeDefault::popupInternalPaddingRight(const ComputedStyle& style) const
+int LayoutThemeDefault::popupInternalPaddingEnd(const ComputedStyle& style) const
 {
-    return menuListInternalPadding(style, RightPadding);
+    return menuListInternalPadding(style, 4 + menuListArrowPaddingSize);
 }
 
 int LayoutThemeDefault::popupInternalPaddingTop(const ComputedStyle& style) const
 {
-    return menuListInternalPadding(style, TopPadding);
+    return menuListInternalPadding(style, 1);
 }
 
 int LayoutThemeDefault::popupInternalPaddingBottom(const ComputedStyle& style) const
 {
-    return menuListInternalPadding(style, BottomPadding);
+    return menuListInternalPadding(style, 1);
 }
 
 // static
@@ -366,21 +360,10 @@
     LayoutThemeFontProvider::setDefaultFontSize(fontSize);
 }
 
-int LayoutThemeDefault::menuListInternalPadding(const ComputedStyle& style, int paddingType) const
+int LayoutThemeDefault::menuListInternalPadding(const ComputedStyle& style, int padding) const
 {
     if (style.appearance() == NoControlPart)
         return 0;
-    // This internal padding is in addition to the user-supplied padding.
-    // Matches the FF behavior.
-    int padding = styledMenuListInternalPadding[paddingType];
-
-    // Reserve the space for right arrow here. The rest of the padding is
-    // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
-    // LayoutMenuList to lay out the individual items in the popup.
-    const int barType = style.direction() == LTR ? RightPadding : LeftPadding;
-    if (paddingType == barType)
-        padding += menuListArrowPaddingSize;
-
     return padding * style.effectiveZoom();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h
index e5f481f..4a7c151 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeDefault.h
@@ -109,8 +109,8 @@
     double animationDurationForProgressBar() const override;
 
     // These methods define the padding for the MenuList's inner block.
-    int popupInternalPaddingLeft(const ComputedStyle&) const override;
-    int popupInternalPaddingRight(const ComputedStyle&) const override;
+    int popupInternalPaddingStart(const ComputedStyle&) const override;
+    int popupInternalPaddingEnd(const ComputedStyle&) const override;
     int popupInternalPaddingTop(const ComputedStyle&) const override;
     int popupInternalPaddingBottom(const ComputedStyle&) const override;
 
@@ -134,7 +134,7 @@
 private:
     ThemePainter& painter() override { return m_painter; }
 
-    int menuListInternalPadding(const ComputedStyle&, int paddingType) const;
+    int menuListInternalPadding(const ComputedStyle&, int padding) const;
 
     static const RGBA32 defaultTapHighlightColor = 0x2e000000; // 18% black.
     static double m_caretBlinkInterval;
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeMac.h b/third_party/WebKit/Source/core/layout/LayoutThemeMac.h
index f6e11f9a..6a10499 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeMac.h
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeMac.h
@@ -66,8 +66,8 @@
     IntSize sliderTickSize() const override;
     int sliderTickOffsetFromTrackCenter() const override;
 
-    int popupInternalPaddingLeft(const ComputedStyle&) const override;
-    int popupInternalPaddingRight(const ComputedStyle&) const override;
+    int popupInternalPaddingStart(const ComputedStyle&) const override;
+    int popupInternalPaddingEnd(const ComputedStyle&) const override;
     int popupInternalPaddingTop(const ComputedStyle&) const override;
     int popupInternalPaddingBottom(const ComputedStyle&) const override;
 
@@ -147,8 +147,8 @@
     static constexpr float menuListBaseArrowHeight = 4.0f;
     static constexpr float menuListBaseArrowWidth = 5.0f;
     static constexpr float menuListBaseSpaceBetweenArrows = 2.0f;
-    static const int menuListArrowPaddingLeft = 4;
-    static const int menuListArrowPaddingRight = 4;
+    static const int menuListArrowPaddingStart = 4;
+    static const int menuListArrowPaddingEnd = 4;
     static const int sliderThumbWidth = 15;
     static const int sliderThumbHeight = 15;
     static const int sliderThumbShadowBlur = 1;
diff --git a/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm b/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
index 7c85b6e9..318293e 100644
--- a/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
+++ b/third_party/WebKit/Source/core/layout/LayoutThemeMac.mm
@@ -476,6 +476,10 @@
             return true;
         if (!style.height().isIntrinsicOrAuto())
             return true;
+        // NSPopUpButtonCell on macOS 10.9 doesn't support
+        // NSUserInterfaceLayoutDirectionRightToLeft.
+        if (IsOSMavericks() && style.direction() == RTL)
+            return true;
     }
     // Some other cells don't work well when scaled.
     if (style.effectiveZoom() != 1) {
@@ -747,31 +751,30 @@
 }
 
 static const int baseBorderRadius = 5;
-static const int styledPopupPaddingLeft = 8;
+static const int styledPopupPaddingStart = 8;
 static const int styledPopupPaddingTop = 1;
 static const int styledPopupPaddingBottom = 2;
 
 // These functions are called with MenuListPart or MenulistButtonPart appearance
 // by LayoutMenuList.
-int LayoutThemeMac::popupInternalPaddingLeft(const ComputedStyle& style) const
+int LayoutThemeMac::popupInternalPaddingStart(const ComputedStyle& style) const
 {
     if (style.appearance() == MenulistPart)
         return popupButtonPadding(controlSizeForFont(style))[ThemeMac::LeftMargin] * style.effectiveZoom();
     if (style.appearance() == MenulistButtonPart)
-        return styledPopupPaddingLeft * style.effectiveZoom();
+        return styledPopupPaddingStart * style.effectiveZoom();
     return 0;
 }
 
-int LayoutThemeMac::popupInternalPaddingRight(const ComputedStyle& style) const
+int LayoutThemeMac::popupInternalPaddingEnd(const ComputedStyle& style) const
 {
     if (style.appearance() == MenulistPart)
         return popupButtonPadding(controlSizeForFont(style))[ThemeMac::RightMargin] * style.effectiveZoom();
-    if (style.appearance() == MenulistButtonPart) {
-        float fontScale = style.fontSize() / baseFontSize;
-        float arrowWidth = menuListBaseArrowWidth * fontScale;
-        return static_cast<int>(ceilf(arrowWidth + (menuListArrowPaddingLeft + menuListArrowPaddingRight) * style.effectiveZoom()));
-    }
-    return 0;
+    if (style.appearance() != MenulistButtonPart)
+        return 0;
+    float fontScale = style.fontSize() / baseFontSize;
+    float arrowWidth = menuListBaseArrowWidth * fontScale;
+    return static_cast<int>(ceilf(arrowWidth + (menuListArrowPaddingStart + menuListArrowPaddingEnd) * style.effectiveZoom()));
 }
 
 int LayoutThemeMac::popupInternalPaddingTop(const ComputedStyle& style) const
@@ -817,6 +820,8 @@
     updateCheckedState(popupButton, object);
     updateEnabledState(popupButton, object);
     updatePressedState(popupButton, object);
+
+    popupButton.userInterfaceLayoutDirection = object.styleRef().direction() == LTR ? NSUserInterfaceLayoutDirectionLeftToRight : NSUserInterfaceLayoutDirectionRightToLeft;
 }
 
 const IntSize* LayoutThemeMac::menuListSizes() const
diff --git a/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h b/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
index c219881..7ebd9ba 100644
--- a/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
+++ b/third_party/WebKit/Source/core/layout/line/BreakingContextInlineHeaders.h
@@ -746,6 +746,10 @@
     // See: fast/css3-text/css3-word-break/word-break-all-wrap-with-floats.html
     float widthMeasurementAtLastBreakOpportunity = 0;
 
+#if OS(ANDROID)
+    // TODO(kojii): Temporary call getHyphenation() to measure the performance.
+    style.getFontDescription().localeOrDefault().getHyphenation();
+#endif
     Hyphenation* hyphenation = style.getHyphenation();
     bool disableSoftHyphen = style.getHyphens() == HyphensNone;
     float hyphenWidth = 0;
diff --git a/third_party/WebKit/Source/core/layout/ng/NGBlockLayoutAlgorithm.cpp b/third_party/WebKit/Source/core/layout/ng/NGBlockLayoutAlgorithm.cpp
new file mode 100644
index 0000000..b7d4b998
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/NGBlockLayoutAlgorithm.cpp
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/layout/ng/NGBlockLayoutAlgorithm.h"
+
+#include "core/layout/LayoutBox.h"
+#include "core/layout/ng/NGConstraintSpace.h"
+#include "core/style/ComputedStyle.h"
+
+namespace blink {
+
+NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm()
+{
+}
+
+NGConstraintSpace NGBlockLayoutAlgorithm::createConstraintSpaceFromLayoutObject(const LayoutBox& child)
+{
+    bool fixedInline = false, fixedBlock = false;
+    // XXX for orthogonal writing mode this is not right
+    LayoutUnit containerLogicalWidth = std::max(LayoutUnit(), child.containingBlockLogicalWidthForContent());
+    // XXX Make sure this height is correct
+    LayoutUnit containerLogicalHeight = child.containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
+    if (child.hasOverrideLogicalContentWidth()) {
+        containerLogicalWidth = child.overrideLogicalContentWidth();
+        fixedInline = true;
+    }
+    if (child.hasOverrideLogicalContentHeight()) {
+        containerLogicalWidth = child.overrideLogicalContentHeight();
+        fixedBlock = true;
+    }
+    NGConstraintSpace space(containerLogicalWidth, containerLogicalHeight);
+    // XXX vertical writing mode
+    space.setOverflowTriggersScrollbar(child.styleRef().overflowX() == OverflowAuto,
+        child.styleRef().overflowY() == OverflowAuto);
+    space.setFixedSize(fixedInline, fixedBlock);
+    return space;
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/NGBlockLayoutAlgorithm.h b/third_party/WebKit/Source/core/layout/ng/NGBlockLayoutAlgorithm.h
new file mode 100644
index 0000000..0fc44a2
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/NGBlockLayoutAlgorithm.h
@@ -0,0 +1,22 @@
+// 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 NGBlockLayoutAlgorithm_h
+#define NGBlockLayoutAlgorithm_h
+
+namespace blink {
+
+class LayoutBox;
+class NGConstraintSpace;
+
+class NGBlockLayoutAlgorithm {
+public:
+    NGBlockLayoutAlgorithm();
+
+    NGConstraintSpace createConstraintSpaceFromLayoutObject(const LayoutBox&);
+};
+
+} // namespace blink
+
+#endif // NGBlockLayoutAlgorithm_h
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
index f0076ae8..320c250 100644
--- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -180,7 +180,7 @@
     , m_progressTracker(ProgressTracker::create(frame))
     , m_loadType(FrameLoadTypeStandard)
     , m_inStopAllLoaders(false)
-    , m_checkTimer(TaskRunnerHelper::getLoadingTaskRunner(frame), this, &FrameLoader::checkTimerFired)
+    , m_checkTimer(TaskRunnerHelper::get(TaskType::Networking, frame), this, &FrameLoader::checkTimerFired)
     , m_didAccessInitialDocument(false)
     , m_forcedSandboxFlags(SandboxNone)
     , m_dispatchingDidClearWindowObjectInMainWorld(false)
diff --git a/third_party/WebKit/Source/core/paint/ThemePainterMac.mm b/third_party/WebKit/Source/core/paint/ThemePainterMac.mm
index 1b35b80..512f084a 100644
--- a/third_party/WebKit/Source/core/paint/ThemePainterMac.mm
+++ b/third_party/WebKit/Source/core/paint/ThemePainterMac.mm
@@ -260,10 +260,15 @@
     float centerY = bounds.y() + bounds.height() / 2.0f;
     float arrowHeight = LayoutThemeMac::menuListBaseArrowHeight * fontScale;
     float arrowWidth = LayoutThemeMac::menuListBaseArrowWidth * fontScale;
-    float leftEdge = bounds.maxX() - LayoutThemeMac::menuListArrowPaddingRight * o.styleRef().effectiveZoom() - arrowWidth;
     float spaceBetweenArrows = LayoutThemeMac::menuListBaseSpaceBetweenArrows * fontScale;
-
-    if (bounds.width() < arrowWidth + LayoutThemeMac::menuListArrowPaddingLeft * o.styleRef().effectiveZoom())
+    float scaledPaddingEnd = LayoutThemeMac::menuListArrowPaddingEnd * o.styleRef().effectiveZoom();
+    float leftEdge;
+    if (o.styleRef().direction() == LTR) {
+        leftEdge = bounds.maxX() - scaledPaddingEnd - arrowWidth;
+    } else {
+        leftEdge = bounds.x() + scaledPaddingEnd;
+    }
+    if (bounds.width() < arrowWidth + scaledPaddingEnd)
         return false;
 
     Color color = o.styleRef().visitedDependentColor(CSSPropertyColor);
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index fee328e2..99a0ddb 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -271,7 +271,7 @@
         unsigned m_styleType : 6; // PseudoId
         unsigned m_pseudoBits : 8;
         unsigned m_explicitInheritance : 1; // Explicitly inherits a non-inherited property
-        unsigned m_variableReference : 1; // A non-inherited property references a variable.
+        unsigned m_variableReference : 1; // A non-inherited property references a variable or @apply is used.
         unsigned m_unique : 1; // Style can not be shared.
 
         unsigned m_emptyState : 1;
diff --git a/third_party/WebKit/Source/devtools/.gitignore b/third_party/WebKit/Source/devtools/.gitignore
index 0ba62a5..a4006378 100644
--- a/third_party/WebKit/Source/devtools/.gitignore
+++ b/third_party/WebKit/Source/devtools/.gitignore
@@ -6,3 +6,6 @@
 *.vcproj*
 *.vcxproj*
 *.xcodeproj*
+node_modules
+config.gypi
+npm-debug.log
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index 1f06252..ba26940e 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -246,6 +246,7 @@
   helper_scripts = [
     "scripts/modular_build.py",
     "scripts/concatenate_application_code.py",
+    "scripts/rjsmin.py",
   ]
 
   inputs = helper_scripts + all_devtools_files + generated_scripts + [
diff --git a/third_party/WebKit/Source/devtools/devtools.gyp b/third_party/WebKit/Source/devtools/devtools.gyp
index 207fa3f..06611f4 100644
--- a/third_party/WebKit/Source/devtools/devtools.gyp
+++ b/third_party/WebKit/Source/devtools/devtools.gyp
@@ -253,6 +253,7 @@
                 'helper_scripts': [
                     'scripts/modular_build.py',
                     'scripts/concatenate_application_code.py',
+                    "scripts/rjsmin.py",
                 ],
                 'inputs': [
                     '<@(_script_name)',
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi
index 5ab2704d..1f04b761 100644
--- a/third_party/WebKit/Source/devtools/devtools.gypi
+++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -304,7 +304,7 @@
             'front_end/ui/SuggestBox.js',
             'front_end/ui/TabbedPane.js',
             'front_end/ui/TextPrompt.js',
-            'front_end/ui/ThrottledView.js',
+            'front_end/ui/ThrottledWidget.js',
             'front_end/ui/UIUtils.js',
             'front_end/ui/View.js',
             'front_end/ui/ViewportControl.js',
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/ARIAAttributesView.js b/third_party/WebKit/Source/devtools/front_end/accessibility/ARIAAttributesView.js
index b740bb2..0a6a22a 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/ARIAAttributesView.js
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/ARIAAttributesView.js
@@ -38,12 +38,6 @@
         var foundAttributes = (this._treeOutline.rootElement().childCount() !== 0);
         this._noPropertiesInfo.classList.toggle("hidden", foundAttributes);
         this._treeOutline.element.classList.toggle("hidden", !foundAttributes);
-        this._gotNodeForTest();
-    },
-
-    _gotNodeForTest: function()
-    {
-        // For sniffing in tests.
     },
 
     __proto__: WebInspector.AccessibilitySubPane.prototype
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js
index 7197e06..d799945 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/AccessibilitySidebarView.js
@@ -4,11 +4,11 @@
 
 /**
  * @constructor
- * @extends {WebInspector.ThrottledView}
+ * @extends {WebInspector.ThrottledWidget}
  */
 WebInspector.AccessibilitySidebarView = function()
 {
-    WebInspector.ThrottledView.call(this, WebInspector.UIString("Accessibility"));
+    WebInspector.ThrottledWidget.call(this);
     this._node = null;
     this._sidebarPaneStack = WebInspector.viewManager.createStackLocation();
     this._ariaSubPane = new WebInspector.ARIAAttributesPane();
@@ -44,24 +44,18 @@
         {
             if (this._axNodeSubPane)
                 this._axNodeSubPane.setAXNode(accessibilityNode);
-            this._accessibilityNodeUpdatedForTest();
         }
         var node = this.node();
         return WebInspector.AccessibilityModel.fromTarget(node.target()).getAXNode(node.id)
             .then(accessibilityNodeCallback.bind(this))
     },
 
-    _accessibilityNodeUpdatedForTest: function()
-    {
-         // For sniffing in tests.
-    },
-
     /**
      * @override
      */
     wasShown: function()
     {
-        WebInspector.ThrottledView.prototype.wasShown.call(this);
+        WebInspector.ThrottledWidget.prototype.wasShown.call(this);
 
         this._axNodeSubPane.setNode(this.node());
         this._ariaSubPane.setNode(this.node());
@@ -118,7 +112,7 @@
     },
 
 
-    __proto__: WebInspector.ThrottledView.prototype
+    __proto__: WebInspector.ThrottledWidget.prototype
 };
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/accessibility/module.json b/third_party/WebKit/Source/devtools/front_end/accessibility/module.json
index 4ea3f958..f1a4608 100644
--- a/third_party/WebKit/Source/devtools/front_end/accessibility/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/accessibility/module.json
@@ -1,8 +1,12 @@
 {
     "extensions": [
         {
-            "type": "@WebInspector.View",
-            "location": "elements-panel",
+            "type": "view",
+            "location": "elements-sidebar",
+            "id": "accessibility.view",
+            "title": "Accessibility",
+            "order": 10,
+            "persistence": "permanent",
             "className": "WebInspector.AccessibilitySidebarView"
         }
     ],
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js
index 51424e1..35d0bbf 100644
--- a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js
@@ -401,51 +401,29 @@
         }
     },
 
-    /**
-     * @param {!WebInspector.Panel} panel
-     * @return {!WebInspector.DOMBreakpointsSidebarPane.Proxy}
-     */
-    createProxy: function(panel)
-    {
-        var proxy = new WebInspector.DOMBreakpointsSidebarPane.Proxy(this, panel);
-        if (!this._proxies)
-            this._proxies = [];
-        this._proxies.push(proxy);
-        return proxy;
-    },
-
     __proto__: WebInspector.BreakpointsSidebarPaneBase.prototype
 }
 
 /**
  * @constructor
- * @extends {WebInspector.SimpleView}
- * @param {!WebInspector.DOMBreakpointsSidebarPane} pane
- * @param {!WebInspector.Panel} panel
+ * @extends {WebInspector.VBox}
  */
-WebInspector.DOMBreakpointsSidebarPane.Proxy = function(pane, panel)
+WebInspector.DOMBreakpointsSidebarPane.Proxy = function()
 {
-    WebInspector.SimpleView.call(this, WebInspector.UIString("DOM Breakpoints"));
+    WebInspector.VBox.call(this);
     this.registerRequiredCSS("components/breakpointsList.css");
-
-    this._wrappedPane = pane;
-    this._panel = panel;
 }
 
 WebInspector.DOMBreakpointsSidebarPane.Proxy.prototype = {
     wasShown: function()
     {
         WebInspector.SimpleView.prototype.wasShown.call(this);
-        this._reattachBody();
+        var pane = WebInspector.domBreakpointsSidebarPane;
+        if (pane.element.parentNode !== this.element)
+            pane.show(this.element);
     },
 
-    _reattachBody: function()
-    {
-        if (this._wrappedPane.element.parentNode !== this.element)
-            this._wrappedPane.show(this.element);
-    },
-
-    __proto__: WebInspector.SimpleView.prototype
+    __proto__: WebInspector.VBox.prototype
 }
 
 /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js b/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js
index 6741bdc..ccc42c20 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ColorSwatchPopoverIcon.js
@@ -33,9 +33,9 @@
     _createDOM: function(text)
     {
         this._element = createElement("nobr");
-        this._element.title = WebInspector.UIString("Open cubic bezier editor");
 
         this._iconElement = this._element.createChild("div", "popover-icon bezier-icon");
+        this._iconElement.title = WebInspector.UIString("Open cubic bezier editor");
         var svg = this._iconElement.createSVGChild("svg");
         svg.setAttribute("height", 10);
         svg.setAttribute("width", 10);
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js
index 4a9c780..d0db21e 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js
@@ -29,11 +29,11 @@
 
 /**
  * @constructor
- * @extends {WebInspector.ThrottledView}
+ * @extends {WebInspector.ThrottledWidget}
  */
 WebInspector.ComputedStyleWidget = function()
 {
-    WebInspector.ThrottledView.call(this, WebInspector.UIString("Computed Style"));
+    WebInspector.ThrottledWidget.call(this);
     this.element.classList.add("computed-style-sidebar-pane");
 
     this.registerRequiredCSS("elements/computedStyleSidebarPane.css");
@@ -356,5 +356,5 @@
         }
     },
 
-    __proto__: WebInspector.ThrottledView.prototype
+    __proto__: WebInspector.ThrottledWidget.prototype
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
index 024fda3..a22d5a3b 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -32,6 +32,7 @@
  * @constructor
  * @implements {WebInspector.Searchable}
  * @implements {WebInspector.TargetManager.Observer}
+ * @implements {WebInspector.ViewLocationResolver}
  * @extends {WebInspector.Panel}
  */
 WebInspector.ElementsPanel = function()
@@ -66,23 +67,16 @@
     this._breadcrumbs.show(crumbsContainer);
     this._breadcrumbs.addEventListener(WebInspector.ElementsBreadcrumbs.Events.NodeSelected, this._crumbNodeSelected, this);
 
-    this.sidebarPanes = {};
-    /** @type !Array<!WebInspector.View> */
-    this._elementsSidebarViews = [];
     this._currentToolbarPane = null;
 
-    this.sidebarPanes.styles = new WebInspector.StylesSidebarPane();
-    this.sidebarPanes.computedStyle = new WebInspector.ComputedStyleWidget();
-    this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
-    this.sidebarPanes.properties = new WebInspector.PropertiesWidget();
-    this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this);
-    this.sidebarPanes.eventListeners = new WebInspector.EventListenersWidget();
+    this._stylesWidget = new WebInspector.StylesSidebarPane();
+    this._computedStyleWidget = new WebInspector.ComputedStyleWidget();
+    this._metricsWidget = new WebInspector.MetricsSidebarPane();
 
-    this._stylesSidebarToolbar = this._createStylesSidebarToolbar(this.sidebarPanes.styles);
+    this._stylesSidebarToolbar = this._createStylesSidebarToolbar();
 
     WebInspector.moduleSetting("sidebarPosition").addChangeListener(this._updateSidebarPosition.bind(this));
     this._updateSidebarPosition();
-    this._loadSidebarViews();
 
     /** @type {!Array.<!WebInspector.ElementsTreeOutline>} */
     this._treeOutlines = [];
@@ -100,22 +94,20 @@
      */
     _revealProperty: function(cssProperty)
     {
-        var stylesSidebarPane = this.sidebarPanes.styles;
-        this.sidebarPaneView.showView(stylesSidebarPane);
-        stylesSidebarPane.revealProperty(/** @type {!WebInspector.CSSProperty} */(cssProperty));
-        return Promise.resolve();
+        return this.sidebarPaneView.showView(this._stylesViewToReveal).then(() => {
+            this._stylesWidget.revealProperty(/** @type {!WebInspector.CSSProperty} */(cssProperty));
+        });
     },
 
     /**
-     * @param {!WebInspector.StylesSidebarPane} ssp
      * @return {!Element}
      */
-    _createStylesSidebarToolbar: function(ssp)
+    _createStylesSidebarToolbar: function()
     {
         var container = createElementWithClass("div", "styles-sidebar-pane-toolbar-container");
         var hbox = container.createChild("div", "hbox styles-sidebar-pane-toolbar");
         var filterContainerElement = hbox.createChild("div", "styles-sidebar-pane-filter-box");
-        var filterInput = WebInspector.StylesSidebarPane.createPropertyFilterElement(WebInspector.UIString("Filter"), hbox, ssp.onFilterChanged.bind(ssp));
+        var filterInput = WebInspector.StylesSidebarPane.createPropertyFilterElement(WebInspector.UIString("Filter"), hbox, this._stylesWidget.onFilterChanged.bind(this._stylesWidget));
         filterContainerElement.appendChild(filterInput);
         var toolbar = new WebInspector.ExtensibleToolbar("styles-sidebarpane-toolbar", hbox);
         toolbar.element.classList.add("styles-pane-toolbar");
@@ -127,6 +119,16 @@
     },
 
     /**
+     * @override
+     * @param {string} locationName
+     * @return {?WebInspector.ViewLocation}
+     */
+    resolveLocation: function(locationName)
+    {
+        return this.sidebarPaneView;
+    },
+
+    /**
      * @param {?WebInspector.Widget} widget
      * @param {!WebInspector.ToolbarToggle=} toggle
      */
@@ -197,42 +199,6 @@
         }
     },
 
-    _loadSidebarViews: function()
-    {
-        var extensions = self.runtime.extensions("@WebInspector.View");
-
-        var promises = [];
-        for (var i = 0; i < extensions.length; ++i) {
-            var descriptor = extensions[i].descriptor();
-            if (descriptor["location"] !== "elements-panel")
-                continue;
-
-            var title = WebInspector.UIString(descriptor["title"]);
-            promises.push(extensions[i].instance().then(addSidebarView.bind(this, title)));
-        }
-
-        Promise.all(promises).then(this._sidebarViewsLoadedForTest.bind(this));
-
-        /**
-         * @param {string} title
-         * @param {!Object} object
-         * @this {WebInspector.ElementsPanel}
-         */
-        function addSidebarView(title, object)
-        {
-            var view = /** @type {!WebInspector.View} */ (object);
-            this._elementsSidebarViews.push(view);
-
-            if (this.sidebarPaneView)
-                this.sidebarPaneView.appendView(view);
-        }
-    },
-
-    _sidebarViewsLoadedForTest: function()
-    {
-        // For sniffing in tests.
-    },
-
     /**
      * @override
      * @param {!WebInspector.Target} target
@@ -767,7 +733,7 @@
         if (!treeOutline.editing()) {
             handleUndoRedo.call(null, treeOutline);
             if (event.handled) {
-                this.sidebarPanes.styles.forceUpdate();
+                this._stylesWidget.forceUpdate();
                 return;
             }
         }
@@ -875,18 +841,16 @@
         this._splitWidget.setVertical(!horizontally);
         this.showToolbarPane(null);
 
-        var computedPane = new WebInspector.SimpleView(WebInspector.UIString("Computed"));
-        computedPane.element.classList.add("composite");
-        computedPane.element.classList.add("fill");
-        computedPane.element.classList.add("metrics-and-computed");
-
         var matchedStylesContainer = new WebInspector.VBox();
         matchedStylesContainer.element.appendChild(this._stylesSidebarToolbar);
         var matchedStylePanesWrapper = new WebInspector.VBox();
         matchedStylePanesWrapper.element.classList.add("style-panes-wrapper");
         matchedStylePanesWrapper.show(matchedStylesContainer.element);
+        this._stylesWidget.show(matchedStylePanesWrapper.element);
+
         var computedStylePanesWrapper = new WebInspector.VBox();
         computedStylePanesWrapper.element.classList.add("style-panes-wrapper");
+        this._computedStyleWidget.show(computedStylePanesWrapper.element);
 
         /**
          * @param {boolean} inComputedStyle
@@ -895,9 +859,9 @@
         function showMetrics(inComputedStyle)
         {
             if (inComputedStyle)
-                this.sidebarPanes.metrics.show(computedStylePanesWrapper.element, this.sidebarPanes.computedStyle.element);
+                this._metricsWidget.show(computedStylePanesWrapper.element, this._computedStyleWidget.element);
             else
-                this.sidebarPanes.metrics.show(matchedStylePanesWrapper.element);
+                this._metricsWidget.show(matchedStylePanesWrapper.element);
         }
 
         /**
@@ -913,7 +877,7 @@
                 showMetrics.call(this, false);
         }
 
-        this.sidebarPaneView = WebInspector.viewManager.createTabbedLocation(() => WebInspector.inspectorView.setCurrentPanel(this), "elements-sidebar");
+        this.sidebarPaneView = WebInspector.viewManager.createTabbedLocation(() => WebInspector.inspectorView.setCurrentPanel(this));
         var tabbedPane = this.sidebarPaneView.tabbedPane();
         tabbedPane.element.addEventListener("contextmenu", this._sidebarContextMenuEventFired.bind(this), false);
         if (this._popoverHelper)
@@ -922,54 +886,39 @@
         this._popoverHelper.setTimeout(0);
 
         if (horizontally) {
+            // Styles and computed are merged into a single tab.
             this._splitWidget.installResizer(tabbedPane.headerElement());
 
-            var compositePane = new WebInspector.SimpleView(WebInspector.UIString("Styles"));
-            compositePane.element.classList.add("flex-auto");
+            var stylesView = new WebInspector.SimpleView(WebInspector.UIString("Styles"));
+            stylesView.element.classList.add("flex-auto");
 
             var splitWidget = new WebInspector.SplitWidget(true, true, "stylesPaneSplitViewState", 215);
-            splitWidget.show(compositePane.element);
+            splitWidget.show(stylesView.element);
 
             splitWidget.setMainWidget(matchedStylesContainer);
             splitWidget.setSidebarWidget(computedStylePanesWrapper);
 
-            computedPane.show(computedStylePanesWrapper.element);
-            this.sidebarPaneView.appendView(compositePane);
-
-            // TODO: remove
-            this.sidebarPanes.styles.setParentViewForReveal(compositePane);
-            this.sidebarPanes.computedStyle.setParentViewForReveal(compositePane);
-            this.sidebarPanes.metrics.setParentViewForReveal(compositePane);
+            this.sidebarPaneView.appendView(stylesView);
+            this._stylesViewToReveal = stylesView;
         } else {
-            var stylesPane = new WebInspector.SimpleView(WebInspector.UIString("Styles"));
-            stylesPane.element.classList.add("flex-auto", "metrics-and-styles");
+            // Styles and computed are in separate tabs.
+            var stylesView = new WebInspector.SimpleView(WebInspector.UIString("Styles"));
+            stylesView.element.classList.add("flex-auto", "metrics-and-styles");
+            matchedStylesContainer.show(stylesView.element);
 
-            matchedStylesContainer.show(stylesPane.element);
-            computedStylePanesWrapper.show(computedPane.element);
+            var computedView = new WebInspector.SimpleView(WebInspector.UIString("Computed"));
+            computedView.element.classList.add("composite", "fill", "metrics-and-computed");
+            computedStylePanesWrapper.show(computedView.element);
 
             tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, tabSelected, this);
-            this.sidebarPaneView.appendView(stylesPane);
-            this.sidebarPaneView.appendView(computedPane);
-
-            // TODO: remove
-            this.sidebarPanes.styles.setParentViewForReveal(stylesPane);
-            this.sidebarPanes.computedStyle.setParentViewForReveal(computedPane);
-            this.sidebarPanes.metrics.setParentViewForReveal(computedPane);
+            this.sidebarPaneView.appendView(stylesView);
+            this.sidebarPaneView.appendView(computedView);
+            this._stylesViewToReveal = stylesView;
         }
 
-        this.sidebarPanes.styles.show(matchedStylePanesWrapper.element);
-        this.sidebarPanes.computedStyle.show(computedStylePanesWrapper.element);
         showMetrics.call(this, horizontally);
 
-        this.sidebarPaneView.appendView(this.sidebarPanes.eventListeners);
-        this.sidebarPaneView.appendView(this.sidebarPanes.domBreakpoints);
-        this.sidebarPaneView.appendView(this.sidebarPanes.properties);
-
-        for (var sidebarViewWrapper of this._elementsSidebarViews)
-            this.sidebarPaneView.appendView(sidebarViewWrapper);
-
-        this._extensionSidebarPanesContainer = this.sidebarPaneView;
-
+        this.sidebarPaneView.appendApplicableItems("elements-sidebar");
         for (var i = 0; i < extensionSidebarPanes.length; ++i)
             this._addExtensionSidebarPane(extensionSidebarPanes[i]);
 
@@ -991,7 +940,7 @@
     _addExtensionSidebarPane: function(pane)
     {
         if (pane.panelName() === this.name)
-            this._extensionSidebarPanesContainer.appendView(pane);
+            this.sidebarPaneView.appendView(pane);
     },
 
     __proto__: WebInspector.Panel.prototype
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsSidebarPane.js
index 3af1ba3e..f569c139 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsSidebarPane.js
@@ -4,12 +4,11 @@
 
 /**
  * @constructor
- * @extends {WebInspector.SimpleView}
- * @param {string} title
+ * @extends {WebInspector.VBox}
  */
-WebInspector.ElementsSidebarPane = function(title)
+WebInspector.ElementsSidebarPane = function()
 {
-    WebInspector.SimpleView.call(this, title);
+    WebInspector.VBox.call(this);
     this.element.classList.add("flex-none");
     this._computedStyleModel = new WebInspector.ComputedStyleModel();
     this._computedStyleModel.addEventListener(WebInspector.ComputedStyleModel.Events.ComputedStyleChanged, this.onCSSModelChanged, this);
@@ -63,7 +62,7 @@
 
     wasShown: function()
     {
-        WebInspector.SimpleView.prototype.wasShown.call(this);
+        WebInspector.VBox.prototype.wasShown.call(this);
         if (this._updateWhenVisible)
             this.update();
     },
@@ -73,5 +72,5 @@
      */
     onCSSModelChanged: function(event) { },
 
-    __proto__: WebInspector.SimpleView.prototype
+    __proto__: WebInspector.VBox.prototype
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js
index b8fccb5..61ace32 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/EventListenersWidget.js
@@ -29,14 +29,15 @@
 
 /**
  * @constructor
- * @extends {WebInspector.ThrottledView}
+ * @extends {WebInspector.ThrottledWidget}
  */
 WebInspector.EventListenersWidget = function()
 {
-    WebInspector.ThrottledView.call(this, WebInspector.UIString("Event Listeners"));
+    WebInspector.ThrottledWidget.call(this);
     this.element.classList.add("events-pane");
+    var toolbar = new WebInspector.Toolbar("", this.contentElement);
 
-    this._showForAncestorsSetting = WebInspector.settings.createSetting("showEventListenersForAncestors", true);
+    this._showForAncestorsSetting = WebInspector.settings.moduleSetting("showEventListenersForAncestors");
     this._showForAncestorsSetting.addChangeListener(this.update.bind(this));
 
     this._dispatchFilterBySetting = WebInspector.settings.createSetting("eventListenerDispatchFilterType", WebInspector.EventListenersWidget.DispatchFilterBy.All);
@@ -48,8 +49,8 @@
 
     var refreshButton = new WebInspector.ToolbarButton(WebInspector.UIString("Refresh"), "refresh-toolbar-item");
     refreshButton.addEventListener("click", this.update.bind(this));
-    this.addToolbarItem(refreshButton);
-    this.addToolbarItem(new WebInspector.ToolbarCheckbox(WebInspector.UIString("Ancestors"), WebInspector.UIString("Show listeners on the ancestors"), this._showForAncestorsSetting));
+    toolbar.appendToolbarItem(refreshButton);
+    toolbar.appendToolbarItem(new WebInspector.ToolbarCheckbox(WebInspector.UIString("Ancestors"), WebInspector.UIString("Show listeners on the ancestors"), this._showForAncestorsSetting));
     var dispatchFilter = new WebInspector.ToolbarComboBox(this._onDispatchFilterTypeChanged.bind(this));
 
     /**
@@ -67,10 +68,11 @@
     addDispatchFilterOption.call(this, WebInspector.UIString("Passive"), WebInspector.EventListenersWidget.DispatchFilterBy.Passive);
     addDispatchFilterOption.call(this, WebInspector.UIString("Blocking"), WebInspector.EventListenersWidget.DispatchFilterBy.Blocking);
     dispatchFilter.setMaxWidth(200);
-    this.addToolbarItem(dispatchFilter);
-    this.addToolbarItem(new WebInspector.ToolbarCheckbox(WebInspector.UIString("Framework listeners"), WebInspector.UIString("Resolve event listeners bound with framework"), this._showFrameworkListenersSetting));
+    toolbar.appendToolbarItem(dispatchFilter);
+    toolbar.appendToolbarItem(new WebInspector.ToolbarCheckbox(WebInspector.UIString("Framework listeners"), WebInspector.UIString("Resolve event listeners bound with framework"), this._showFrameworkListenersSetting));
 
     WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this.update, this);
+    this.update();
 }
 
 WebInspector.EventListenersWidget.DispatchFilterBy = {
@@ -164,5 +166,5 @@
     {
     },
 
-    __proto__: WebInspector.ThrottledView.prototype
+    __proto__: WebInspector.ThrottledWidget.prototype
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js
index b770aea..d01e432 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/MetricsSidebarPane.js
@@ -32,7 +32,7 @@
  */
 WebInspector.MetricsSidebarPane = function()
 {
-    WebInspector.ElementsSidebarPane.call(this, WebInspector.UIString("Metrics"));
+    WebInspector.ElementsSidebarPane.call(this);
 }
 
 WebInspector.MetricsSidebarPane.prototype = {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js
index 140c347..92c35af 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js
@@ -30,12 +30,12 @@
 
 /**
  * @constructor
- * @extends {WebInspector.ThrottledView}
+ * @extends {WebInspector.ThrottledWidget}
  * @param {!WebInspector.ComputedStyleModel} sharedModel
  */
 WebInspector.PlatformFontsWidget = function(sharedModel)
 {
-    WebInspector.ThrottledView.call(this, WebInspector.UIString("Fonts"), true);
+    WebInspector.ThrottledWidget.call(this, true);
     this.registerRequiredCSS("elements/platformFontsWidget.css");
 
     this._sharedModel = sharedModel;
@@ -102,5 +102,5 @@
         }
     },
 
-    __proto__: WebInspector.ThrottledView.prototype
+    __proto__: WebInspector.ThrottledWidget.prototype
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/PropertiesWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/PropertiesWidget.js
index a8a26c6..3080b63 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/PropertiesWidget.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/PropertiesWidget.js
@@ -29,17 +29,19 @@
 
 /**
  * @constructor
- * @extends {WebInspector.ThrottledView}
+ * @extends {WebInspector.ThrottledWidget}
  */
 WebInspector.PropertiesWidget = function()
 {
-    WebInspector.ThrottledView.call(this, WebInspector.UIString("Properties"));
+    WebInspector.ThrottledWidget.call(this);
 
     WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.AttrModified, this._onNodeChange, this);
     WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.AttrRemoved, this._onNodeChange, this);
     WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.CharacterDataModified, this._onNodeChange, this);
     WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._onNodeChange, this);
     WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._setNode, this);
+    this._node = WebInspector.context.flavor(WebInspector.DOMNode);
+    this.update();
 }
 
 WebInspector.PropertiesWidget._objectGroupName = "properties-sidebar-pane";
@@ -180,5 +182,5 @@
         this.update();
     },
 
-    __proto__: WebInspector.ThrottledView.prototype
+    __proto__: WebInspector.ThrottledWidget.prototype
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
index 09990f3..a392a8ee 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -33,7 +33,7 @@
  */
 WebInspector.StylesSidebarPane = function()
 {
-    WebInspector.ElementsSidebarPane.call(this, WebInspector.UIString("Styles"));
+    WebInspector.ElementsSidebarPane.call(this);
     this.setMinimumSize(96, 26);
 
     WebInspector.moduleSetting("colorFormat").addChangeListener(this.update.bind(this));
@@ -425,7 +425,6 @@
      */
     _addBlankSection: function(insertAfterSection, styleSheetId, ruleLocation)
     {
-        this.revealView();
         var node = this.node();
         var blankSection = new WebInspector.BlankStylePropertiesSection(this, insertAfterSection._matchedStyles, node ? WebInspector.DOMPresentationUtils.simpleSelector(node) : "", styleSheetId, ruleLocation, insertAfterSection._style);
 
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css b/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css
index 7c2ac95..64f3efd 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/elements/elementsPanel.css
@@ -737,6 +737,10 @@
     margin: 0;
 }
 
+.events-pane .toolbar {
+    border-bottom: 1px solid #eee;
+}
+
 .style-properties li.editing {
     margin-left: 10px;
     text-overflow: clip;
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/module.json b/third_party/WebKit/Source/devtools/front_end/elements/module.json
index d2615ed..1bfc610 100644
--- a/third_party/WebKit/Source/devtools/front_end/elements/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/elements/module.json
@@ -87,6 +87,12 @@
             "defaultValue": true
         },
         {
+            "type": "setting",
+            "settingName": "showEventListenersForAncestors",
+            "settingType": "boolean",
+            "defaultValue": true
+        },
+        {
             "type": "@WebInspector.ToolbarItem.Provider",
             "className": "WebInspector.ElementStatePaneWidget.ButtonProvider",
             "order": 1,
@@ -167,6 +173,38 @@
             "order": 4,
             "location": "styles-sidebarpane-toolbar",
             "experiment": "layoutEditor"
+        },
+        {
+            "type": "@WebInspector.ViewLocationResolver",
+            "name": "elements-sidebar",
+            "className": "WebInspector.ElementsPanel"
+        },
+        {
+            "type": "view",
+            "location": "elements-sidebar",
+            "id": "elements.eventListeners",
+            "title": "Event Listeners",
+            "order": 5,
+            "persistence": "permanent",
+            "className": "WebInspector.EventListenersWidget"
+        },
+        {
+            "type": "view",
+            "location": "elements-sidebar",
+            "id": "elements.domBreakpoints",
+            "title": "DOM Breakpoints",
+            "order": 6,
+            "persistence": "permanent",
+            "factoryName": "WebInspector.DOMBreakpointsSidebarPane.Proxy"
+        },
+        {
+            "type": "view",
+            "location": "elements-sidebar",
+            "id": "elements.domProperties",
+            "title": "Properties",
+            "order": 7,
+            "persistence": "permanent",
+            "className": "WebInspector.PropertiesWidget"
         }
     ],
     "dependencies": [
diff --git a/third_party/WebKit/Source/devtools/front_end/main/Main.js b/third_party/WebKit/Source/devtools/front_end/main/Main.js
index 64c796c..eb7fcc5 100644
--- a/third_party/WebKit/Source/devtools/front_end/main/Main.js
+++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -1098,5 +1098,4 @@
     }
 }
 
-
 new WebInspector.Main();
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
index ab7e7cf..2bd7e4c 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkDataGridNode.js
@@ -381,7 +381,10 @@
             cell.setTextAndTitle(WebInspector.UIString("(from ServiceWorker)"));
             cell.classList.add("network-dim-cell");
         } else if (this._request.cached()) {
-            cell.setTextAndTitle(WebInspector.UIString("(from cache)"));
+            if (this._request.cachedInMemory())
+                cell.setTextAndTitle(WebInspector.UIString("(from memory cache)"));
+            else
+                cell.setTextAndTitle(WebInspector.UIString("(from disk cache)"));
             cell.classList.add("network-dim-cell");
         } else {
             var resourceSize = Number.bytesToString(this._request.resourceSize);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js b/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js
index 467952e..dcd77aec 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/RequestHeadersView.js
@@ -370,7 +370,10 @@
                 statusText += " " + WebInspector.UIString("(from ServiceWorker)");
                 statusTextElement.classList.add("status-from-cache");
             } else if (this._request.cached()) {
-                statusText += " " + WebInspector.UIString("(from cache)");
+                if (this._request.cachedInMemory())
+                    statusText += " " + WebInspector.UIString("(from memory cache)");
+                else
+                    statusText += " " + WebInspector.UIString("(from disk cache)");
                 statusTextElement.classList.add("status-from-cache");
             }
             statusTextElement.textContent = statusText;
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js
index d92a393..2f84bd2 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js
@@ -602,9 +602,9 @@
 {
     columns = columns || [
         {id: "object", title: WebInspector.UIString("Object"), disclosure: true, sortable: true},
-        {id: "distance", title: WebInspector.UIString("Distance"), width: "80px", sortable: true},
-        {id: "shallowSize", title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true},
-        {id: "retainedSize", title: WebInspector.UIString("Retained Size"), width: "120px", sortable: true, sort: WebInspector.DataGrid.Order.Descending}
+        {id: "distance", title: WebInspector.UIString("Distance"), width: "65px", sortable: true, fixedWidth: true},
+        {id: "shallowSize", title: WebInspector.UIString("Shallow Size"), width: "105px", sortable: true, fixedWidth: true},
+        {id: "retainedSize", title: WebInspector.UIString("Retained Size"), width: "105px", sortable: true, fixedWidth: true, sort: WebInspector.DataGrid.Order.Descending}
     ];
     WebInspector.HeapSnapshotSortableDataGrid.call(this, dataDisplayDelegate, columns);
 }
@@ -648,9 +648,9 @@
 {
     var columns = [
         {id: "object", title: WebInspector.UIString("Object"), disclosure: true, sortable: true},
-        {id: "distance", title: WebInspector.UIString("Distance"), width: "80px", sortable: true, sort: WebInspector.DataGrid.Order.Ascending},
-        {id: "shallowSize", title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true},
-        {id: "retainedSize", title: WebInspector.UIString("Retained Size"), width: "120px", sortable: true}
+        {id: "distance", title: WebInspector.UIString("Distance"), width: "65px", sortable: true, fixedWidth: true, sort: WebInspector.DataGrid.Order.Ascending},
+        {id: "shallowSize", title: WebInspector.UIString("Shallow Size"), width: "105px", sortable: true, fixedWidth: true},
+        {id: "retainedSize", title: WebInspector.UIString("Retained Size"), width: "105px", sortable: true, fixedWidth: true}
     ];
     WebInspector.HeapSnapshotContainmentDataGrid.call(this, dataDisplayDelegate, columns);
 }
@@ -705,10 +705,10 @@
 {
     var columns = [
         {id: "object", title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true},
-        {id: "distance", title: WebInspector.UIString("Distance"), width: "90px", sortable: true},
-        {id: "count", title: WebInspector.UIString("Objects Count"), width: "90px", sortable: true},
-        {id: "shallowSize", title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true},
-        {id: "retainedSize", title: WebInspector.UIString("Retained Size"), width: "120px", sort: WebInspector.DataGrid.Order.Descending, sortable: true}
+        {id: "distance", title: WebInspector.UIString("Distance"), width: "65px", sortable: true, fixedWidth: true},
+        {id: "count", title: WebInspector.UIString("Objects Count"), width: "90px", sortable: true, fixedWidth: true},
+        {id: "shallowSize", title: WebInspector.UIString("Shallow Size"), width: "105px", sortable: true, fixedWidth: true},
+        {id: "retainedSize", title: WebInspector.UIString("Retained Size"), width: "105px", sort: WebInspector.DataGrid.Order.Descending, sortable: true, fixedWidth: true}
     ];
     WebInspector.HeapSnapshotViewportDataGrid.call(this, dataDisplayDelegate, columns);
     this._profileIndex = -1;
@@ -876,12 +876,12 @@
 {
     var columns = [
         {id: "object", title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true},
-        {id: "addedCount", title: WebInspector.UIString("# New"), width: "72px", sortable: true},
-        {id: "removedCount", title: WebInspector.UIString("# Deleted"), width: "72px", sortable: true},
-        {id: "countDelta", title: WebInspector.UIString("# Delta"), width: "64px", sortable: true},
-        {id: "addedSize", title: WebInspector.UIString("Alloc. Size"), width: "72px", sortable: true, sort: WebInspector.DataGrid.Order.Descending},
-        {id: "removedSize", title: WebInspector.UIString("Freed Size"), width: "72px", sortable: true},
-        {id: "sizeDelta", title: WebInspector.UIString("Size Delta"), width: "72px", sortable: true}
+        {id: "addedCount", title: WebInspector.UIString("# New"), width: "72px", sortable: true, fixedWidth: true},
+        {id: "removedCount", title: WebInspector.UIString("# Deleted"), width: "72px", sortable: true, fixedWidth: true},
+        {id: "countDelta", title: WebInspector.UIString("# Delta"), width: "64px", sortable: true, fixedWidth: true},
+        {id: "addedSize", title: WebInspector.UIString("Alloc. Size"), width: "72px", sortable: true, fixedWidth: true, sort: WebInspector.DataGrid.Order.Descending},
+        {id: "removedSize", title: WebInspector.UIString("Freed Size"), width: "72px", sortable: true, fixedWidth: true},
+        {id: "sizeDelta", title: WebInspector.UIString("Size Delta"), width: "72px", sortable: true, fixedWidth: true}
     ];
     WebInspector.HeapSnapshotViewportDataGrid.call(this, dataDisplayDelegate, columns);
 }
@@ -969,10 +969,10 @@
 WebInspector.AllocationDataGrid = function(target, dataDisplayDelegate)
 {
     var columns = [
-        {id: "liveCount", title: WebInspector.UIString("Live Count"), width: "72px", sortable: true},
-        {id: "count", title: WebInspector.UIString("Count"), width: "72px", sortable: true},
-        {id: "liveSize", title: WebInspector.UIString("Live Size"), width: "72px", sortable: true},
-        {id: "size", title: WebInspector.UIString("Size"), width: "72px", sortable: true, sort: WebInspector.DataGrid.Order.Descending},
+        {id: "liveCount", title: WebInspector.UIString("Live Count"), width: "72px", sortable: true, fixedWidth: true},
+        {id: "count", title: WebInspector.UIString("Count"), width: "60px", sortable: true, fixedWidth: true},
+        {id: "liveSize", title: WebInspector.UIString("Live Size"), width: "72px", sortable: true, fixedWidth: true},
+        {id: "size", title: WebInspector.UIString("Size"), width: "72px", sortable: true, fixedWidth: true, sort: WebInspector.DataGrid.Order.Descending},
         {id: "name", title: WebInspector.UIString("Function"), disclosure: true, sortable: true},
     ];
     WebInspector.HeapSnapshotViewportDataGrid.call(this, dataDisplayDelegate, columns);
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/heapProfiler.css b/third_party/WebKit/Source/devtools/front_end/profiler/heapProfiler.css
index f5f7eaf..8db4de9 100644
--- a/third_party/WebKit/Source/devtools/front_end/profiler/heapProfiler.css
+++ b/third_party/WebKit/Source/devtools/front_end/profiler/heapProfiler.css
@@ -51,7 +51,7 @@
 }
 
 .heap-snapshot-view .data-grid span.percent-column {
-    width: 32px;
+    width: 34px !important;
 }
 
 .heap-snapshot-view .object-value-object,
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
index b6d620a..950dc6cb 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/NetworkRequest.js
@@ -463,6 +463,14 @@
         return (!!this._fromMemoryCache || !!this._fromDiskCache) && !this._transferSize;
     },
 
+    /**
+     * @return {boolean}
+     */
+    cachedInMemory: function()
+    {
+        return !!this._fromMemoryCache && !this._transferSize;
+    },
+
     setFromMemoryCache: function()
     {
         this._fromMemoryCache = true;
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 9f97ef7..db904e23 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -91,7 +91,6 @@
 
     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
     this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.breakpointManager, this.showUISourceCode.bind(this));
-    this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this);
     this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
     this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
     this.sidebarPanes.objectEventListeners = new WebInspector.ObjectEventListenersSidebarPane();
@@ -129,6 +128,14 @@
 WebInspector.SourcesPanel.prototype = {
     /**
      * @override
+     */
+    focus: function()
+    {
+        this._sourcesView.focus();
+    },
+
+    /**
+     * @override
      * @param {!WebInspector.Target} target
      */
     targetAdded: function(target)
@@ -219,7 +226,10 @@
      */
     resolveLocation: function(locationName)
     {
-        return this._navigatorTabbedLocation;
+        if (locationName === "sources-sidebar")
+            return this._sidebarPaneStack;
+        else
+            return this._navigatorTabbedLocation;
     },
 
     /**
@@ -1122,7 +1132,8 @@
         var vbox = new WebInspector.VBox();
         vbox.element.appendChild(this._debugToolbarDrawer);
         vbox.setMinimumAndPreferredSizes(25, 25, WebInspector.SourcesPanel.minToolbarWidth, 100);
-        this._sidebarPaneStack = WebInspector.viewManager.createStackLocation(this._setAsCurrentPanel.bind(this), "sources-sidebar");
+        this._sidebarPaneStack = WebInspector.viewManager.createStackLocation(this._setAsCurrentPanel.bind(this));
+        this._sidebarPaneStack.widget().element.classList.add("overflow-auto");
         this._sidebarPaneStack.widget().show(vbox.element);
         vbox.element.appendChild(this._debugToolbar.element);
 
@@ -1137,11 +1148,11 @@
         }
 
         this._sidebarPaneStack.showView(this.sidebarPanes.callstack);
-        this._sidebarPaneStack.showView(this.sidebarPanes.scopechain);
-        this._sidebarPaneStack.showView(this.sidebarPanes.jsBreakpoints);
 
         if (!vertically) {
             // Populate the rest of the stack.
+            this._sidebarPaneStack.showView(this.sidebarPanes.scopechain);
+            this._sidebarPaneStack.showView(this.sidebarPanes.jsBreakpoints);
             for (var pane in this.sidebarPanes) {
                 if (this.sidebarPanes[pane])
                     this._sidebarPaneStack.appendView(this.sidebarPanes[pane]);
@@ -1153,12 +1164,12 @@
             splitWidget.setMainWidget(vbox);
 
             // Populate the left stack.
-            this._sidebarPaneStack.appendView(this.sidebarPanes.domBreakpoints);
+            this._sidebarPaneStack.showView(this.sidebarPanes.jsBreakpoints);
             this._sidebarPaneStack.appendView(this.sidebarPanes.xhrBreakpoints);
             this._sidebarPaneStack.appendView(this.sidebarPanes.eventListenerBreakpoints);
             this._sidebarPaneStack.appendView(this.sidebarPanes.objectEventListeners);
 
-            var tabbedLocation = WebInspector.viewManager.createTabbedLocation(this._setAsCurrentPanel.bind(this), "sources-sidebar-tabs");
+            var tabbedLocation = WebInspector.viewManager.createTabbedLocation(this._setAsCurrentPanel.bind(this));
             splitWidget.setSidebarWidget(tabbedLocation.tabbedPane());
             tabbedLocation.appendView(this.sidebarPanes.scopechain);
             tabbedLocation.appendView(this.sidebarPanes.watchExpressions);
@@ -1166,6 +1177,7 @@
             this.sidebarPaneView = splitWidget;
         }
 
+        this._sidebarPaneStack.appendApplicableItems("sources-sidebar");
         var extensionSidebarPanes = WebInspector.extensionServer.sidebarPanes();
         for (var i = 0; i < extensionSidebarPanes.length; ++i)
             this._addExtensionSidebarPane(extensionSidebarPanes[i]);
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 e70e693..1da852f6 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sources/module.json
@@ -365,6 +365,20 @@
             "type": "@WebInspector.ViewLocationResolver",
             "name": "navigator-view",
             "className": "WebInspector.SourcesPanel"
+        },
+        {
+            "type": "@WebInspector.ViewLocationResolver",
+            "name": "sources-sidebar",
+            "className": "WebInspector.SourcesPanel"
+        },
+        {
+            "type": "view",
+            "location": "sources-sidebar",
+            "id": "sources.domBreakpoints",
+            "title": "DOM Breakpoints",
+            "order": 7,
+            "persistence": "permanent",
+            "factoryName": "WebInspector.DOMBreakpointsSidebarPane.Proxy"
         }
     ],
     "dependencies": [
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css b/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css
index 8ee0bd29..efa5287f 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css
+++ b/third_party/WebKit/Source/devtools/front_end/sources/sourcesPanel.css
@@ -263,3 +263,7 @@
     color: #888;
     background-color: #FFFFC2;
 }
+
+.event-listeners-sidebar-pane .toolbar {
+    border-bottom: 1px solid #eee;
+}
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ThrottledView.js b/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js
similarity index 74%
rename from third_party/WebKit/Source/devtools/front_end/ui/ThrottledView.js
rename to third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js
index 650d552..e545cf8 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/ThrottledView.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/ThrottledWidget.js
@@ -4,18 +4,17 @@
 
 /**
  * @constructor
- * @extends {WebInspector.SimpleView}
- * @param {string} title
+ * @extends {WebInspector.VBox}
  * @param {boolean=} isWebComponent
  */
-WebInspector.ThrottledView = function(title, isWebComponent)
+WebInspector.ThrottledWidget = function(isWebComponent)
 {
-    WebInspector.SimpleView.call(this, title, isWebComponent);
+    WebInspector.VBox.call(this, isWebComponent);
     this._updateThrottler = new WebInspector.Throttler(100);
     this._updateWhenVisible = false;
 }
 
-WebInspector.ThrottledView.prototype = {
+WebInspector.ThrottledWidget.prototype = {
     /**
      * @protected
      * @return {!Promise.<?>}
@@ -33,7 +32,7 @@
         this._updateThrottler.schedule(innerUpdate.bind(this));
 
         /**
-         * @this {WebInspector.ThrottledView}
+         * @this {WebInspector.ThrottledWidget}
          * @return {!Promise.<?>}
          */
         function innerUpdate()
@@ -52,10 +51,10 @@
      */
     wasShown: function()
     {
-        WebInspector.SimpleView.prototype.wasShown.call(this);
+        WebInspector.VBox.prototype.wasShown.call(this);
         if (this._updateWhenVisible)
             this.update();
     },
 
-    __proto__: WebInspector.SimpleView.prototype
+    __proto__: WebInspector.VBox.prototype
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/View.js b/third_party/WebKit/Source/devtools/front_end/ui/View.js
index 608bb09..8add555 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/View.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/View.js
@@ -132,15 +132,7 @@
      */
     revealView: function()
     {
-        return WebInspector.viewManager.revealView(this._parentViewToReveal || this);
-    },
-
-    /**
-     * @param {!WebInspector.View} view
-     */
-    setParentViewForReveal: function(view)
-    {
-        this._parentViewToReveal = view;
+        return WebInspector.viewManager.revealView(this);
     },
 
     __proto__: WebInspector.VBox.prototype
@@ -219,6 +211,11 @@
 
 WebInspector.ViewLocation.prototype = {
     /**
+     * @param {string} locationName
+     */
+    appendApplicableItems: function(locationName) { },
+
+    /**
      * @param {!WebInspector.View} view
      * @param {?WebInspector.View=} insertBefore
      */
@@ -330,7 +327,7 @@
 
         var resolverExtensions = self.runtime.extensions(WebInspector.ViewLocationResolver).filter(extension => extension.descriptor()["name"] === location);
         if (!resolverExtensions.length)
-            return /** @type {!Promise<?WebInspector.ViewManager._Location>} */ (Promise.resolve(null));
+            throw new Error("Unresolved location: " + location);
         var resolverExtension = resolverExtensions[0];
         return resolverExtension.instance().then(resolver => /** @type {?WebInspector.ViewManager._Location} */(resolver.resolveLocation(location)));
     },
@@ -503,13 +500,11 @@
  * @param {!WebInspector.ViewManager} manager
  * @param {!WebInspector.Widget} widget
  * @param {function()=} revealCallback
- * @param {string=} location
  */
-WebInspector.ViewManager._Location = function(manager, widget, revealCallback, location)
+WebInspector.ViewManager._Location = function(manager, widget, revealCallback)
 {
     this._manager = manager;
     this._revealCallback = revealCallback;
-    this._location = location;
     this._widget = widget;
 }
 
@@ -543,7 +538,7 @@
 WebInspector.ViewManager._TabbedLocation = function(manager, revealCallback, location, restoreSelection)
 {
     this._tabbedPane = new WebInspector.TabbedPane();
-    WebInspector.ViewManager._Location.call(this, manager, this._tabbedPane, revealCallback, location);
+    WebInspector.ViewManager._Location.call(this, manager, this._tabbedPane, revealCallback);
 
     this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
     this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabClosed, this._tabClosed, this);
@@ -553,7 +548,9 @@
 
     /** @type {!Map.<string, !WebInspector.View>} */
     this._views = new Map();
-    this._populateLocation();
+
+    if (location)
+        this.appendApplicableItems(location);
 }
 
 WebInspector.ViewManager._TabbedLocation.prototype = {
@@ -586,11 +583,13 @@
         this._tabbedPane.disableOverflowMenu();
     },
 
-    _populateLocation: function()
+    /**
+     * @override
+     * @param {string} locationName
+     */
+    appendApplicableItems: function(locationName)
     {
-        if (!this._location)
-            return;
-        for (var view of this._manager._viewsForLocation(this._location)) {
+        for (var view of this._manager._viewsForLocation(locationName)) {
             var id = view.viewId();
             this._views.set(id, view);
             view[WebInspector.ViewManager._Location.symbol] = this;
@@ -721,11 +720,13 @@
 WebInspector.ViewManager._StackLocation = function(manager, revealCallback, location)
 {
     this._vbox = new WebInspector.VBox();
-    WebInspector.ViewManager._Location.call(this, manager, this._vbox, revealCallback, location);
+    WebInspector.ViewManager._Location.call(this, manager, this._vbox, revealCallback);
 
     /** @type {!Map<string, !WebInspector.ViewManager._ExpandableContainerWidget>} */
     this._expandableContainers = new Map();
-    this._populateLocation();
+
+    if (location)
+        this.appendApplicableItems(location);
 }
 
 WebInspector.ViewManager._StackLocation.prototype = {
@@ -764,11 +765,13 @@
         return container._expand();
     },
 
-    _populateLocation: function()
+    /**
+     * @override
+     * @param {string} locationName
+     */
+    appendApplicableItems: function(locationName)
     {
-        if (!this._location)
-            return;
-        for (var view of this._manager._viewsForLocation(this._location))
+        for (var view of this._manager._viewsForLocation(locationName))
             this.appendView(view);
     },
 
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/module.json b/third_party/WebKit/Source/devtools/front_end/ui/module.json
index 54ac23fd..e5871636 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/ui/module.json
@@ -40,7 +40,7 @@
         "StackView.js",
         "SwatchPopoverHelper.js",
         "TextPrompt.js",
-        "ThrottledView.js",
+        "ThrottledWidget.js",
         "Toolbar.js",
         "Tooltip.js",
         "SuggestBox.js",
diff --git a/third_party/WebKit/Source/devtools/scripts/rjsmin.py b/third_party/WebKit/Source/devtools/scripts/rjsmin.py
index 8357a6d..2d15e03 100755
--- a/third_party/WebKit/Source/devtools/scripts/rjsmin.py
+++ b/third_party/WebKit/Source/devtools/scripts/rjsmin.py
@@ -99,7 +99,8 @@
     string1 = \
         r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'
     string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'
-    strings = r'(?:%s|%s)' % (string1, string2)
+    string3 = r'(?:`(?:[^`\\]|\\.)*`)'
+    strings = r'(?:%s|%s|%s)' % (string1, string2, string3)
 
     charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
     nospecial = r'[^/\\\[\r\n]'
@@ -162,7 +163,7 @@
     id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
     id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')
 
-    dull = r'[^\047"/\000-\040]'
+    dull = r'[^\047"`/\000-\040]'
 
     space_sub = _re.compile((
         r'(%(dull)s+)'
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
index 9759a2f..e2961a98 100644
--- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
+++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -25,6 +25,7 @@
 #include "mojo/public/cpp/bindings/wtf_array.h"
 #include "platform/mojo/MojoHelper.h"
 #include "public/platform/InterfaceProvider.h"
+#include "public/platform/WebTraceLocation.h"
 #include "wtf/HashSet.h"
 #include <utility>
 
@@ -488,6 +489,7 @@
 
 void PaymentRequest::onCompleteTimeoutForTesting()
 {
+    m_completeTimer.stop();
     onCompleteTimeout(0);
 }
 
@@ -686,7 +688,6 @@
 
 void PaymentRequest::onCompleteTimeout(TimerBase*)
 {
-    m_completeTimer.stop();
     m_paymentProvider->Complete(mojom::blink::PaymentComplete(Fail));
     clearResolversAndCloseMojoConnection();
 }
diff --git a/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp b/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp
index 6e4bba14..87fa7f0 100644
--- a/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp
+++ b/third_party/WebKit/Source/modules/webshare/NavigatorShare.cpp
@@ -10,6 +10,7 @@
 #include "core/frame/LocalFrame.h"
 #include "core/frame/Navigator.h"
 #include "modules/webshare/ShareData.h"
+#include "platform/UserGestureIndicator.h"
 #include "platform/mojo/MojoHelper.h"
 #include "public/platform/InterfaceProvider.h"
 #include "public/platform/Platform.h"
@@ -81,6 +82,11 @@
 
 ScriptPromise NavigatorShare::share(ScriptState* scriptState, const ShareData& shareData)
 {
+    if (!UserGestureIndicator::utilizeUserGesture()) {
+        DOMException* error = DOMException::create(SecurityError, "Must be handling a user gesture to perform a share request.");
+        return ScriptPromise::rejectWithDOMException(scriptState, error);
+    }
+
     if (!m_service) {
         Document* doc = toDocument(scriptState->getExecutionContext());
         DCHECK(doc);
diff --git a/third_party/WebKit/Source/platform/LayoutLocale.cpp b/third_party/WebKit/Source/platform/LayoutLocale.cpp
index a5578dab9..0af11b7 100644
--- a/third_party/WebKit/Source/platform/LayoutLocale.cpp
+++ b/third_party/WebKit/Source/platform/LayoutLocale.cpp
@@ -55,16 +55,6 @@
     return m_stringForSkFontMgr.data();
 }
 
-static bool isUnambiguousHanScript(UScriptCode script)
-{
-    // localeToScriptCodeForFontSelection() does not return these values.
-    DCHECK(script != USCRIPT_HIRAGANA && script != USCRIPT_KATAKANA);
-    return script == USCRIPT_KATAKANA_OR_HIRAGANA
-        || script == USCRIPT_SIMPLIFIED_HAN
-        || script == USCRIPT_TRADITIONAL_HAN
-        || script == USCRIPT_HANGUL;
-}
-
 void LayoutLocale::computeScriptForHan() const
 {
     if (isUnambiguousHanScript(m_script)) {
diff --git a/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp b/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp
index 05fbef9d..b634c0c 100644
--- a/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp
+++ b/third_party/WebKit/Source/platform/LayoutLocaleTest.cpp
@@ -41,6 +41,10 @@
     } tests[] = {
         { "en-US", USCRIPT_LATIN },
 
+        // Common lang-script.
+        { "en-Latn", USCRIPT_LATIN },
+        { "ar-Arab", USCRIPT_ARABIC },
+
         // Common lang-region in East Asia.
         { "ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, true },
         { "ko-KR", USCRIPT_HANGUL, true },
diff --git a/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.cpp b/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.cpp
index a6d8bab6..778d2c2a 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.cpp
+++ b/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.cpp
@@ -30,28 +30,20 @@
 
 }
 
-void CompositorFilterAnimationCurve::addCubicBezierKeyframe(const CompositorFilterKeyframe& keyframe, CubicBezierTimingFunction::EaseType easeType)
+void CompositorFilterAnimationCurve::addCubicBezierKeyframe(const CompositorFilterKeyframe& keyframe, const TimingFunction& timingFunction)
 {
     const cc::FilterOperations& filterOperations = keyframe.value().asFilterOperations();
     m_curve->AddKeyframe(cc::FilterKeyframe::Create(
         base::TimeDelta::FromSecondsD(keyframe.time()), filterOperations,
-        cc::CubicBezierTimingFunction::CreatePreset(easeType)));
+        timingFunction.cloneToCC()));
 }
 
-void CompositorFilterAnimationCurve::addCubicBezierKeyframe(const CompositorFilterKeyframe& keyframe, double x1, double y1, double x2, double y2)
+void CompositorFilterAnimationCurve::addStepsKeyframe(const CompositorFilterKeyframe& keyframe, const TimingFunction& timingFunction)
 {
     const cc::FilterOperations& filterOperations = keyframe.value().asFilterOperations();
     m_curve->AddKeyframe(cc::FilterKeyframe::Create(
         base::TimeDelta::FromSecondsD(keyframe.time()), filterOperations,
-        cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)));
-}
-
-void CompositorFilterAnimationCurve::addStepsKeyframe(const CompositorFilterKeyframe& keyframe, int steps, StepsTimingFunction::StepPosition stepPosition)
-{
-    const cc::FilterOperations& filterOperations = keyframe.value().asFilterOperations();
-    m_curve->AddKeyframe(cc::FilterKeyframe::Create(
-        base::TimeDelta::FromSecondsD(keyframe.time()), filterOperations,
-        cc::StepsTimingFunction::Create(steps, stepPosition)));
+        timingFunction.cloneToCC()));
 }
 
 void CompositorFilterAnimationCurve::setLinearTimingFunction()
@@ -59,19 +51,14 @@
     m_curve->SetTimingFunction(nullptr);
 }
 
-void CompositorFilterAnimationCurve::setCubicBezierTimingFunction(CubicBezierTimingFunction::EaseType easeType)
+void CompositorFilterAnimationCurve::setCubicBezierTimingFunction(const TimingFunction& timingFunction)
 {
-    m_curve->SetTimingFunction(cc::CubicBezierTimingFunction::CreatePreset(easeType));
+    m_curve->SetTimingFunction(timingFunction.cloneToCC());
 }
 
-void CompositorFilterAnimationCurve::setCubicBezierTimingFunction(double x1, double y1, double x2, double y2)
+void CompositorFilterAnimationCurve::setStepsTimingFunction(const TimingFunction& timingFunction)
 {
-    m_curve->SetTimingFunction(cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2));
-}
-
-void CompositorFilterAnimationCurve::setStepsTimingFunction(int numberOfSteps, StepsTimingFunction::StepPosition stepPosition)
-{
-    m_curve->SetTimingFunction(cc::StepsTimingFunction::Create(numberOfSteps, stepPosition));
+    m_curve->SetTimingFunction(timingFunction.cloneToCC());
 }
 
 std::unique_ptr<cc::AnimationCurve> CompositorFilterAnimationCurve::cloneToAnimationCurve() const
diff --git a/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.h b/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.h
index 4b621f1..820d825 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.h
+++ b/third_party/WebKit/Source/platform/animation/CompositorFilterAnimationCurve.h
@@ -34,16 +34,12 @@
     ~CompositorFilterAnimationCurve() override;
 
     void addLinearKeyframe(const CompositorFilterKeyframe&);
-    void addCubicBezierKeyframe(const CompositorFilterKeyframe&, CubicBezierTimingFunction::EaseType);
-    // Adds the keyframe with a custom, bezier timing function. Note, it is
-    // assumed that x0 = y0, and x3 = y3 = 1.
-    void addCubicBezierKeyframe(const CompositorFilterKeyframe&, double x1, double y1, double x2, double y2);
-    void addStepsKeyframe(const CompositorFilterKeyframe&, int steps, StepsTimingFunction::StepPosition);
+    void addCubicBezierKeyframe(const CompositorFilterKeyframe&, const TimingFunction&);
+    void addStepsKeyframe(const CompositorFilterKeyframe&, const TimingFunction&);
 
     void setLinearTimingFunction();
-    void setCubicBezierTimingFunction(CubicBezierTimingFunction::EaseType);
-    void setCubicBezierTimingFunction(double x1, double y1, double x2, double y2);
-    void setStepsTimingFunction(int numberOfSteps, StepsTimingFunction::StepPosition);
+    void setCubicBezierTimingFunction(const TimingFunction&);
+    void setStepsTimingFunction(const TimingFunction&);
 
     // blink::CompositorAnimationCurve implementation.
     std::unique_ptr<cc::AnimationCurve> cloneToAnimationCurve() const override;
diff --git a/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.cpp b/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.cpp
index 5c6a461..52241c5 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.cpp
+++ b/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.cpp
@@ -80,26 +80,18 @@
             keyframe.value, nullptr));
 }
 
-void CompositorFloatAnimationCurve::addCubicBezierKeyframe(const CompositorFloatKeyframe& keyframe,
-    CubicBezierTimingFunction::EaseType easeType)
-{
-    m_curve->AddKeyframe(
-        cc::FloatKeyframe::Create(base::TimeDelta::FromSecondsD(keyframe.time),
-            keyframe.value, cc::CubicBezierTimingFunction::CreatePreset(easeType)));
-}
-
-void CompositorFloatAnimationCurve::addCubicBezierKeyframe(const CompositorFloatKeyframe& keyframe, double x1, double y1, double x2, double y2)
+void CompositorFloatAnimationCurve::addCubicBezierKeyframe(const CompositorFloatKeyframe& keyframe, const TimingFunction& timingFunction)
 {
     m_curve->AddKeyframe(cc::FloatKeyframe::Create(
         base::TimeDelta::FromSecondsD(keyframe.time), keyframe.value,
-        cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)));
+        timingFunction.cloneToCC()));
 }
 
-void CompositorFloatAnimationCurve::addStepsKeyframe(const CompositorFloatKeyframe& keyframe, int steps, StepsTimingFunction::StepPosition stepPosition)
+void CompositorFloatAnimationCurve::addStepsKeyframe(const CompositorFloatKeyframe& keyframe, const TimingFunction& timingFunction)
 {
     m_curve->AddKeyframe(cc::FloatKeyframe::Create(
         base::TimeDelta::FromSecondsD(keyframe.time), keyframe.value,
-        cc::StepsTimingFunction::Create(steps, stepPosition)));
+        timingFunction.cloneToCC()));
 }
 
 void CompositorFloatAnimationCurve::setLinearTimingFunction()
@@ -107,19 +99,14 @@
     m_curve->SetTimingFunction(nullptr);
 }
 
-void CompositorFloatAnimationCurve::setCubicBezierTimingFunction(CubicBezierTimingFunction::EaseType easeType)
+void CompositorFloatAnimationCurve::setCubicBezierTimingFunction(const TimingFunction& timingFunction)
 {
-    m_curve->SetTimingFunction(cc::CubicBezierTimingFunction::CreatePreset(easeType));
+    m_curve->SetTimingFunction(timingFunction.cloneToCC());
 }
 
-void CompositorFloatAnimationCurve::setCubicBezierTimingFunction(double x1, double y1, double x2, double y2)
+void CompositorFloatAnimationCurve::setStepsTimingFunction(const TimingFunction& timingFunction)
 {
-    m_curve->SetTimingFunction(cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2));
-}
-
-void CompositorFloatAnimationCurve::setStepsTimingFunction(int numberOfSteps, StepsTimingFunction::StepPosition stepPosition)
-{
-    m_curve->SetTimingFunction(cc::StepsTimingFunction::Create(numberOfSteps, stepPosition));
+    m_curve->SetTimingFunction(timingFunction.cloneToCC());
 }
 
 float CompositorFloatAnimationCurve::getValue(double time) const
diff --git a/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.h b/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.h
index 69340ce..1d3cf61 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.h
+++ b/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurve.h
@@ -45,16 +45,12 @@
     bool keyframeHasLinearTimingFunctionForTesting(unsigned long index) const;
 
     void addLinearKeyframe(const CompositorFloatKeyframe&);
-    void addCubicBezierKeyframe(const CompositorFloatKeyframe&, CubicBezierTimingFunction::EaseType);
-    // Adds the keyframe with a custom, bezier timing function. Note, it is
-    // assumed that x0 = y0 , and x3 = y3 = 1.
-    void addCubicBezierKeyframe(const CompositorFloatKeyframe&, double x1, double y1, double x2, double y2);
-    void addStepsKeyframe(const CompositorFloatKeyframe&, int steps, StepsTimingFunction::StepPosition);
+    void addCubicBezierKeyframe(const CompositorFloatKeyframe&, const TimingFunction&);
+    void addStepsKeyframe(const CompositorFloatKeyframe&, const TimingFunction&);
 
     void setLinearTimingFunction();
-    void setCubicBezierTimingFunction(CubicBezierTimingFunction::EaseType);
-    void setCubicBezierTimingFunction(double x1, double y1, double x2, double y2);
-    void setStepsTimingFunction(int numberOfSteps, StepsTimingFunction::StepPosition);
+    void setCubicBezierTimingFunction(const TimingFunction&);
+    void setStepsTimingFunction(const TimingFunction&);
 
     float getValue(double time) const;
 
diff --git a/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurveTest.cpp b/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurveTest.cpp
index dc34795..128ab131 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurveTest.cpp
+++ b/third_party/WebKit/Source/platform/animation/CompositorFloatAnimationCurveTest.cpp
@@ -99,7 +99,7 @@
 TEST(WebFloatAnimationCurveTest, CubicBezierTimingFunction)
 {
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), 0.25, 0, 0.75, 1);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), *CubicBezierTimingFunction::create(0.25, 0, 0.75, 1));
     curve->addLinearKeyframe(CompositorFloatKeyframe(1, 1));
 
     EXPECT_FLOAT_EQ(0, curve->getValue(0));
@@ -115,7 +115,7 @@
 TEST(WebFloatAnimationCurveTest, EaseTimingFunction)
 {
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), CubicBezierTimingFunction::EaseType::EASE);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE));
     curve->addLinearKeyframe(CompositorFloatKeyframe(1, 1));
 
     std::unique_ptr<cc::TimingFunction> timingFunction(
@@ -143,7 +143,7 @@
 TEST(WebFloatAnimationCurveTest, EaseInTimingFunction)
 {
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), CubicBezierTimingFunction::EaseType::EASE_IN);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE_IN));
     curve->addLinearKeyframe(CompositorFloatKeyframe(1, 1));
 
     std::unique_ptr<cc::TimingFunction> timingFunction(
@@ -158,7 +158,7 @@
 TEST(WebFloatAnimationCurveTest, EaseOutTimingFunction)
 {
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), CubicBezierTimingFunction::EaseType::EASE_OUT);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE_OUT));
     curve->addLinearKeyframe(CompositorFloatKeyframe(1, 1));
 
     std::unique_ptr<cc::TimingFunction> timingFunction(
@@ -173,7 +173,7 @@
 TEST(WebFloatAnimationCurveTest, EaseInOutTimingFunction)
 {
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), CubicBezierTimingFunction::EaseType::EASE_IN_OUT);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE_IN_OUT));
     curve->addLinearKeyframe(CompositorFloatKeyframe(1, 1));
 
     std::unique_ptr<cc::TimingFunction> timingFunction(
@@ -192,7 +192,7 @@
     double y1 = 0.2;
     double x2 = 0.8;
     double y2 = 0.7;
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), x1, y1, x2, y2);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), *CubicBezierTimingFunction::create(x1, y1, x2, y2));
     curve->addLinearKeyframe(CompositorFloatKeyframe(1, 1));
 
     std::unique_ptr<cc::TimingFunction> timingFunction(
@@ -207,7 +207,7 @@
 TEST(WebFloatAnimationCurveTest, DefaultTimingFunction)
 {
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), CubicBezierTimingFunction::EaseType::EASE);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, 0), *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE));
     curve->addLinearKeyframe(CompositorFloatKeyframe(1, 1));
 
     std::unique_ptr<cc::TimingFunction> timingFunction(
diff --git a/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.cpp b/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.cpp
index d2b24f0..bcdab859 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.cpp
+++ b/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.cpp
@@ -29,28 +29,20 @@
         base::TimeDelta::FromSecondsD(keyframe.time()), transformOperations, nullptr));
 }
 
-void CompositorTransformAnimationCurve::addCubicBezierKeyframe(const CompositorTransformKeyframe& keyframe, CubicBezierTimingFunction::EaseType easeType)
+void CompositorTransformAnimationCurve::addCubicBezierKeyframe(const CompositorTransformKeyframe& keyframe, const TimingFunction& timingFunction)
 {
     const cc::TransformOperations& transformOperations = keyframe.value().asTransformOperations();
     m_curve->AddKeyframe(cc::TransformKeyframe::Create(
         base::TimeDelta::FromSecondsD(keyframe.time()), transformOperations,
-        cc::CubicBezierTimingFunction::CreatePreset(easeType)));
+        timingFunction.cloneToCC()));
 }
 
-void CompositorTransformAnimationCurve::addCubicBezierKeyframe(const CompositorTransformKeyframe& keyframe,  double x1, double y1, double x2, double y2)
+void CompositorTransformAnimationCurve::addStepsKeyframe(const CompositorTransformKeyframe& keyframe, const TimingFunction& timingFunction)
 {
     const cc::TransformOperations& transformOperations = keyframe.value().asTransformOperations();
     m_curve->AddKeyframe(cc::TransformKeyframe::Create(
         base::TimeDelta::FromSecondsD(keyframe.time()), transformOperations,
-        cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2)));
-}
-
-void CompositorTransformAnimationCurve::addStepsKeyframe(const CompositorTransformKeyframe& keyframe, int steps, StepsTimingFunction::StepPosition stepPosition)
-{
-    const cc::TransformOperations& transformOperations = keyframe.value().asTransformOperations();
-    m_curve->AddKeyframe(cc::TransformKeyframe::Create(
-        base::TimeDelta::FromSecondsD(keyframe.time()), transformOperations,
-        cc::StepsTimingFunction::Create(steps, stepPosition)));
+        timingFunction.cloneToCC()));
 }
 
 void CompositorTransformAnimationCurve::setLinearTimingFunction()
@@ -58,20 +50,14 @@
     m_curve->SetTimingFunction(nullptr);
 }
 
-void CompositorTransformAnimationCurve::setCubicBezierTimingFunction(CubicBezierTimingFunction::EaseType easeType)
+void CompositorTransformAnimationCurve::setCubicBezierTimingFunction(const TimingFunction& timingFunction)
 {
-    m_curve->SetTimingFunction(cc::CubicBezierTimingFunction::CreatePreset(easeType));
+    m_curve->SetTimingFunction(timingFunction.cloneToCC());
 }
 
-void CompositorTransformAnimationCurve::setCubicBezierTimingFunction(double x1, double y1, double x2, double y2)
+void CompositorTransformAnimationCurve::setStepsTimingFunction(const TimingFunction& timingFunction)
 {
-    m_curve->SetTimingFunction(
-        cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2));
-}
-
-void CompositorTransformAnimationCurve::setStepsTimingFunction(int numberOfSteps, StepsTimingFunction::StepPosition stepPosition)
-{
-    m_curve->SetTimingFunction(cc::StepsTimingFunction::Create(numberOfSteps, stepPosition));
+    m_curve->SetTimingFunction(timingFunction.cloneToCC());
 }
 
 std::unique_ptr<cc::AnimationCurve> CompositorTransformAnimationCurve::cloneToAnimationCurve() const
diff --git a/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.h b/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.h
index 1b882e3..8853007 100644
--- a/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.h
+++ b/third_party/WebKit/Source/platform/animation/CompositorTransformAnimationCurve.h
@@ -35,16 +35,12 @@
     ~CompositorTransformAnimationCurve() override;
 
     void addLinearKeyframe(const CompositorTransformKeyframe&);
-    void addCubicBezierKeyframe(const CompositorTransformKeyframe&, CubicBezierTimingFunction::EaseType);
-    // Adds the keyframe with a custom, bezier timing function. Note, it is
-    // assumed that x0 = y0, and x3 = y3 = 1.
-    void addCubicBezierKeyframe(const CompositorTransformKeyframe&, double x1, double y1, double x2, double y2);
-    void addStepsKeyframe(const CompositorTransformKeyframe&, int steps, StepsTimingFunction::StepPosition);
+    void addCubicBezierKeyframe(const CompositorTransformKeyframe&, const TimingFunction&);
+    void addStepsKeyframe(const CompositorTransformKeyframe&, const TimingFunction&);
 
     void setLinearTimingFunction();
-    void setCubicBezierTimingFunction(CubicBezierTimingFunction::EaseType);
-    void setCubicBezierTimingFunction(double x1, double y1, double x2, double y2);
-    void setStepsTimingFunction(int numberOfSteps, StepsTimingFunction::StepPosition);
+    void setCubicBezierTimingFunction(const TimingFunction&);
+    void setStepsTimingFunction(const TimingFunction&);
 
     // CompositorAnimationCurve implementation.
     std::unique_ptr<cc::AnimationCurve> cloneToAnimationCurve() const override;
diff --git a/third_party/WebKit/Source/platform/animation/TimingFunction.cpp b/third_party/WebKit/Source/platform/animation/TimingFunction.cpp
index ccc55ffe..fa8ba56 100644
--- a/third_party/WebKit/Source/platform/animation/TimingFunction.cpp
+++ b/third_party/WebKit/Source/platform/animation/TimingFunction.cpp
@@ -23,6 +23,12 @@
 {
 }
 
+std::unique_ptr<cc::TimingFunction> LinearTimingFunction::cloneToCC() const
+{
+    return nullptr;
+}
+
+
 String CubicBezierTimingFunction::toString() const
 {
     switch (this->getEaseType()) {
@@ -46,67 +52,30 @@
 
 double CubicBezierTimingFunction::evaluate(double fraction, double accuracy) const
 {
-    return m_bezier.SolveWithEpsilon(fraction, accuracy);
+    return m_bezier->bezier().SolveWithEpsilon(fraction, accuracy);
 }
 
-// This works by taking taking the derivative of the cubic bezier, on the y
-// axis. We can then solve for where the derivative is zero to find the min
-// and max distace along the line. We the have to solve those in terms of time
-// rather than distance on the x-axis
 void CubicBezierTimingFunction::range(double* minValue, double* maxValue) const
 {
-    if (0 <= m_y1 && m_y2 < 1 && 0 <= m_y2 && m_y2 <= 1) {
-        return;
-    }
-
-    double a = 3.0 * (m_y1 - m_y2) + 1.0;
-    double b = 2.0 * (m_y2 - 2.0 * m_y1);
-    double c = m_y1;
-
-    if (std::abs(a) < std::numeric_limits<double>::epsilon()
-        && std::abs(b) < std::numeric_limits<double>::epsilon()) {
-        return;
-    }
-
-    double t1 = 0.0;
-    double t2 = 0.0;
-
-    if (std::abs(a) < std::numeric_limits<double>::epsilon()) {
-        t1 = -c / b;
-    } else {
-        double discriminant = b * b - 4 * a * c;
-        if (discriminant < 0)
-            return;
-        double discriminantSqrt = sqrt(discriminant);
-        t1 = (-b + discriminantSqrt) / (2 * a);
-        t2 = (-b - discriminantSqrt) / (2 * a);
-    }
-
-    double solution1 = 0.0;
-    double solution2 = 0.0;
-
-    // If the solution is in the range [0,1] then we include it, otherwise we
-    // ignore it.
-
-    // An interesting fact about these beziers is that they are only
-    // actually evaluated in [0,1]. After that we take the tangent at that point
-    // and linearly project it out.
-    if (0 < t1 && t1 < 1)
-        solution1 = m_bezier.SampleCurveY(t1);
-
-    if (0 < t2 && t2 < 1)
-        solution2 = m_bezier.SampleCurveY(t2);
+    const double solution1 = m_bezier->bezier().range_min();
+    const double solution2 = m_bezier->bezier().range_max();
 
     // Since our input values can be out of the range 0->1 so we must also
     // consider the minimum and maximum points.
-    double solutionMin = m_bezier.SolveWithEpsilon(*minValue, std::numeric_limits<double>::epsilon());
-    double solutionMax = m_bezier.SolveWithEpsilon(*maxValue, std::numeric_limits<double>::epsilon());
+    double solutionMin = m_bezier->bezier().SolveWithEpsilon(*minValue, std::numeric_limits<double>::epsilon());
+    double solutionMax = m_bezier->bezier().SolveWithEpsilon(*maxValue, std::numeric_limits<double>::epsilon());
     *minValue = std::min(std::min(solutionMin, solutionMax), 0.0);
     *maxValue = std::max(std::max(solutionMin, solutionMax), 1.0);
     *minValue = std::min(std::min(*minValue, solution1), solution2);
     *maxValue = std::max(std::max(*maxValue, solution1), solution2);
 }
 
+std::unique_ptr<cc::TimingFunction> CubicBezierTimingFunction::cloneToCC() const
+{
+    return m_bezier->Clone();
+}
+
+
 String StepsTimingFunction::toString() const
 {
     const char* positionString = nullptr;
@@ -144,21 +113,15 @@
 
 double StepsTimingFunction::evaluate(double fraction, double) const
 {
-    double startOffset = 0;
-    switch (m_stepPosition) {
-    case StepPosition::START:
-        startOffset = 1;
-        break;
-    case StepPosition::MIDDLE:
-        startOffset = 0.5;
-        break;
-    case StepPosition::END:
-        startOffset = 0;
-        break;
-    }
-    return clampTo(floor((m_steps * fraction) + startOffset) / m_steps, 0.0, 1.0);
+    return m_steps->GetPreciseValue(fraction);
 }
 
+std::unique_ptr<cc::TimingFunction> StepsTimingFunction::cloneToCC() const
+{
+    return m_steps->Clone();
+}
+
+
 // Equals operators
 bool operator==(const LinearTimingFunction& lhs, const TimingFunction& rhs)
 {
diff --git a/third_party/WebKit/Source/platform/animation/TimingFunction.h b/third_party/WebKit/Source/platform/animation/TimingFunction.h
index 9da8afde..10d897a 100644
--- a/third_party/WebKit/Source/platform/animation/TimingFunction.h
+++ b/third_party/WebKit/Source/platform/animation/TimingFunction.h
@@ -56,6 +56,9 @@
     // calling evaluate();
     virtual void range(double* minValue, double* maxValue) const = 0;
 
+    // Create CC instance.
+    virtual std::unique_ptr<cc::TimingFunction> cloneToCC() const = 0;
+
 protected:
     TimingFunction(Type type)
         : m_type(type)
@@ -76,10 +79,12 @@
 
     ~LinearTimingFunction() override { }
 
+    // TimingFunction implementation.
     String toString() const override;
-
     double evaluate(double fraction, double) const override;
     void range(double* minValue, double* maxValue) const override;
+    std::unique_ptr<cc::TimingFunction> cloneToCC() const override;
+
 private:
     LinearTimingFunction()
         : TimingFunction(Type::LINEAR)
@@ -93,15 +98,15 @@
 
     static PassRefPtr<CubicBezierTimingFunction> create(double x1, double y1, double x2, double y2)
     {
-        return adoptRef(new CubicBezierTimingFunction(EaseType::CUSTOM, x1, y1, x2, y2));
+        return adoptRef(new CubicBezierTimingFunction(x1, y1, x2, y2));
     }
 
     static CubicBezierTimingFunction* preset(EaseType easeType)
     {
-        DEFINE_STATIC_REF(CubicBezierTimingFunction, ease, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE, 0.25, 0.1, 0.25, 1.0))));
-        DEFINE_STATIC_REF(CubicBezierTimingFunction, easeIn, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE_IN, 0.42, 0.0, 1.0, 1.0))));
-        DEFINE_STATIC_REF(CubicBezierTimingFunction, easeOut, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE_OUT, 0.0, 0.0, 0.58, 1.0))));
-        DEFINE_STATIC_REF(CubicBezierTimingFunction, easeInOut, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE_IN_OUT, 0.42, 0.0, 0.58, 1.0))));
+        DEFINE_STATIC_REF(CubicBezierTimingFunction, ease, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE))));
+        DEFINE_STATIC_REF(CubicBezierTimingFunction, easeIn, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE_IN))));
+        DEFINE_STATIC_REF(CubicBezierTimingFunction, easeOut, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE_OUT))));
+        DEFINE_STATIC_REF(CubicBezierTimingFunction, easeInOut, (adoptRef(new CubicBezierTimingFunction(EaseType::EASE_IN_OUT))));
 
         switch (easeType) {
         case EaseType::EASE:
@@ -120,41 +125,46 @@
 
     ~CubicBezierTimingFunction() override { }
 
+    // TimingFunction implementation.
     String toString() const override;
-
     double evaluate(double fraction, double accuracy) const override;
     void range(double* minValue, double* maxValue) const override;
+    std::unique_ptr<cc::TimingFunction> cloneToCC() const override;
 
-    double x1() const { return m_x1; }
-    double y1() const { return m_y1; }
-    double x2() const { return m_x2; }
-    double y2() const { return m_y2; }
-
-    EaseType getEaseType() const { return m_easeType; }
+    double x1() const { DCHECK_EQ(getEaseType(), EaseType::CUSTOM); return m_x1; }
+    double y1() const { DCHECK_EQ(getEaseType(), EaseType::CUSTOM); return m_y1; }
+    double x2() const { DCHECK_EQ(getEaseType(), EaseType::CUSTOM); return m_x2; }
+    double y2() const { DCHECK_EQ(getEaseType(), EaseType::CUSTOM); return m_y2; }
+    EaseType getEaseType() const { return m_bezier->ease_type(); }
 
 private:
-    explicit CubicBezierTimingFunction(EaseType easeType, double x1, double y1, double x2, double y2)
+    explicit CubicBezierTimingFunction(EaseType easeType)
         : TimingFunction(Type::CUBIC_BEZIER)
-        , m_bezier(x1, y1, x2, y2)
+        , m_bezier(cc::CubicBezierTimingFunction::CreatePreset(easeType))
+        , m_x1()
+        , m_y1()
+        , m_x2()
+        , m_y2()
+    {
+    }
+
+    CubicBezierTimingFunction(double x1, double y1, double x2, double y2)
+        : TimingFunction(Type::CUBIC_BEZIER)
+        , m_bezier(cc::CubicBezierTimingFunction::Create(x1, y1, x2, y2))
         , m_x1(x1)
         , m_y1(y1)
         , m_x2(x2)
         , m_y2(y2)
-        , m_easeType(easeType)
     {
     }
 
-    // Finds points on the cubic bezier that cross the given horizontal
-    // line, storing their x values in solution1-3 and returning the
-    // number of solutions found.
-    size_t findIntersections(double intersectionY, double& solution1, double& solution2, double& solution3) const;
+    std::unique_ptr<cc::CubicBezierTimingFunction> m_bezier;
 
-    gfx::CubicBezier m_bezier;
+    // TODO(loyso): Get these values from m_bezier->bezier_ (gfx::CubicBezier)
     const double m_x1;
     const double m_y1;
     const double m_x2;
     const double m_y2;
-    const EaseType m_easeType;
 };
 
 class PLATFORM_EXPORT StepsTimingFunction final : public TimingFunction {
@@ -186,24 +196,23 @@
 
     ~StepsTimingFunction() override { }
 
+    // TimingFunction implementation.
     String toString() const override;
-
     double evaluate(double fraction, double) const override;
     void range(double* minValue, double* maxValue) const override;
+    std::unique_ptr<cc::TimingFunction> cloneToCC() const override;
 
-    int numberOfSteps() const { return m_steps; }
-    StepPosition getStepPosition() const { return m_stepPosition; }
+    int numberOfSteps() const { return m_steps->steps(); }
+    StepPosition getStepPosition() const { return m_steps->step_position(); }
 
 private:
     StepsTimingFunction(int steps, StepPosition stepPosition)
         : TimingFunction(Type::STEPS)
-        , m_steps(steps)
-        , m_stepPosition(stepPosition)
+        , m_steps(cc::StepsTimingFunction::Create(steps, stepPosition))
     {
     }
 
-    int m_steps;
-    StepPosition m_stepPosition;
+    std::unique_ptr<cc::StepsTimingFunction> m_steps;
 };
 
 PLATFORM_EXPORT bool operator==(const LinearTimingFunction&, const TimingFunction&);
diff --git a/third_party/WebKit/Source/platform/fonts/FontDescription.h b/third_party/WebKit/Source/platform/fonts/FontDescription.h
index 8d1e13e..1286e3d 100644
--- a/third_party/WebKit/Source/platform/fonts/FontDescription.h
+++ b/third_party/WebKit/Source/platform/fonts/FontDescription.h
@@ -38,7 +38,6 @@
 #include "platform/fonts/FontWidthVariant.h"
 #include "platform/fonts/TextRenderingMode.h"
 #include "platform/fonts/TypesettingFeatures.h"
-#include "platform/text/LocaleToScriptMapping.h"
 #include "wtf/Allocator.h"
 #include "wtf/MathExtras.h"
 
diff --git a/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp b/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
index 83c8b7d3..0f24adb0 100644
--- a/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
+++ b/third_party/WebKit/Source/platform/fonts/android/FontCacheAndroid.cpp
@@ -34,7 +34,6 @@
 #include "platform/fonts/SimpleFontData.h"
 #include "platform/fonts/FontDescription.h"
 #include "platform/fonts/FontFaceCreationParams.h"
-#include "platform/text/LocaleToScriptMapping.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/ports/SkFontMgr.h"
 
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
index 73432861..fef527b 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayerTest.cpp
@@ -108,7 +108,7 @@
     ASSERT_FALSE(m_platformLayer->hasActiveAnimationForTesting());
 
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0.0, 0.0), CubicBezierTimingFunction::EaseType::EASE);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0.0, 0.0), *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE));
     std::unique_ptr<CompositorAnimation> floatAnimation(CompositorAnimation::create(*curve, CompositorTargetProperty::OPACITY, 0, 0));
     int animationId = floatAnimation->id();
 
diff --git a/third_party/WebKit/Source/platform/inspector_protocol/String16STL.cpp b/third_party/WebKit/Source/platform/inspector_protocol/String16STL.cpp
index 4883f4c..10c7fa6 100644
--- a/third_party/WebKit/Source/platform/inspector_protocol/String16STL.cpp
+++ b/third_party/WebKit/Source/platform/inspector_protocol/String16STL.cpp
@@ -113,14 +113,6 @@
     return nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
 }
 
-template<typename CharType> inline bool isASCIIAlphaCaselessEqual(CharType cssCharacter, char character)
-{
-    // This function compares a (preferrably) constant ASCII
-    // lowercase letter to any input character.
-    DCHECK(character >= 'a' && character <= 'z');
-    return LIKELY(toASCIILowerUnchecked(cssCharacter) == character);
-}
-
 inline int inlineUTF8SequenceLengthNonASCII(char b0)
 {
     if ((b0 & 0xC0) != 0xC0)
diff --git a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
index 593f095..8dbe206 100644
--- a/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
+++ b/third_party/WebKit/Source/platform/network/HTTPParsers.cpp
@@ -186,7 +186,10 @@
     // FIXME: This should really match name against
     // field-value in section 4.2 of RFC 2616.
 
-    return name.containsOnlyLatin1() && !name.contains('\r') && !name.contains('\n') && !name.contains(static_cast<UChar>('\0'));
+    return name.containsOnlyLatin1()
+        && !name.contains('\r')
+        && !name.contains('\n')
+        && !name.contains('\0');
 }
 
 // See RFC 7230, Section 3.2.
diff --git a/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.cpp b/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.cpp
index d06e737..ae2f92c6 100644
--- a/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.cpp
+++ b/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.cpp
@@ -512,7 +512,7 @@
             break;
         case 4: // script = 4ALPHA
             script = scriptNameToCode(locale.substring(begin, len));
-            if (script != USCRIPT_INVALID_CODE)
+            if (isUnambiguousHanScript(script))
                 return script;
         }
     }
diff --git a/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.h b/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.h
index 041d29a..f193d447 100644
--- a/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.h
+++ b/third_party/WebKit/Source/platform/text/LocaleToScriptMapping.h
@@ -44,6 +44,16 @@
 
 PLATFORM_EXPORT UScriptCode scriptCodeForHanFromSubtags(const String&, char delimiter = '-');
 
+inline bool isUnambiguousHanScript(UScriptCode script)
+{
+    // localeToScriptCodeForFontSelection() does not return these values.
+    DCHECK(script != USCRIPT_HIRAGANA && script != USCRIPT_KATAKANA);
+    return script == USCRIPT_KATAKANA_OR_HIRAGANA
+        || script == USCRIPT_SIMPLIFIED_HAN
+        || script == USCRIPT_TRADITIONAL_HAN
+        || script == USCRIPT_HANGUL;
+}
+
 }
 
 #endif
diff --git a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
index 364d3068..ac13837b 100644
--- a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
+++ b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
@@ -311,15 +311,15 @@
 
     std::unique_ptr<CompositorFloatAnimationCurve> curve = CompositorFloatAnimationCurve::create();
 
-    const auto easeType = CubicBezierTimingFunction::EaseType::EASE;
+    const auto& timingFunction = *CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseType::EASE);
 
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, startOpacity), easeType);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(0, startOpacity), timingFunction);
     // Make sure we have displayed for at least minPreFadeDuration before starting to fade out.
     float extraDurationRequired = std::max(0.f, minPreFadeDuration - static_cast<float>(monotonicallyIncreasingTime() - m_startTime));
     if (extraDurationRequired)
-        curve->addCubicBezierKeyframe(CompositorFloatKeyframe(extraDurationRequired, startOpacity), easeType);
+        curve->addCubicBezierKeyframe(CompositorFloatKeyframe(extraDurationRequired, startOpacity), timingFunction);
     // For layout tests we don't fade out.
-    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(fadeDuration + extraDurationRequired, layoutTestMode() ? startOpacity : 0), easeType);
+    curve->addCubicBezierKeyframe(CompositorFloatKeyframe(fadeDuration + extraDurationRequired, layoutTestMode() ? startOpacity : 0), timingFunction);
 
     std::unique_ptr<CompositorAnimation> animation = CompositorAnimation::create(*curve, CompositorTargetProperty::OPACITY, 0, 0);
 
diff --git a/third_party/WebKit/Source/web/PopupMenuImpl.cpp b/third_party/WebKit/Source/web/PopupMenuImpl.cpp
index 76677ef4..7ee847eb08 100644
--- a/third_party/WebKit/Source/web/PopupMenuImpl.cpp
+++ b/third_party/WebKit/Source/web/PopupMenuImpl.cpp
@@ -246,7 +246,7 @@
 void PopupMenuImpl::writeDocument(SharedBuffer* data)
 {
     HTMLSelectElement& ownerElement = *m_ownerElement;
-    IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(ownerElement.elementRectRelativeToViewport(), ownerElement.document().view());
+    IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(ownerElement.visibleBoundsInVisualViewport(), ownerElement.document().view());
 
     PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data);
     data->append(Platform::current()->loadResource("pickerCommon.css"));
@@ -511,7 +511,7 @@
     }
     context.finishGroupIfNecessary();
     PagePopupClient::addString("],\n", data.get());
-    IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_ownerElement->elementRectRelativeToViewport(), ownerElement().document().view());
+    IntRect anchorRectInScreen = m_chromeClient->viewportToScreen(m_ownerElement->visibleBoundsInVisualViewport(), ownerElement().document().view());
     addProperty("anchorRectInScreen", anchorRectInScreen, data.get());
     PagePopupClient::addString("}\n", data.get());
     m_popup->postMessage(String::fromUTF8(data->data(), data->size()));
diff --git a/third_party/WebKit/Source/web/ValidationMessageClientImpl.cpp b/third_party/WebKit/Source/web/ValidationMessageClientImpl.cpp
index 0285b54..2d24c2c 100644
--- a/third_party/WebKit/Source/web/ValidationMessageClientImpl.cpp
+++ b/third_party/WebKit/Source/web/ValidationMessageClientImpl.cpp
@@ -118,14 +118,7 @@
         return;
     }
 
-    // Check the visibility of the element.
-    // FIXME: Can we check invisibility by scrollable non-frame elements?
-    IntRect newAnchorRectInViewport = currentView()->contentsToViewport(m_currentAnchor->pixelSnappedBoundingBox());
-
-    // FIXME: This intersection eliminates the part of the rect outside the root view.
-    // If this is meant as a visiblity test, intersecting it against the viewport rect
-    // likely makes more sense.
-    newAnchorRectInViewport = intersection(currentView()->convertToRootFrame(currentView()->boundsRect()), newAnchorRectInViewport);
+    IntRect newAnchorRectInViewport = m_currentAnchor->visibleBoundsInVisualViewport();
     if (newAnchorRectInViewport.isEmpty()) {
         hideValidationMessage(*m_currentAnchor);
         return;
diff --git a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
index ad5fef436..cf47dc68 100644
--- a/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
+++ b/third_party/WebKit/Source/web/tests/VisualViewportTest.cpp
@@ -1544,6 +1544,22 @@
     EXPECT_SIZE_EQ(expectedBounds.size(), boundsInViewport.size());
 }
 
+TEST_P(ParameterizedVisualViewportTest, ElementVisibleBoundsInVisualViewport)
+{
+    initializeWithAndroidSettings();
+    webViewImpl()->resize(IntSize(640, 1080));
+    registerMockedHttpURLLoad("viewport-select.html");
+    navigateTo(m_baseURL + "viewport-select.html");
+
+    ASSERT_EQ(2.0f, webViewImpl()->pageScaleFactor());
+    webViewImpl()->setInitialFocus(false);
+    Element* element = webViewImpl()->focusedElement();
+    EXPECT_FALSE(element->visibleBoundsInVisualViewport().isEmpty());
+
+    webViewImpl()->setPageScaleFactor(4.0);
+    EXPECT_TRUE(element->visibleBoundsInVisualViewport().isEmpty());
+}
+
 // Test that the various window.scroll and document.body.scroll properties and
 // methods work unchanged from the pre-virtual viewport mode.
 TEST_P(ParameterizedVisualViewportTest, bodyAndWindowScrollPropertiesAccountForViewport)
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
index a1c03667..3405216 100644
--- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -3231,6 +3231,39 @@
     }
 }
 
+// Make sure the SubframeBeforeUnloadUseCounter is only incremented on subframe
+// unloads. crbug.com/635029.
+TEST_F(WebViewTest, SubframeBeforeUnloadUseCounter)
+{
+    registerMockedHttpURLLoad("visible_iframe.html");
+    registerMockedHttpURLLoad("single_iframe.html");
+    WebViewImpl* webView = m_webViewHelper.initializeAndLoad(m_baseURL + "single_iframe.html", true);
+
+    WebFrame* frame = m_webViewHelper.webView()->mainFrame();
+    Document* document =
+        toLocalFrame(m_webViewHelper.webView()->page()->mainFrame())->document();
+
+    // Add a beforeunload handler in the main frame. Make sure firing
+    // beforeunload doesn't increment the subframe use counter.
+    {
+        frame->executeScript(WebScriptSource(
+            "addEventListener('beforeunload', function() {});"));
+        webView->mainFrame()->toWebLocalFrame()->dispatchBeforeUnloadEvent(false);
+        EXPECT_FALSE(UseCounter::isCounted(*document, UseCounter::SubFrameBeforeUnloadFired));
+    }
+
+    // Add a beforeunload handler in the iframe and dispatch. Make sure we do
+    // increment the use counter for subframe beforeunloads.
+    {
+        frame->executeScript(WebScriptSource(
+            "document.getElementsByTagName('iframe')[0].contentWindow.addEventListener('beforeunload', function() {});"));
+        webView->mainFrame()->firstChild()->toWebLocalFrame()->dispatchBeforeUnloadEvent(false);
+
+        Document* childDocument = toLocalFrame(m_webViewHelper.webView()->page()->mainFrame()->tree().firstChild())->document();
+        EXPECT_TRUE(UseCounter::isCounted(*childDocument, UseCounter::SubFrameBeforeUnloadFired));
+    }
+}
+
 // Verify that page loads are deferred until all ScopedPageLoadDeferrers are
 // destroyed.
 TEST_F(WebViewTest, NestedLoadDeferrals)
diff --git a/third_party/WebKit/Source/web/tests/data/viewport-select.html b/third_party/WebKit/Source/web/tests/data/viewport-select.html
new file mode 100644
index 0000000..8f37921
--- /dev/null
+++ b/third_party/WebKit/Source/web/tests/data/viewport-select.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="minimum-scale=2.0">
+<style>
+select {
+  position: absolute;
+  left: 320px;
+  top: 800px;
+  width: 100px;
+  height: 20px;
+}
+</style>
+</head>
+<body>
+<select><option>abc</option></select>
+</body>
+</html>
diff --git a/third_party/WebKit/Source/wtf/ASCIICType.h b/third_party/WebKit/Source/wtf/ASCIICType.h
index 4d036b3..d6e5b35 100644
--- a/third_party/WebKit/Source/wtf/ASCIICType.h
+++ b/third_party/WebKit/Source/wtf/ASCIICType.h
@@ -124,16 +124,6 @@
     return static_cast<char>(ASCIICaseFoldTable[static_cast<LChar>(c)]);
 }
 
-template<typename CharType> inline CharType toASCIILowerUnchecked(CharType character)
-{
-    // This function can be used for comparing any input character
-    // to a lowercase English character. The isASCIIAlphaCaselessEqual
-    // below should be used for regular comparison of ASCII alpha
-    // characters, but switch statements in CSS tokenizer require
-    // direct use of this function.
-    return character | 0x20;
-}
-
 template<typename CharType> inline CharType toASCIIUpper(CharType c)
 {
     return c & ~((c >= 'a' && c <= 'z') << 5);
@@ -168,7 +158,7 @@
     // This function compares a (preferrably) constant ASCII
     // lowercase letter to any input character.
     ASSERT(character >= 'a' && character <= 'z');
-    return LIKELY(toASCIILowerUnchecked(cssCharacter) == character);
+    return LIKELY((cssCharacter | 0x20) == character);
 }
 
 } // namespace WTF
@@ -185,7 +175,6 @@
 using WTF::isASCIIUpper;
 using WTF::toASCIIHexValue;
 using WTF::toASCIILower;
-using WTF::toASCIILowerUnchecked;
 using WTF::toASCIIUpper;
 using WTF::lowerNibbleToASCIIHexDigit;
 using WTF::upperNibbleToASCIIHexDigit;
diff --git a/third_party/WebKit/Source/wtf/text/AtomicString.h b/third_party/WebKit/Source/wtf/text/AtomicString.h
index ed2a0ce..2dc75a7 100644
--- a/third_party/WebKit/Source/wtf/text/AtomicString.h
+++ b/third_party/WebKit/Source/wtf/text/AtomicString.h
@@ -73,19 +73,22 @@
 
     UChar operator[](unsigned i) const { return m_string[i]; }
 
-    bool contains(UChar c) const { return m_string.contains(c); }
-    bool contains(const LChar* s, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
-        { return m_string.contains(s, caseSensitivity); }
-    bool contains(const String& s, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
-        { return m_string.contains(s, caseSensitivity); }
-
-    size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); }
+    // Find characters.
+    size_t find(UChar c, unsigned start = 0) const
+        { return m_string.find(c, start); }
+    size_t find(LChar c, unsigned start = 0) const
+        { return m_string.find(c, start); }
+    size_t find(char c, unsigned start = 0) const { return find(static_cast<LChar>(c), start); }
     size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const
         { return m_string.find(matchFunction, start); }
-    size_t find(const LChar* s, size_t start = 0, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
-        { return m_string.find(s, start, caseSensitivity); }
-    size_t find(const String& s, size_t start = 0, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
-        { return m_string.find(s, start, caseSensitivity); }
+
+    // Find substrings.
+    size_t find(const StringView& value, unsigned start = 0, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
+        { return m_string.find(value, start, caseSensitivity); }
+
+    bool contains(char c) const { return find(c) != kNotFound; }
+    bool contains(const StringView& value, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
+        { return find(value, 0, caseSensitivity) != kNotFound; }
 
     bool startsWith(const StringView& prefix, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
         { return m_string.startsWith(prefix, caseSensitivity); }
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
index afae4eb..e05c031 100644
--- a/third_party/WebKit/Source/wtf/text/StringImpl.cpp
+++ b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
@@ -1162,91 +1162,6 @@
     return WTF::find(characters16(), m_length, matchFunction, start);
 }
 
-size_t StringImpl::find(const LChar* matchString, unsigned index)
-{
-    // Check for null or empty string to match against
-    if (!matchString)
-        return kNotFound;
-    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
-    RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max());
-    unsigned matchLength = matchStringLength;
-    if (!matchLength)
-        return min(index, length());
-
-    // Optimization 1: fast case for strings of length 1.
-    if (matchLength == 1)
-        return WTF::find(characters16(), length(), *matchString, index);
-
-    // Check index & matchLength are in range.
-    if (index > length())
-        return kNotFound;
-    unsigned searchLength = length() - index;
-    if (matchLength > searchLength)
-        return kNotFound;
-    // delta is the number of additional times to test; delta == 0 means test only once.
-    unsigned delta = searchLength - matchLength;
-
-    const UChar* searchCharacters = characters16() + index;
-
-    // Optimization 2: keep a running hash of the strings,
-    // only call equal if the hashes match.
-    unsigned searchHash = 0;
-    unsigned matchHash = 0;
-    for (unsigned i = 0; i < matchLength; ++i) {
-        searchHash += searchCharacters[i];
-        matchHash += matchString[i];
-    }
-
-    unsigned i = 0;
-    // keep looping until we match
-    while (searchHash != matchHash || !equal(searchCharacters + i, matchString, matchLength)) {
-        if (i == delta)
-            return kNotFound;
-        searchHash += searchCharacters[i + matchLength];
-        searchHash -= searchCharacters[i];
-        ++i;
-    }
-    return index + i;
-}
-
-template<typename CharType>
-ALWAYS_INLINE size_t findIgnoringCaseInternal(const CharType* searchCharacters, const LChar* matchString, unsigned index, unsigned searchLength, unsigned matchLength)
-{
-    // delta is the number of additional times to test; delta == 0 means test only once.
-    unsigned delta = searchLength - matchLength;
-
-    unsigned i = 0;
-    while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) {
-        if (i == delta)
-            return kNotFound;
-        ++i;
-    }
-    return index + i;
-}
-
-size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index)
-{
-    // Check for null or empty string to match against
-    if (!matchString)
-        return kNotFound;
-    size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString));
-    RELEASE_ASSERT(matchStringLength <= numeric_limits<unsigned>::max());
-    unsigned matchLength = matchStringLength;
-    if (!matchLength)
-        return min(index, length());
-
-    // Check index & matchLength are in range.
-    if (index > length())
-        return kNotFound;
-    unsigned searchLength = length() - index;
-    if (matchLength > searchLength)
-        return kNotFound;
-
-    if (is8Bit())
-        return findIgnoringCaseInternal(characters8() + index, matchString, index, searchLength, matchLength);
-    return findIgnoringCaseInternal(characters16() + index, matchString, index, searchLength, matchLength);
-}
-
 template <typename SearchCharacterType, typename MatchCharacterType>
 ALWAYS_INLINE static size_t findInternal(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
 {
@@ -1276,58 +1191,18 @@
     return index + i;
 }
 
-size_t StringImpl::find(StringImpl* matchString)
+size_t StringImpl::find(const StringView& matchString, unsigned index)
 {
-    // Check for null string to match against
-    if (UNLIKELY(!matchString))
-        return kNotFound;
-    unsigned matchLength = matchString->length();
-
-    // Optimization 1: fast case for strings of length 1.
-    if (matchLength == 1) {
-        if (is8Bit()) {
-            if (matchString->is8Bit())
-                return WTF::find(characters8(), length(), matchString->characters8()[0]);
-            return WTF::find(characters8(), length(), matchString->characters16()[0]);
-        }
-        if (matchString->is8Bit())
-            return WTF::find(characters16(), length(), matchString->characters8()[0]);
-        return WTF::find(characters16(), length(), matchString->characters16()[0]);
-    }
-
-    // Check matchLength is in range.
-    if (matchLength > length())
+    if (UNLIKELY(matchString.isNull()))
         return kNotFound;
 
-    // Check for empty string to match against
-    if (UNLIKELY(!matchLength))
-        return 0;
-
-    if (is8Bit()) {
-        if (matchString->is8Bit())
-            return findInternal(characters8(), matchString->characters8(), 0, length(), matchLength);
-        return findInternal(characters8(), matchString->characters16(), 0, length(), matchLength);
-    }
-
-    if (matchString->is8Bit())
-        return findInternal(characters16(), matchString->characters8(), 0, length(), matchLength);
-
-    return findInternal(characters16(), matchString->characters16(), 0, length(), matchLength);
-}
-
-size_t StringImpl::find(StringImpl* matchString, unsigned index)
-{
-    // Check for null or empty string to match against
-    if (UNLIKELY(!matchString))
-        return kNotFound;
-
-    unsigned matchLength = matchString->length();
+    unsigned matchLength = matchString.length();
 
     // Optimization 1: fast case for strings of length 1.
     if (matchLength == 1) {
         if (is8Bit())
-            return WTF::find(characters8(), length(), (*matchString)[0], index);
-        return WTF::find(characters16(), length(), (*matchString)[0], index);
+            return WTF::find(characters8(), length(), matchString[0], index);
+        return WTF::find(characters16(), length(), matchString[0], index);
     }
 
     if (UNLIKELY(!matchLength))
@@ -1341,19 +1216,17 @@
         return kNotFound;
 
     if (is8Bit()) {
-        if (matchString->is8Bit())
-            return findInternal(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
-        return findInternal(characters8() + index, matchString->characters16(), index, searchLength, matchLength);
+        if (matchString.is8Bit())
+            return findInternal(characters8() + index, matchString.characters8(), index, searchLength, matchLength);
+        return findInternal(characters8() + index, matchString.characters16(), index, searchLength, matchLength);
     }
-
-    if (matchString->is8Bit())
-        return findInternal(characters16() + index, matchString->characters8(), index, searchLength, matchLength);
-
-    return findInternal(characters16() + index, matchString->characters16(), index, searchLength, matchLength);
+    if (matchString.is8Bit())
+        return findInternal(characters16() + index, matchString.characters8(), index, searchLength, matchLength);
+    return findInternal(characters16() + index, matchString.characters16(), index, searchLength, matchLength);
 }
 
 template <typename SearchCharacterType, typename MatchCharacterType>
-ALWAYS_INLINE static size_t findIgnoringCaseInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
+ALWAYS_INLINE static size_t findIgnoringCaseInternal(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
 {
     // delta is the number of additional times to test; delta == 0 means test only once.
     unsigned delta = searchLength - matchLength;
@@ -1368,12 +1241,12 @@
     return index + i;
 }
 
-size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index)
+size_t StringImpl::findIgnoringCase(const StringView& matchString, unsigned index)
 {
-    // Check for null or empty string to match against
-    if (!matchString)
+    if (UNLIKELY(matchString.isNull()))
         return kNotFound;
-    unsigned matchLength = matchString->length();
+
+    unsigned matchLength = matchString.length();
     if (!matchLength)
         return min(index, length());
 
@@ -1385,19 +1258,17 @@
         return kNotFound;
 
     if (is8Bit()) {
-        if (matchString->is8Bit())
-            return findIgnoringCaseInner(characters8() + index, matchString->characters8(), index, searchLength, matchLength);
-        return findIgnoringCaseInner(characters8() + index, matchString->characters16(), index, searchLength, matchLength);
+        if (matchString.is8Bit())
+            return findIgnoringCaseInternal(characters8() + index, matchString.characters8(), index, searchLength, matchLength);
+        return findIgnoringCaseInternal(characters8() + index, matchString.characters16(), index, searchLength, matchLength);
     }
-
-    if (matchString->is8Bit())
-        return findIgnoringCaseInner(characters16() + index, matchString->characters8(), index, searchLength, matchLength);
-
-    return findIgnoringCaseInner(characters16() + index, matchString->characters16(), index, searchLength, matchLength);
+    if (matchString.is8Bit())
+        return findIgnoringCaseInternal(characters16() + index, matchString.characters8(), index, searchLength, matchLength);
+    return findIgnoringCaseInternal(characters16() + index, matchString.characters16(), index, searchLength, matchLength);
 }
 
 template <typename SearchCharacterType, typename MatchCharacterType>
-ALWAYS_INLINE static size_t findIgnoringASCIICaseInner(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
+ALWAYS_INLINE static size_t findIgnoringASCIICaseInternal(const SearchCharacterType* searchCharacters, const MatchCharacterType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength)
 {
     // delta is the number of additional times to test; delta == 0 means test only once.
     unsigned delta = searchLength - matchLength;
@@ -1412,12 +1283,12 @@
     return index + i;
 }
 
-size_t StringImpl::findIgnoringASCIICase(StringImpl* matchString, unsigned index)
+size_t StringImpl::findIgnoringASCIICase(const StringView& matchString, unsigned index)
 {
-    // Check for null or empty string to match against
-    if (!matchString)
+    if (UNLIKELY(matchString.isNull()))
         return kNotFound;
-    unsigned matchLength = matchString->length();
+
+    unsigned matchLength = matchString.length();
     if (!matchLength)
         return min(index, length());
 
@@ -1429,16 +1300,13 @@
         return kNotFound;
 
     if (is8Bit()) {
-        const LChar* searchStart = characters8() + index;
-        if (matchString->is8Bit())
-            return findIgnoringASCIICaseInner(searchStart, matchString->characters8(), index, searchLength, matchLength);
-        return findIgnoringASCIICaseInner(searchStart, matchString->characters16(), index, searchLength, matchLength);
+        if (matchString.is8Bit())
+            return findIgnoringASCIICaseInternal(characters8() + index, matchString.characters8(), index, searchLength, matchLength);
+        return findIgnoringASCIICaseInternal(characters8() + index, matchString.characters16(), index, searchLength, matchLength);
     }
-
-    const UChar* searchStart = characters16() + index;
-    if (matchString->is8Bit())
-        return findIgnoringASCIICaseInner(searchStart, matchString->characters8(), index, searchLength, matchLength);
-    return findIgnoringASCIICaseInner(searchStart, matchString->characters16(), index, searchLength, matchLength);
+    if (matchString.is8Bit())
+        return findIgnoringASCIICaseInternal(characters16() + index, matchString.characters8(), index, searchLength, matchLength);
+    return findIgnoringASCIICaseInternal(characters16() + index, matchString.characters16(), index, searchLength, matchLength);
 }
 
 size_t StringImpl::reverseFind(UChar c, unsigned index)
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.h b/third_party/WebKit/Source/wtf/text/StringImpl.h
index 89bef3a..1311c0d 100644
--- a/third_party/WebKit/Source/wtf/text/StringImpl.h
+++ b/third_party/WebKit/Source/wtf/text/StringImpl.h
@@ -366,18 +366,16 @@
     template <typename CharType>
     ALWAYS_INLINE PassRefPtr<StringImpl> removeCharacters(const CharType* characters, CharacterMatchFunctionPtr);
 
+    // Find characters.
     size_t find(LChar character, unsigned start = 0);
     size_t find(char character, unsigned start = 0);
     size_t find(UChar character, unsigned start = 0);
     size_t find(CharacterMatchFunctionPtr, unsigned index = 0);
-    size_t find(const LChar*, unsigned index = 0);
-    ALWAYS_INLINE size_t find(const char* s, unsigned index = 0) { return find(reinterpret_cast<const LChar*>(s), index); }
-    size_t find(StringImpl*);
-    size_t find(StringImpl*, unsigned index);
-    size_t findIgnoringCase(const LChar*, unsigned index = 0);
-    ALWAYS_INLINE size_t findIgnoringCase(const char* s, unsigned index = 0) { return findIgnoringCase(reinterpret_cast<const LChar*>(s), index); }
-    size_t findIgnoringCase(StringImpl*, unsigned index = 0);
-    size_t findIgnoringASCIICase(StringImpl*, unsigned index = 0);
+
+    // Find substrings.
+    size_t find(const StringView&, unsigned index = 0);
+    size_t findIgnoringCase(const StringView&, unsigned index = 0);
+    size_t findIgnoringASCIICase(const StringView&, unsigned index = 0);
 
     size_t reverseFind(UChar, unsigned index = UINT_MAX);
     size_t reverseFind(StringImpl*, unsigned index = UINT_MAX);
diff --git a/third_party/WebKit/Source/wtf/text/TextEncodingRegistry.cpp b/third_party/WebKit/Source/wtf/text/TextEncodingRegistry.cpp
index 129722e..e541198 100644
--- a/third_party/WebKit/Source/wtf/text/TextEncodingRegistry.cpp
+++ b/third_party/WebKit/Source/wtf/text/TextEncodingRegistry.cpp
@@ -293,7 +293,7 @@
     if (!alias.length())
         return 0;
 
-    if (alias.contains(static_cast<UChar>('\0')))
+    if (alias.contains('\0'))
         return 0;
 
     if (alias.is8Bit())
diff --git a/third_party/WebKit/Source/wtf/text/WTFString.h b/third_party/WebKit/Source/wtf/text/WTFString.h
index 9236f86..2595365 100644
--- a/third_party/WebKit/Source/wtf/text/WTFString.h
+++ b/third_party/WebKit/Source/wtf/text/WTFString.h
@@ -169,23 +169,22 @@
     static String numberToStringECMAScript(double);
     static String numberToStringFixedWidth(double, unsigned decimalPlaces);
 
-    // Find a single character or string, also with match function & latin1
-    // forms.
+    // Find characters.
     size_t find(UChar c, unsigned start = 0) const
         { return m_impl ? m_impl->find(c, start) : kNotFound; }
     size_t find(LChar c, unsigned start = 0) const
         { return m_impl ? m_impl->find(c, start) : kNotFound; }
     size_t find(char c, unsigned start = 0) const { return find(static_cast<LChar>(c), start); }
-
-    size_t find(const String& str) const
-        { return m_impl ? m_impl->find(str.impl()) : kNotFound; }
-    size_t find(const String& str, unsigned start) const
-        { return m_impl ? m_impl->find(str.impl(), start) : kNotFound; }
-
     size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const
         { return m_impl ? m_impl->find(matchFunction, start) : kNotFound; }
-    size_t find(const LChar* str, unsigned start = 0) const
-        { return m_impl ? m_impl->find(str, start) : kNotFound; }
+
+    // Find substrings.
+    size_t find(const StringView& value, unsigned start = 0, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
+        { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->find, (value, start)) : kNotFound; }
+
+    bool contains(char c) const { return find(c) != kNotFound; }
+    bool contains(const StringView& value, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
+        { return find(value, 0, caseSensitivity) != kNotFound; }
 
     // Find the last instance of a single character or string.
     size_t reverseFind(UChar c, unsigned start = UINT_MAX) const
@@ -203,12 +202,6 @@
     size_t findIgnoringASCIICase(const String& str, unsigned start = 0) const
         { return m_impl ? m_impl->findIgnoringASCIICase(str.impl(), start) : kNotFound; }
 
-    // Wrappers for find adding dynamic sensitivity check.
-    size_t find(const LChar* str, unsigned start, TextCaseSensitivity caseSensitivity) const
-        { return DISPATCH_CASE_OP(caseSensitivity, find, (str, start)); }
-    size_t find(const String& str, unsigned start, TextCaseSensitivity caseSensitivity) const
-        { return DISPATCH_CASE_OP(caseSensitivity, find, (str, start)); }
-
     unsigned copyTo(UChar* buffer, unsigned pos, unsigned maxLength) const;
 
     template<typename BufferType>
@@ -218,10 +211,6 @@
     void prependTo(BufferType&, unsigned pos = 0, unsigned len = UINT_MAX) const;
 
     UChar32 characterStartingAt(unsigned) const;
-    template<typename CharacterType>
-    bool contains(CharacterType c) const { return find(c) != kNotFound; }
-    bool contains(const LChar* str, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { return find(str, 0, caseSensitivity) != kNotFound; }
-    bool contains(const String& str, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { return find(str, 0, caseSensitivity) != kNotFound; }
 
     bool startsWith(const StringView& prefix, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const
         { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->startsWith, (prefix)) : prefix.isEmpty(); }
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/config/irc.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/config/irc.py
deleted file mode 100644
index 6dd299d..0000000
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/config/irc.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2013 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#
-# 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.
-
-server = "irc.freenode.net"
-port = 6667
-channel = "#blink"
-nickname = "commit-bot"
-
-update_wait_seconds = 10
-retry_attempts = 8
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py
index 374a8ad..e176c5f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/net/buildbot.py
@@ -91,10 +91,9 @@
     def fetch_results(self, build):
         return self.fetch_layout_test_results(self.results_url(build.builder_name, build.build_number))
 
+    @memoized
     def fetch_layout_test_results(self, results_url):
         """Returns a LayoutTestResults object for results fetched from a given URL."""
-        # FIXME: This should cache that the result was a 404 and stop hitting the network.
-        # This may be able to be done by just adding a @memoized decorator.
         results_file = NetworkTransaction(convert_404_to_None=True).run(
             lambda: self._fetch_file_from_results(results_url, "failing_results.json"))
         revision = NetworkTransaction(convert_404_to_None=True).run(
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py
index 402fd02..7803e5b23 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/controllers/manager_unittest.py
@@ -29,6 +29,7 @@
 
 """Unit tests for manager.py."""
 
+import optparse
 import time
 import unittest
 
@@ -36,7 +37,6 @@
 from webkitpy.layout_tests.controllers.manager import Manager
 from webkitpy.layout_tests.models import test_expectations
 from webkitpy.layout_tests.models.test_run_results import TestRunResults
-from webkitpy.tool.mock_tool import MockOptions
 
 
 class FakePrinter(object):
@@ -51,7 +51,7 @@
         def get_manager():
             host = MockHost()
             port = host.port_factory.get('test-mac-mac10.10')
-            manager = Manager(port, options=MockOptions(http=True, max_locked_shards=1), printer=FakePrinter())
+            manager = Manager(port, options=optparse.Values({'http': True, 'max_locked_shards': 1}), printer=FakePrinter())
             return manager
 
         manager = get_manager()
@@ -62,7 +62,7 @@
 
     def test_servers_started(self):
         def get_manager(port):
-            manager = Manager(port, options=MockOptions(http=True, max_locked_shards=1), printer=FakePrinter())
+            manager = Manager(port, options=optparse.Values({'http': True, 'max_locked_shards': 1}), printer=FakePrinter())
             return manager
 
         def start_http_server(additional_dirs, number_of_drivers):
@@ -113,7 +113,10 @@
         def get_manager():
             host = MockHost()
             port = host.port_factory.get('test-mac-mac10.10')
-            manager = Manager(port, options=MockOptions(test_list=None, http=True, max_locked_shards=1), printer=FakePrinter())
+            manager = Manager(
+                port,
+                options=optparse.Values({'test_list': None, 'http': True, 'max_locked_shards': 1}),
+                printer=FakePrinter())
             return manager
         host = MockHost()
         port = host.port_factory.get('test-mac-mac10.10')
@@ -132,7 +135,7 @@
         port = host.port_factory.get('test-mac-mac10.10')
 
         def get_manager():
-            manager = Manager(port, options=MockOptions(max_locked_shards=1), printer=FakePrinter())
+            manager = Manager(port, options=optparse.Values({'max_locked_shards': 1}), printer=FakePrinter())
             return manager
         self._make_fake_test_result(port.host, '/tmp/layout-test-results')
         self.assertTrue(port.host.filesystem.exists('/tmp/layout-test-results'))
@@ -149,7 +152,7 @@
         port = host.port_factory.get('test-mac-mac10.10')
 
         def get_manager():
-            manager = Manager(port, options=MockOptions(max_locked_shards=1), printer=FakePrinter())
+            manager = Manager(port, options=optparse.Values({'max_locked_shards': 1}), printer=FakePrinter())
             return manager
         self._make_fake_test_result(port.host, '/tmp/layout-test-results')
         self.assertTrue(port.host.filesystem.exists('/tmp/layout-test-results'))
@@ -162,7 +165,7 @@
         port = host.port_factory.get('test-mac-mac10.10')
 
         def get_manager():
-            manager = Manager(port, options=MockOptions(max_locked_shards=1), printer=FakePrinter())
+            manager = Manager(port, options=optparse.Values({'max_locked_shards': 1}), printer=FakePrinter())
             return manager
         for x in range(1, 31):
             dir_name = '/tmp/layout-test-results' + '_' + str(x)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
index 6d80621..2286c39d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
@@ -26,6 +26,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+from collections import OrderedDict
 import unittest
 
 from webkitpy.common.host_mock import MockHost
@@ -34,12 +35,6 @@
 from webkitpy.layout_tests.models.test_configuration import *
 from webkitpy.layout_tests.models.test_expectations import *
 
-try:
-    from collections import OrderedDict
-except ImportError:
-    # Needed for Python < 2.7
-    from webkitpy.thirdparty.ordered_dict import OrderedDict
-
 
 class Base(unittest.TestCase):
     # Note that all of these tests are written assuming the configuration
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py
index 1394403..352eb15 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/android_unittest.py
@@ -31,15 +31,11 @@
 import time
 import unittest
 
-from webkitpy.common.system import executive_mock
 from webkitpy.common.system.executive_mock import MockExecutive2
 from webkitpy.common.system.systemhost_mock import MockSystemHost
-
 from webkitpy.layout_tests.port import android
-from webkitpy.layout_tests.port import port_testcase
-from webkitpy.layout_tests.port import driver
 from webkitpy.layout_tests.port import driver_unittest
-from webkitpy.tool.mock_tool import MockOptions
+from webkitpy.layout_tests.port import port_testcase
 
 # Type of tombstone test which the mocked Android Debug Bridge should execute.
 VALID_TOMBSTONE_TEST_TYPE = 0
@@ -167,7 +163,7 @@
 
     def test_check_build(self):
         host = MockSystemHost()
-        port = self.make_port(host=host, options=MockOptions(child_processes=1))
+        port = self.make_port(host=host, options=optparse.Values({'child_processes': 1}))
         host.filesystem.exists = lambda p: True
         port.check_build(needs_http=True, printer=port_testcase.FakePrinter())
 
@@ -247,10 +243,12 @@
         mock_adb = MockAndroidDebugBridge(2)
         mock_executive = MockExecutive2(run_command_fn=mock_adb.run_command)
 
-        port0 = android.AndroidPort(MockSystemHost(executive=mock_executive),
-                                    'android', options=MockOptions(additional_driver_flag=['--foo=bar']))
-        port1 = android.AndroidPort(MockSystemHost(executive=mock_executive),
-                                    'android', options=MockOptions(driver_name='content_shell'))
+        port0 = android.AndroidPort(
+            MockSystemHost(executive=mock_executive), 'android',
+            options=optparse.Values({'additional_driver_flag': ['--foo=bar']}))
+        port1 = android.AndroidPort(
+            MockSystemHost(executive=mock_executive), 'android',
+            options=optparse.Values({'driver_name': 'content_shell'}))
 
         self.assertEqual(1, port0.driver_cmd_line().count('--foo=bar'))
         self.assertEqual(0, port1.driver_cmd_line().count('--create-stdin-fifo'))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test_unittest.py
index 11ea3c2..59e8465 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/browser_test_unittest.py
@@ -26,15 +26,13 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
 
 from webkitpy.common.system.executive_mock import MockExecutive2
-from webkitpy.common.system.systemhost_mock import MockSystemHost
-from webkitpy.tool.mock_tool import MockOptions
-
 from webkitpy.layout_tests.models import test_run_results
 from webkitpy.layout_tests.port import browser_test
-from webkitpy.layout_tests.port import port_testcase
 from webkitpy.layout_tests.port import browser_test_driver
+from webkitpy.layout_tests.port import port_testcase
 
 
 class _BrowserTestTestCaseMixin(object):
@@ -48,13 +46,13 @@
         self.assertTrue(self.make_port()._path_to_driver().endswith(self.driver_name_endswith))
 
     def test_default_timeout_ms(self):
-        self.assertEqual(self.make_port(options=MockOptions(configuration='Release')).default_timeout_ms(),
+        self.assertEqual(self.make_port(options=optparse.Values({'configuration': 'Release'})).default_timeout_ms(),
                          self.timeout_ms)
-        self.assertEqual(self.make_port(options=MockOptions(configuration='Debug')).default_timeout_ms(),
+        self.assertEqual(self.make_port(options=optparse.Values({'configuration': 'Debug'})).default_timeout_ms(),
                          3 * self.timeout_ms)
 
     def test_driver_type(self):
-        self.assertTrue(isinstance(self.make_port(options=MockOptions(driver_name='browser_tests')
+        self.assertTrue(isinstance(self.make_port(options=optparse.Values({'driver_name': 'browser_tests'})
                                                   ).create_driver(1), browser_test_driver.BrowserTestDriver))
 
     def test_layout_tests_dir(self):
@@ -93,5 +91,5 @@
     timeout_ms = 20 * 1000
 
     def test_driver_path(self):
-        test_port = self.make_port(options=MockOptions(driver_name='browser_tests'))
+        test_port = self.make_port(options=optparse.Values({'driver_name': 'browser_tests'}))
         self.assertNotIn('.app/Contents/MacOS', test_port._path_to_driver())
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
index 2276f2a3..d032001 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/driver_unittest.py
@@ -26,25 +26,21 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
 import unittest
 
 from webkitpy.common.system.systemhost_mock import MockSystemHost
-
 from webkitpy.layout_tests.port.base import Port
 from webkitpy.layout_tests.port.driver import Driver
-from webkitpy.layout_tests.port.driver import DriverOutput
-from webkitpy.layout_tests.port.server_process_mock import MockServerProcess
-
 # FIXME: remove the dependency on TestWebKitPort
 from webkitpy.layout_tests.port.port_testcase import TestWebKitPort
-
-from webkitpy.tool.mock_tool import MockOptions
+from webkitpy.layout_tests.port.server_process_mock import MockServerProcess
 
 
 class DriverTest(unittest.TestCase):
 
     def make_port(self):
-        port = Port(MockSystemHost(), 'test', MockOptions(configuration='Release'))
+        port = Port(MockSystemHost(), 'test', optparse.Values({'configuration': 'Release'}))
         return port
 
     def _assert_wrapper(self, wrapper_string, expected_wrapper):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
index c2846ddf..51ffc07 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/factory_unittest.py
@@ -26,18 +26,16 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
 import unittest
 
-from webkitpy.tool.mock_tool import MockOptions
 from webkitpy.common.host_mock import MockHost
 from webkitpy.common.webkit_finder import WebKitFinder
-
 from webkitpy.layout_tests.port import android
+from webkitpy.layout_tests.port import factory
 from webkitpy.layout_tests.port import linux
 from webkitpy.layout_tests.port import mac
 from webkitpy.layout_tests.port import win
-from webkitpy.layout_tests.port import factory
-from webkitpy.layout_tests.port import test
 
 
 class FactoryTest(unittest.TestCase):
@@ -46,7 +44,7 @@
     # instead of passing generic "options".
 
     def setUp(self):
-        self.webkit_options = MockOptions(pixel_tests=False)
+        self.webkit_options = optparse.Values({'pixel_tests': False})
 
     def assert_port(self, port_name=None, os_name=None, os_version=None, options=None, cls=None):
         host = MockHost(os_name=os_name, os_version=os_version)
@@ -86,7 +84,7 @@
         files = files or {}
         for path, contents in files.items():
             host.filesystem.write_text_file(wkf.path_from_chromium_base(path), contents)
-        options = MockOptions(target=target, configuration=configuration)
+        options = optparse.Values({'target': target, 'configuration': configuration})
         return factory.PortFactory(host).get(options=options)
 
     def test_default_target_and_configuration(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py
index fb09b1b..9b3e792 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/linux_unittest.py
@@ -26,11 +26,12 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
+
 from webkitpy.common.system import executive_mock
 from webkitpy.common.system.systemhost_mock import MockSystemHost
 from webkitpy.layout_tests.port import linux
 from webkitpy.layout_tests.port import port_testcase
-from webkitpy.tool.mock_tool import MockOptions
 
 
 class LinuxPortTest(port_testcase.PortTestCase):
@@ -86,16 +87,16 @@
 
     def test_build_path(self):
         # Test that optional paths are used regardless of whether they exist.
-        options = MockOptions(configuration='Release', build_directory='/foo')
+        options = optparse.Values({'configuration': 'Release', 'build_directory': '/foo'})
         self.assert_build_path(options, ['/mock-checkout/out/Release'], '/foo/Release')
 
         # Test that optional relative paths are returned unmodified.
-        options = MockOptions(configuration='Release', build_directory='foo')
+        options = optparse.Values({'configuration': 'Release', 'build_directory': 'foo'})
         self.assert_build_path(options, ['/mock-checkout/out/Release'], 'foo/Release')
 
     def test_driver_name_option(self):
         self.assertTrue(self.make_port()._path_to_driver().endswith('content_shell'))
-        self.assertTrue(self.make_port(options=MockOptions(driver_name='OtherDriver'))._path_to_driver().endswith('OtherDriver'))
+        self.assertTrue(self.make_port(options=optparse.Values({'driver_name': 'OtherDriver'}))._path_to_driver().endswith('OtherDriver'))
 
     def test_path_to_image_diff(self):
         self.assertEqual(self.make_port()._path_to_image_diff(), '/mock-checkout/out/Release/image_diff')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
index fb90b578..2d5260b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mac_unittest.py
@@ -26,10 +26,10 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
 
 from webkitpy.layout_tests.port import mac
 from webkitpy.layout_tests.port import port_testcase
-from webkitpy.tool.mock_tool import MockOptions
 
 
 class MacPortTest(port_testcase.PortTestCase):
@@ -48,20 +48,20 @@
 
     def test_build_path(self):
         # Test that optional paths are used regardless of whether they exist.
-        options = MockOptions(configuration='Release', build_directory='/foo')
+        options = optparse.Values({'configuration': 'Release', 'build_directory': '/foo'})
         self.assert_build_path(options, ['/mock-checkout/out/Release'], '/foo/Release')
 
         # Test that optional relative paths are returned unmodified.
-        options = MockOptions(configuration='Release', build_directory='foo')
+        options = optparse.Values({'configuration': 'Release', 'build_directory': 'foo'})
         self.assert_build_path(options, ['/mock-checkout/out/Release'], 'foo/Release')
 
         # Test that we prefer the legacy dir over the new dir.
-        options = MockOptions(configuration='Release', build_directory=None)
+        options = optparse.Values({'configuration': 'Release', 'build_directory': None})
         self.assert_build_path(options, ['/mock-checkout/xcodebuild/Release',
                                          '/mock-checkout/out/Release'], '/mock-checkout/xcodebuild/Release')
 
     def test_build_path_timestamps(self):
-        options = MockOptions(configuration='Release', build_directory=None)
+        options = optparse.Values({'configuration': 'Release', 'build_directory': None})
         port = self.make_port(options=options)
         port.host.filesystem.maybe_make_directory('/mock-checkout/out/Release')
         port.host.filesystem.maybe_make_directory('/mock-checkout/xcodebuild/Release')
@@ -74,7 +74,7 @@
 
     def test_driver_name_option(self):
         self.assertTrue(self.make_port()._path_to_driver().endswith('Content Shell'))
-        self.assertTrue(self.make_port(options=MockOptions(driver_name='OtherDriver'))._path_to_driver().endswith('OtherDriver'))
+        self.assertTrue(self.make_port(options=optparse.Values(dict(driver_name='OtherDriver')))._path_to_driver().endswith('OtherDriver'))
 
     def test_path_to_image_diff(self):
         self.assertEqual(self.make_port()._path_to_image_diff(), '/mock-checkout/out/Release/image_diff')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
index 613d469..32c9e14 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/mock_drt_unittest.py
@@ -29,6 +29,7 @@
 """Unit tests for MockDRT."""
 
 import io
+import optparse
 import unittest
 
 from webkitpy.common.system.systemhost_mock import MockSystemHost
@@ -36,15 +37,11 @@
 from webkitpy.layout_tests.port import port_testcase
 from webkitpy.layout_tests.port import test
 from webkitpy.layout_tests.port.factory import PortFactory
-from webkitpy.tool.mock_tool import MockOptions
-
-
-mock_options = MockOptions(configuration='Release')
 
 
 class MockDRTPortTest(port_testcase.PortTestCase):
 
-    def make_port(self, host=None, options=mock_options):
+    def make_port(self, host=None, options=optparse.Values({'configuration': 'Release'})):
         host = host or MockSystemHost()
         test.add_unit_tests_to_mock_filesystem(host.filesystem)
         return mock_drt.MockDRTPort(host, port_name='mock-mac', options=options)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
index 4b6cd892..3ea3f0a 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/port_testcase.py
@@ -30,6 +30,7 @@
 
 import collections
 import errno
+import optparse
 import socket
 import unittest
 
@@ -40,9 +41,6 @@
 from webkitpy.common.system.systemhost_mock import MockSystemHost
 from webkitpy.layout_tests.models import test_run_results
 from webkitpy.layout_tests.port.base import Port
-from webkitpy.layout_tests.port.base import TestConfiguration
-from webkitpy.layout_tests.port.server_process_mock import MockServerProcess
-from webkitpy.tool.mock_tool import MockOptions
 
 
 # FIXME: get rid of this fixture
@@ -90,7 +88,7 @@
 
     def make_port(self, host=None, port_name=None, options=None, os_name=None, os_version=None, **kwargs):
         host = host or MockSystemHost(os_name=(os_name or self.os_name), os_version=(os_version or self.os_version))
-        options = options or MockOptions(configuration='Release')
+        options = options or optparse.Values({'configuration': 'Release'})
         port_name = port_name or self.port_name
         port_name = self.port_maker.determine_full_port_name(host, options, port_name)
         port = self.port_maker(host, port_name, options=options, **kwargs)
@@ -149,8 +147,8 @@
         self.assertEqual(port.default_max_locked_shards(), 1)
 
     def test_default_timeout_ms(self):
-        self.assertEqual(self.make_port(options=MockOptions(configuration='Release')).default_timeout_ms(), 6000)
-        self.assertEqual(self.make_port(options=MockOptions(configuration='Debug')).default_timeout_ms(), 18000)
+        self.assertEqual(self.make_port(options=optparse.Values({'configuration': 'Release'})).default_timeout_ms(), 6000)
+        self.assertEqual(self.make_port(options=optparse.Values({'configuration': 'Debug'})).default_timeout_ms(), 18000)
 
     def test_default_pixel_tests(self):
         self.assertEqual(self.make_port().default_pixel_tests(), True)
@@ -159,7 +157,7 @@
         port = self.make_port()
         self.assertTrue(len(port.driver_cmd_line()))
 
-        options = MockOptions(additional_driver_flag=['--foo=bar', '--foo=baz'])
+        options = optparse.Values(dict(additional_driver_flag=['--foo=bar', '--foo=baz']))
         port = self.make_port(options=options)
         cmd_line = port.driver_cmd_line()
         self.assertTrue('--foo=bar' in cmd_line)
@@ -316,7 +314,7 @@
         ])
 
     def test_expectations_files_wptserve_enabled(self):
-        port = self.make_port(options=MockOptions(enable_wptserve=True))
+        port = self.make_port(options=optparse.Values(dict(enable_wptserve=True)))
         self.assertEqual(port.expectations_files(), [
             port.path_to_generic_test_expectations_file(),
             port._filesystem.join(port.layout_tests_dir(), 'NeverFixTests'),
@@ -339,7 +337,7 @@
         ordered_dict = port.expectations_dict()
         self.assertEqual(port.path_to_generic_test_expectations_file(), ordered_dict.keys()[0])
 
-        options = MockOptions(additional_expectations=['/tmp/foo', '/tmp/bar'])
+        options = optparse.Values(dict(additional_expectations=['/tmp/foo', '/tmp/bar']))
         port = self.make_port(options=options)
         for path in port.expectations_files():
             port._filesystem.write_text_file(path, '')
@@ -418,7 +416,7 @@
         self.assertEqual(port.path_to_apache_config_file(), '/existing/httpd.conf')
 
     def test_additional_platform_directory(self):
-        port = self.make_port(options=MockOptions(additional_platform_directory=['/tmp/foo']))
+        port = self.make_port(options=optparse.Values(dict(additional_platform_directory=['/tmp/foo'])))
         self.assertEqual(port.baseline_search_path()[0], '/tmp/foo')
 
     def test_virtual_test_suites(self):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py
index 89ef5ff..07953dbb 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/win_unittest.py
@@ -26,12 +26,12 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
+
 from webkitpy.common.system import outputcapture
 from webkitpy.common.system.executive_mock import MockExecutive
-from webkitpy.common.system.filesystem_mock import MockFileSystem
 from webkitpy.layout_tests.port import port_testcase
 from webkitpy.layout_tests.port import win
-from webkitpy.tool.mock_tool import MockOptions
 
 
 class WinPortTest(port_testcase.PortTestCase):
@@ -56,7 +56,7 @@
         self.assertEqual(env['CYGWIN_PATH'], '/mock-checkout/third_party/cygwin/bin')
 
     def test_setup_environ_for_server_register_cygwin(self):
-        port = self.make_port(options=MockOptions(register_cygwin=True, results_directory='/'))
+        port = self.make_port(options=optparse.Values({'register_cygwin': True, 'results_directory': '/'}))
         port._executive = MockExecutive(should_log=True)
         expected_logs = "MOCK run_command: ['/mock-checkout/third_party/cygwin/setup_mount.bat'], cwd=None\n"
         output = outputcapture.OutputCapture()
@@ -112,19 +112,19 @@
 
     def test_build_path(self):
         # Test that optional paths are used regardless of whether they exist.
-        options = MockOptions(configuration='Release', build_directory='/foo')
+        options = optparse.Values({'configuration': 'Release', 'build_directory': '/foo'})
         self.assert_build_path(options, ['/mock-checkout/out/Release'], '/foo/Release')
 
         # Test that optional relative paths are returned unmodified.
-        options = MockOptions(configuration='Release', build_directory='foo')
+        options = optparse.Values({'configuration': 'Release', 'build_directory': 'foo'})
         self.assert_build_path(options, ['/mock-checkout/out/Release'], 'foo/Release')
 
         # Test that we prefer the legacy dir over the new dir.
-        options = MockOptions(configuration='Release', build_directory=None)
+        options = optparse.Values({'configuration': 'Release', 'build_directory': None})
         self.assert_build_path(options, ['/mock-checkout/build/Release', '/mock-checkout/out'], '/mock-checkout/build/Release')
 
     def test_build_path_timestamps(self):
-        options = MockOptions(configuration='Release', build_directory=None)
+        options = optparse.Values({'configuration': 'Release', 'build_directory': None})
         port = self.make_port(options=options)
         port.host.filesystem.maybe_make_directory('/mock-checkout/out/Release')
         port.host.filesystem.maybe_make_directory('/mock-checkout/build/Release')
@@ -140,8 +140,8 @@
 
     def test_driver_name_option(self):
         self.assertTrue(self.make_port()._path_to_driver().endswith('content_shell.exe'))
-        self.assertTrue(self.make_port(options=MockOptions(driver_name='OtherDriver')
-                                       )._path_to_driver().endswith('OtherDriver.exe'))
+        self.assertTrue(
+            self.make_port(options=optparse.Values({'driver_name': 'OtherDriver'}))._path_to_driver().endswith('OtherDriver.exe'))
 
     def test_path_to_image_diff(self):
         self.assertEqual(self.make_port()._path_to_image_diff(), '/mock-checkout/out/Release/image_diff.exe')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest.py b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest.py
index 43e77ac4..814bfead 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftest.py
@@ -103,9 +103,6 @@
     def description(self):
         return self._description
 
-    def prepare(self, time_out_ms):
-        return True
-
     def _create_driver(self):
         return self._port.create_driver(worker_number=0, no_timeout=True)
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
index 81eefb7..eb2a84f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/performance_tests/perftestsrunner.py
@@ -200,10 +200,6 @@
             runs = ' (Run %d of %d)' % (run_count, repeat) if repeat > 1 else ''
             _log.info("Running %d tests%s", len(tests), runs)
 
-            for test in tests:
-                if not test.prepare(self._options.time_out_ms):
-                    return self.EXIT_CODE_BAD_PREPARATION
-
             try:
                 if needs_http:
                     self._start_http_servers()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py
index 9207872b..8177691 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py
@@ -29,19 +29,25 @@
 import time
 
 from webkitpy.common.checkout.scm.git import Git
-from webkitpy.common.config.irc import server, port, channel, nickname
-from webkitpy.common.config.irc import update_wait_seconds, retry_attempts
 from webkitpy.common.system.executive import ScriptError
 from webkitpy.thirdparty.irc.ircbot import SingleServerIRCBot
 
 _log = logging.getLogger(__name__)
 
+SERVER = "irc.freenode.net"
+PORT = 6667
+CHANNEL = "#blink"
+NICKNAME = "commit-bot"
+
+UPDATE_WAIT_SECONDS = 10
+RETRY_ATTEMPTS = 8
+
 
 class CommitAnnouncer(SingleServerIRCBot):
     _commit_detail_format = "%H\n%ae\n%s\n%b"  # commit-sha1, author email, subject, body
 
     def __init__(self, tool, announce_path, irc_password):
-        SingleServerIRCBot.__init__(self, [(server, port, irc_password)], nickname, nickname)
+        SingleServerIRCBot.__init__(self, [(SERVER, PORT, irc_password)], NICKNAME, NICKNAME)
         self.announce_path = announce_path
         self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive)
         self.commands = {
@@ -96,7 +102,7 @@
         connection.nick('%s_' % connection.get_nickname())
 
     def on_welcome(self, connection, event):
-        connection.join(channel)
+        connection.join(CHANNEL)
 
     def on_pubmsg(self, connection, event):
         message = event.arguments()[0]
@@ -117,18 +123,18 @@
                 return False
 
         attempts = 1
-        while attempts <= retry_attempts:
+        while attempts <= RETRY_ATTEMPTS:
             if attempts > 1:
                 # User may have sent a keyboard interrupt during the wait.
                 if not self.connection.is_connected():
                     return False
-                wait = int(update_wait_seconds) << (attempts - 1)
+                wait = int(UPDATE_WAIT_SECONDS) << (attempts - 1)
                 if wait < 120:
                     _log.info('Waiting %s seconds', wait)
                 else:
                     _log.info('Waiting %s minutes', wait / 60)
                 time.sleep(wait)
-                _log.info('Pull attempt %s out of %s', attempts, retry_attempts)
+                _log.info('Pull attempt %s out of %s', attempts, RETRY_ATTEMPTS)
             try:
                 self.git.pull()
                 return True
@@ -182,7 +188,7 @@
         return ('%s %s committed "%s" %s' % (url, email, subject, red_flag_message)).strip()
 
     def _post(self, message):
-        self.connection.execute_delayed(0, lambda: self.connection.privmsg(channel, self._sanitize_string(message)))
+        self.connection.execute_delayed(0, lambda: self.connection.privmsg(CHANNEL, self._sanitize_string(message)))
 
     def _sanitize_string(self, message):
         return message.encode('ascii', 'backslashreplace')
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py
index f7a29c4..a4c357b 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/analyze_baselines_unittest.py
@@ -2,11 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import optparse
+
 from webkitpy.common.checkout.baselineoptimizer import BaselineOptimizer
-from webkitpy.layout_tests.controllers.test_result_writer import TestResultWriter
 from webkitpy.tool.commands.analyze_baselines import AnalyzeBaselines
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
-from webkitpy.tool.mock_tool import MockOptions
 
 
 class _FakeOptimizer(BaselineOptimizer):
@@ -29,13 +29,13 @@
         self.command._write = (lambda msg: self.lines.append(msg))
 
     def test_default(self):
-        self.command.execute(MockOptions(suffixes='txt', missing=False, platform=None), ['passes/text.html'], self.tool)
+        self.command.execute(optparse.Values(dict(suffixes='txt', missing=False, platform=None)), ['passes/text.html'], self.tool)
         self.assertEqual(self.lines,
                          ['passes/text-expected.txt:',
                           '  (generic): 123456'])
 
     def test_missing_baselines(self):
-        self.command.execute(MockOptions(suffixes='png,txt', missing=True, platform=None), ['passes/text.html'], self.tool)
+        self.command.execute(optparse.Values(dict(suffixes='png,txt', missing=True, platform=None)), ['passes/text.html'], self.tool)
         self.assertEqual(self.lines,
                          ['passes/text-expected.png: (no baselines found)',
                           'passes/text-expected.txt:',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py
index d768ab9d..08bae64 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/auto_rebaseline_unittest.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import optparse
+
 from webkitpy.common.net.buildbot import Build
 from webkitpy.common.net.layouttestresults import LayoutTestResults
 from webkitpy.common.system.executive_mock import MockExecutive
@@ -9,7 +11,6 @@
 from webkitpy.tool.commands.auto_rebaseline import AutoRebaseline
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
 from webkitpy.tool.commands.rebaseline_unittest import MockLineRemovingExecutive
-from webkitpy.tool.mock_tool import MockOptions
 
 
 class TestAutoRebaseline(BaseTestCase):
@@ -21,10 +22,16 @@
 
     def _execute_with_mock_options(self, auth_refresh_token_json=None, commit_author=None, dry_run=False):
         self.command.execute(
-            MockOptions(optimize=True, verbose=False, results_directory=False,
-                        auth_refresh_token_json=auth_refresh_token_json,
-                        commit_author=commit_author, dry_run=dry_run),
-            [], self.tool)
+            optparse.Values({
+                'optimize': True,
+                'verbose': False,
+                'results_directory': False,
+                'auth_refresh_token_json': auth_refresh_token_json,
+                'commit_author': commit_author,
+                'dry_run': dry_run
+            }),
+            [],
+            self.tool)
 
     def setUp(self):
         super(TestAutoRebaseline, self).setUp()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py
index 413ae79..b1e4398 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/command_test.py
@@ -26,16 +26,17 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
 import unittest
 
 from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.tool.mock_tool import MockOptions, MockWebKitPatch
+from webkitpy.tool.mock_tool import MockWebKitPatch
 
 
 class CommandsTest(unittest.TestCase):
 
     def assert_execute_outputs(self, command, args=None, expected_stdout="", expected_stderr="",
-                               expected_exception=None, expected_logs=None, options=MockOptions(), tool=MockWebKitPatch()):
+                               expected_exception=None, expected_logs=None, options=optparse.Values(), tool=MockWebKitPatch()):
         args = args or []
         options.blocks = None
         options.cc = 'MOCK cc'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/commit_announcer.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/commit_announcer.py
index ab9d2cc..4c00a69f 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/commit_announcer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/commit_announcer.py
@@ -24,16 +24,17 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import logging
-from optparse import make_option
+import optparse
 import time
 import traceback
 
-from webkitpy.common.config.irc import update_wait_seconds
 from webkitpy.tool.bot.commit_announcer import CommitAnnouncerThread
+from webkitpy.tool.bot.commit_announcer import UPDATE_WAIT_SECONDS
 from webkitpy.tool.commands.command import Command
 
 _log = logging.getLogger(__name__)
-announce_path = "third_party/WebKit"
+ANNOUNCE_PATH = "third_party/WebKit"
+
 
 
 class CommitAnnouncerCommand(Command):
@@ -43,18 +44,18 @@
 
     def __init__(self):
         options = [
-            make_option("--irc-password", default=None, help="Specify IRC password to use."),
+            optparse.make_option("--irc-password", default=None, help="Specify IRC password to use."),
         ]
         super(CommitAnnouncerCommand, self).__init__(options)
 
     def execute(self, options, args, tool):
-        bot_thread = CommitAnnouncerThread(tool, announce_path, options.irc_password)
+        bot_thread = CommitAnnouncerThread(tool, ANNOUNCE_PATH, options.irc_password)
         bot_thread.start()
         _log.info("Bot started")
         try:
             while bot_thread.is_alive():
                 bot_thread.bot.post_new_commits()
-                time.sleep(update_wait_seconds)
+                time.sleep(UPDATE_WAIT_SECONDS)
         except KeyboardInterrupt:
             _log.error("Terminated by keyboard interrupt")
         except Exception:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/flaky_tests_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/flaky_tests_unittest.py
index ad38515..73c1d2df 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/flaky_tests_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/flaky_tests_unittest.py
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import optparse
+
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.layout_tests.layout_package import bot_test_expectations
 from webkitpy.tool.commands import flaky_tests
 from webkitpy.tool.commands.command_test import CommandsTest
-from webkitpy.tool.mock_tool import MockWebKitPatch, MockOptions
+from webkitpy.tool.mock_tool import MockWebKitPatch
 
 
 class FakeBotTestExpectations(object):
@@ -73,7 +75,7 @@
         tool = MockWebKitPatch()
         tool.builders = self.fake_builders_list()
         command.expectations_factory = FakeBotTestExpectationsFactory
-        options = MockOptions(upload=True)
+        options = optparse.Values({'upload': True})
         expected_stdout = flaky_tests.FlakyTests.OUTPUT % (
             flaky_tests.FlakyTests.HEADER,
             '',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py
index 9242a8b..a4bdc0d 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/optimize_baselines_unittest.py
@@ -2,10 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import optparse
+
 from webkitpy.common.system.outputcapture import OutputCapture
 from webkitpy.tool.commands.optimize_baselines import OptimizeBaselines
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
-from webkitpy.tool.mock_tool import MockOptions
 
 
 class TestOptimizeBaselines(BaseTestCase):
@@ -25,7 +26,7 @@
         self._write_test_file(test_port, 'another/test-expected.txt', "result A")
 
         OutputCapture().assert_outputs(self, self.command.execute, args=[
-            MockOptions(suffixes='txt', no_modify_scm=False, platform='test-mac-mac10.10'),
+            optparse.Values({'suffixes': 'txt', 'no_modify_scm': False, 'platform': 'test-mac-mac10.10'}),
             ['another/test.html'],
             self.tool,
         ], expected_stdout='{"add": [], "remove-lines": [], "delete": []}\n')
@@ -42,7 +43,7 @@
         self._write_test_file(test_port, 'another/test-expected.txt', "result A")
 
         OutputCapture().assert_outputs(self, self.command.execute, args=[
-            MockOptions(suffixes='txt', no_modify_scm=True, platform='test-mac-mac10.10'),
+            optparse.Values({'suffixes': 'txt', 'no_modify_scm': True, 'platform': 'test-mac-mac10.10'}),
             ['another/test.html'],
             self.tool,
         ], expected_stdout='{"add": [], "remove-lines": [], "delete": ["/test.checkout/LayoutTests/platform/test-mac-mac10.10/another/test-expected.txt"]}\n')
@@ -63,9 +64,10 @@
         try:
             oc = OutputCapture()
             oc.capture_output()
-            self.command.execute(MockOptions(suffixes='txt,wav,png', no_modify_scm=True, platform='test-mac-mac10.10'),
-                                 ['another/test.html'],
-                                 self.tool)
+            self.command.execute(
+                optparse.Values({'suffixes': 'txt,wav,png', 'no_modify_scm': True, 'platform': 'test-mac-mac10.10'}),
+                ['another/test.html'],
+                self.tool)
         finally:
             out, _, _ = oc.restore_output()
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py
index e74c2c1d..1d6efd5 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/queries_unittest.py
@@ -27,11 +27,13 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+import optparse
 import unittest
 
 from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.tool.commands.queries import *
-from webkitpy.tool.mock_tool import MockWebKitPatch, MockOptions
+from webkitpy.tool.commands.queries import PrintBaselines
+from webkitpy.tool.commands.queries import PrintExpectations
+from webkitpy.tool.mock_tool import MockWebKitPatch
 
 
 class PrintExpectationsTest(unittest.TestCase):
@@ -42,7 +44,7 @@
             'include_keyword': [], 'exclude_keyword': [], 'paths': False,
         }
         options_defaults.update(kwargs)
-        options = MockOptions(**options_defaults)
+        options = optparse.Values(dict(**options_defaults))
         tool = MockWebKitPatch()
         tool.port_factory.all_port_names = lambda: [
             'test-linux-trusty', 'test-linux-precise',
@@ -141,8 +143,8 @@
         command = PrintBaselines()
         command.bind_to_tool(self.tool)
         self.capture_output()
-        command.execute(MockOptions(all=False, include_virtual_tests=False,
-                                    csv=False, platform=None), ['passes/text.html'], self.tool)
+        options = optparse.Values({'all': False, 'include_virtual_tests': False, 'csv': False, 'platform': None})
+        command.execute(options, ['passes/text.html'], self.tool)
         stdout, _, _ = self.restore_output()
         self.assertMultiLineEqual(stdout,
                                   ('// For test-win-win7\n'
@@ -153,8 +155,8 @@
         command = PrintBaselines()
         command.bind_to_tool(self.tool)
         self.capture_output()
-        command.execute(MockOptions(all=False, include_virtual_tests=False, csv=False,
-                                    platform='test-win-*'), ['passes/text.html'], self.tool)
+        options = optparse.Values({'all': False, 'include_virtual_tests': False, 'csv': False, 'platform': 'test-win-*'})
+        command.execute(options, ['passes/text.html'], self.tool)
         stdout, _, _ = self.restore_output()
         self.assertMultiLineEqual(stdout,
                                   ('// For test-win-win10\n'
@@ -169,8 +171,8 @@
         command = PrintBaselines()
         command.bind_to_tool(self.tool)
         self.capture_output()
-        command.execute(MockOptions(all=False, platform='*win7', csv=True,
-                                    include_virtual_tests=False), ['passes/text.html'], self.tool)
+        options = optparse.Values({'all': False, 'platform': '*win7', 'csv': True, 'include_virtual_tests': False})
+        command.execute(options, ['passes/text.html'], self.tool)
         stdout, _, _ = self.restore_output()
         self.assertMultiLineEqual(stdout,
                                   ('test-win-win7,passes/text.html,None,png,passes/text-expected.png,None\n'
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
index 77fe0e4..242f9a2 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
@@ -62,14 +62,14 @@
         """Gets the Rietveld CL number from either |options| or from the current local branch."""
         if options.issue:
             return options.issue
-        issue_number = self._git().get_issue_number()
+        issue_number = self.git().get_issue_number()
         _log.debug('Issue number for current branch: %s', issue_number)
         if not issue_number.isdigit():
             _log.error('No issue number given and no issue for current branch.')
             return None
         return int(issue_number)
 
-    def _git(self):
+    def git(self):
         """Returns a Git instance; can be overridden for tests."""
         # Pass in a current working directory inside of the repo so
         # that this command can be called from outside of the repo.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
index 19f17e2..4c2ec2c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
@@ -2,16 +2,16 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import optparse
 import json
 
+from webkitpy.common.checkout.scm.scm_mock import MockSCM
 from webkitpy.common.net.buildbot import Build
 from webkitpy.common.net.web_mock import MockWeb
 from webkitpy.common.system.outputcapture import OutputCapture
 from webkitpy.layout_tests.builder_list import BuilderList
 from webkitpy.tool.commands.rebaseline_from_try_jobs import RebaselineFromTryJobs
 from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase
-from webkitpy.tool.mock_tool import MockOptions
-from webkitpy.common.checkout.scm.scm_mock import MockSCM
 
 
 class RebaselineFromTryJobsTest(BaseTestCase):
@@ -50,7 +50,7 @@
         })
         self.git = MockSCM()
         self.git.get_issue_number = lambda: 'None'
-        self.command._git = lambda: self.git
+        self.command.git = lambda: self.git
 
     @staticmethod
     def command_options(**kwargs):
@@ -62,7 +62,7 @@
             'results_directory': None,
         }
         options.update(kwargs)
-        return MockOptions(**options)
+        return optparse.Values(dict(**options))
 
     def test_execute_with_issue_number_given(self):
         oc = OutputCapture()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
index f988172..5e83405 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_unittest.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import optparse
 import unittest
 
 from webkitpy.common.net.buildbot import Build
@@ -11,13 +12,12 @@
 from webkitpy.common.system.executive_mock import MockExecutive2
 from webkitpy.common.system.outputcapture import OutputCapture
 from webkitpy.layout_tests.builder_list import BuilderList
+from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand
 from webkitpy.tool.commands.rebaseline import CopyExistingBaselinesInternal
-from webkitpy.tool.commands.rebaseline import RebaselineExpectations
 from webkitpy.tool.commands.rebaseline import Rebaseline
+from webkitpy.tool.commands.rebaseline import RebaselineExpectations
 from webkitpy.tool.commands.rebaseline import RebaselineJson
 from webkitpy.tool.commands.rebaseline import RebaselineTest
-from webkitpy.tool.commands.rebaseline import AbstractParallelRebaselineCommand
-from webkitpy.tool.mock_tool import MockOptions
 from webkitpy.tool.mock_tool import MockWebKitPatch
 
 
@@ -124,9 +124,13 @@
 
         oc = OutputCapture()
         try:
-            options = MockOptions(builder="MOCK Mac10.11", suffixes="txt", verbose=True,
-                                  test="failures/expected/image.html", results_directory=None)
-
+            options = optparse.Values({
+                'builder': "MOCK Mac10.11",
+                'suffixes': 'txt',
+                'verbose': True,
+                'test': "failures/expected/image.html",
+                'results_directory': None
+            })
             oc.capture_output()
             self.command.execute(options, [], self.tool)
         finally:
@@ -149,9 +153,13 @@
 
         oc = OutputCapture()
         try:
-            options = MockOptions(builder="MOCK Win7", suffixes="txt", verbose=True,
-                                  test="failures/expected/image.html", results_directory=None)
-
+            options = optparse.Values({
+                'builder': "MOCK Win7",
+                'suffixes': "txt",
+                'verbose': True,
+                'test': "failures/expected/image.html",
+                'results_directory': None
+            })
             oc.capture_output()
             self.command.execute(options, [], self.tool)
         finally:
@@ -177,9 +185,13 @@
 
         oc = OutputCapture()
         try:
-            options = MockOptions(builder="MOCK Win7", suffixes="txt", verbose=True,
-                                  test="failures/expected/image.html", results_directory=None)
-
+            options = optparse.Values({
+                'builder': "MOCK Win7",
+                'suffixes': "txt",
+                'verbose': True,
+                'test': "failures/expected/image.html",
+                'results_directory': None
+            })
             oc.capture_output()
             self.command.execute(options, [], self.tool)
         finally:
@@ -215,9 +227,12 @@
              "[ Linux ] failures/expected/image.html [ Skip ]\n"))
         oc = OutputCapture()
         try:
-            options = MockOptions(builder="MOCK Win7", suffixes="txt", verbose=True,
-                                  test="failures/expected/image.html", results_directory=None)
-
+            options = optparse.Values({
+                'builder': "MOCK Win7",
+                'suffixes': "txt", 'verbose': True,
+                'test': "failures/expected/image.html",
+                'results_directory': None
+            })
             oc.capture_output()
             self.command.execute(options, [], self.tool)
         finally:
@@ -245,9 +260,16 @@
 
     def setUp(self):
         super(TestRebaselineTest, self).setUp()
-        self.options = MockOptions(
-            builder="MOCK Mac10.11", test="userscripts/another-test.html", suffixes="txt", results_directory=None,
-            build_number=None)
+
+    @staticmethod
+    def options(**kwargs):
+        return optparse.Values(dict({
+            'builder': "MOCK Mac10.11",
+            'test': "userscripts/another-test.html",
+            'suffixes': "txt",
+            'results_directory': None,
+            'build_number': None
+        }, **kwargs))
 
     def test_baseline_directory(self):
         command = self.command
@@ -270,8 +292,7 @@
         self._write("fast/css/large-list-of-rules-crash.html", "Dummy test contents")
         self._write("userscripts/another-test.html", "Dummy test contents")
 
-        self.options.suffixes = "png,wav,txt"
-        self.command._rebaseline_test_and_update_expectations(self.options)
+        self.command._rebaseline_test_and_update_expectations(self.options(suffixes="png,wav,txt"))
 
         self.assertItemsEqual(self.tool.web.urls_fetched,
                               [self.WEB_PREFIX + '/userscripts/another-test-actual.png',
@@ -293,15 +314,13 @@
             self.mac_expectations_path,
             ("Bug(x) [ Mac ] userscripts/another-test.html [ Failure ]\n"
              "bug(z) [ Linux ] userscripts/another-test.html [ Failure ]\n"))
-        self.options.results_directory = '/tmp'
-        self.command._rebaseline_test_and_update_expectations(self.options)
+        self.command._rebaseline_test_and_update_expectations(self.options(results_directory='/tmp'))
         self.assertItemsEqual(self.tool.web.urls_fetched, ['file:///tmp/userscripts/another-test-actual.txt'])
 
     def test_rebaseline_reftest(self):
         self._write("userscripts/another-test.html", "test data")
         self._write("userscripts/another-test-expected.html", "generic result")
-        self.options.suffixes = 'png'
-        OutputCapture().assert_outputs(self, self.command._rebaseline_test_and_update_expectations, args=[self.options],
+        OutputCapture().assert_outputs(self, self.command._rebaseline_test_and_update_expectations, args=[self.options(suffixes='png')],
                                        expected_logs="Cannot rebaseline image result for reftest: userscripts/another-test.html\n")
         self.assertDictEqual(self.command._scm_changes, {'add': [], 'remove-lines': [], "delete": []})
 
@@ -326,10 +345,15 @@
 
         oc = OutputCapture()
         try:
-            options = MockOptions(
-                optimize=True, builder="MOCK Win10", suffixes="txt", verbose=True, test="failures/expected/image.html",
-                results_directory=None, build_number=None)
-
+            options = optparse.Values({
+                'optimize': True,
+                'builder': "MOCK Win10",
+                'suffixes': "txt",
+                'verbose': True,
+                'test': "failures/expected/image.html",
+                'results_directory': None,
+                'build_number': None
+            })
             oc.capture_output()
             self.command.execute(options, [], self.tool)
         finally:
@@ -362,6 +386,14 @@
     def tearDown(self):
         super(TestRebaselineJson, self).tearDown()
 
+    @staticmethod
+    def options(**kwargs):
+        return optparse.Values(dict({
+            'optimize': True,
+            'verbose': True,
+            'results_directory': None
+        }, **kwargs))
+
     def test_rebaseline_test_passes_on_all_builders(self):
         self._setup_mock_build_data()
 
@@ -376,21 +408,18 @@
             }
         }))
 
-        options = MockOptions(optimize=True, verbose=True, results_directory=None)
-
         self._write(self.mac_expectations_path, "Bug(x) userscripts/first-test.html [ Failure ]\n")
         self._write("userscripts/first-test.html", "Dummy test contents")
 
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
+        self.command._rebaseline(self.options(), {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
 
         self.assertEqual(self.tool.executive.calls, [])
 
     def test_rebaseline_all(self):
         self._setup_mock_build_data()
 
-        options = MockOptions(optimize=True, verbose=True, results_directory=None)
         self._write("userscripts/first-test.html", "Dummy test contents")
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
+        self.command._rebaseline(self.options(), {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
 
         # Note that we have one run_in_parallel() call followed by a run_command()
         self.assertEqual(
@@ -407,9 +436,8 @@
     def test_rebaseline_debug(self):
         self._setup_mock_build_data()
 
-        options = MockOptions(optimize=True, verbose=True, results_directory=None)
         self._write("userscripts/first-test.html", "Dummy test contents")
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Win7 (dbg)"): ["txt", "png"]}})
+        self.command._rebaseline(self.options(), {"userscripts/first-test.html": {Build("MOCK Win7 (dbg)"): ["txt", "png"]}})
 
         # Note that we have one run_in_parallel() call followed by a run_command()
         self.assertEqual(
@@ -427,9 +455,10 @@
         self._setup_mock_build_data()
         print self.tool.buildbot._canned_results
 
-        options = MockOptions(optimize=False, verbose=True, results_directory=None)
         self._write("userscripts/first-test.html", "Dummy test contents")
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
+        self.command._rebaseline(
+            self.options(optimize=False),
+            {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
 
         # Note that we have only one run_in_parallel() call
         self.assertEqual(
@@ -444,9 +473,10 @@
     def test_results_directory(self):
         self._setup_mock_build_data()
 
-        options = MockOptions(optimize=False, verbose=True, results_directory='/tmp')
         self._write("userscripts/first-test.html", "Dummy test contents")
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
+        self.command._rebaseline(
+            self.options(optimize=False, results_directory='/tmp'),
+            {"userscripts/first-test.html": {Build("MOCK Win7"): ["txt", "png"]}})
 
         # Note that we have only one run_in_parallel() call
         self.assertEqual(
@@ -470,9 +500,15 @@
             return '{"add": [], "remove-lines": [{"test": "userscripts/first-test.html", "builder": "MOCK Mac10.11"}]}\n'
         self.tool.executive.run_command = mock_run_command
 
-    def test_rebaseline_updates_expectations_file(self):
-        options = MockOptions(optimize=False, verbose=True, results_directory=None)
+    @staticmethod
+    def options():
+        return optparse.Values({
+            'optimize': False,
+            'verbose': True,
+            'results_directory': None
+        })
 
+    def test_rebaseline_updates_expectations_file(self):
         self._write(
             self.mac_expectations_path,
             ("Bug(x) [ Mac ] userscripts/first-test.html [ Failure ]\n"
@@ -480,7 +516,9 @@
         self._write("userscripts/first-test.html", "Dummy test contents")
         self._setup_mock_build_data()
 
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
+        self.command._rebaseline(
+            self.options(),
+            {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
 
         new_expectations = self._read(self.mac_expectations_path)
         self.assertMultiLineEqual(
@@ -489,13 +527,13 @@
              "bug(z) [ Linux ] userscripts/first-test.html [ Failure ]\n"))
 
     def test_rebaseline_updates_expectations_file_all_platforms(self):
-        options = MockOptions(optimize=False, verbose=True, results_directory=None)
-
         self._write(self.mac_expectations_path, "Bug(x) userscripts/first-test.html [ Failure ]\n")
         self._write("userscripts/first-test.html", "Dummy test contents")
         self._setup_mock_build_data()
 
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
+        self.command._rebaseline(
+            self.options(),
+            {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
 
         new_expectations = self._read(self.mac_expectations_path)
         self.assertMultiLineEqual(
@@ -505,14 +543,14 @@
         # This test is just like test_rebaseline_updates_expectations_file_all_platforms(),
         # except that if a particular port happens to SKIP a test in an overrides file,
         # we count that as passing, and do not think that we still need to rebaseline it.
-        options = MockOptions(optimize=False, verbose=True, results_directory=None)
-
         self._write(self.mac_expectations_path, "Bug(x) userscripts/first-test.html [ Failure ]\n")
         self._write("NeverFixTests", "Bug(y) [ Android ] userscripts [ WontFix ]\n")
         self._write("userscripts/first-test.html", "Dummy test contents")
         self._setup_mock_build_data()
 
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
+        self.command._rebaseline(
+            self.options(),
+            {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
 
         new_expectations = self._read(self.mac_expectations_path)
         self.assertMultiLineEqual(
@@ -524,15 +562,15 @@
         # the Skip line should be left unmodified. Note that the first line is now
         # qualified as "[Linux Mac Win]"; if it was unqualified, it would conflict with
         # the second line.
-        options = MockOptions(optimize=False, verbose=True, results_directory=None)
-
         self._write(self.mac_expectations_path,
                     ("Bug(x) [ Linux Mac Win ] userscripts/first-test.html [ Failure ]\n"
                      "Bug(y) [ Android ] userscripts/first-test.html [ Skip ]\n"))
         self._write("userscripts/first-test.html", "Dummy test contents")
         self._setup_mock_build_data()
 
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
+        self.command._rebaseline(
+            self.options(),
+            {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
 
         new_expectations = self._read(self.mac_expectations_path)
         self.assertMultiLineEqual(
@@ -545,14 +583,14 @@
         # a test not being in the SmokeTests file, instead of using overrides files.
         # If a test is not part of the smoke tests, we count that as passing on ports that only
         # run smoke tests, and do not think that we still need to rebaseline it.
-        options = MockOptions(optimize=False, verbose=True, results_directory=None)
-
         self._write(self.mac_expectations_path, "Bug(x) userscripts/first-test.html [ Failure ]\n")
         self._write("SmokeTests", "fast/html/article-element.html")
         self._write("userscripts/first-test.html", "Dummy test contents")
         self._setup_mock_build_data()
 
-        self.command._rebaseline(options, {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
+        self.command._rebaseline(
+            self.options(),
+            {"userscripts/first-test.html": {Build("MOCK Mac10.11"): ["txt", "png"]}})
 
         new_expectations = self._read(self.mac_expectations_path)
         self.assertMultiLineEqual(
@@ -571,9 +609,14 @@
 
         self._zero_out_test_expectations()
         self._setup_mock_build_data()
-
-        self.command.execute(MockOptions(results_directory=False, optimize=False, builders=None,
-                                         suffixes="txt,png", verbose=True), ['userscripts/first-test.html'], self.tool)
+        options = optparse.Values({
+            'results_directory': False,
+            'optimize': False,
+            'builders': None,
+            'suffixes': "txt,png",
+            'verbose': True
+        })
+        self.command.execute(options, ['userscripts/first-test.html'], self.tool)
 
         self.assertEqual(
             self.tool.executive.calls,
@@ -591,9 +634,14 @@
         self._write("userscripts/second-test.html", "test data")
 
         self._setup_mock_build_data()
-
-        self.command.execute(MockOptions(results_directory=False, optimize=False, builders=None,
-                                         suffixes="txt,png", verbose=True), ['userscripts'], self.tool)
+        options = optparse.Values({
+            'results_directory': False,
+            'optimize': False,
+            'builders': None,
+            'suffixes': "txt,png",
+            'verbose': True
+        })
+        self.command.execute(options, ['userscripts'], self.tool)
 
         self.assertEqual(
             self.tool.executive.calls,
@@ -619,8 +667,17 @@
 
     def setUp(self):
         super(TestRebaselineExpectations, self).setUp()
-        self.options = MockOptions(optimize=False, builders=None, suffixes=['txt'],
-                                   verbose=False, platform=None, results_directory=None)
+
+    @staticmethod
+    def options():
+        return optparse.Values({
+            'optimize': False,
+            'builders': None,
+            'suffixes': ['txt'],
+            'verbose': False,
+            'platform': None,
+            'results_directory': None
+        })
 
     def _write_test_file(self, port, path, contents):
         abs_path = self.tool.filesystem.join(port.layout_tests_dir(), path)
@@ -655,7 +712,7 @@
             'userscripts/not-actually-failing.html': set(['txt', 'png', 'wav']),
         }
 
-        self.command.execute(self.options, [], self.tool)
+        self.command.execute(self.options(), [], self.tool)
 
         self.assertEqual(self.tool.executive.calls, [
             [
@@ -714,7 +771,7 @@
             'userscripts/reftest-image-text.html': set(['png', 'txt']),
         }
 
-        self.command.execute(self.options, [], self.tool)
+        self.command.execute(self.options(), [], self.tool)
 
         self.assertEqual(self.tool.executive.calls, [
             [
@@ -737,7 +794,7 @@
         oc = OutputCapture()
         try:
             oc.capture_output()
-            self.command.execute(self.options, [], self.tool)
+            self.command.execute(self.options(), [], self.tool)
         finally:
             _, _, logs = oc.restore_output()
             self.assertEqual(self.tool.filesystem.written_files, {})
@@ -797,7 +854,7 @@
             "MOCK Mac10.11": {"port_name": "test-mac-mac10.11", "specifiers": ["Mac10.11", "Release"]},
         })
 
-        self.command.execute(self.options, [], self.tool)
+        self.command.execute(self.options(), [], self.tool)
         self.assertEqual(self.tool.executive.calls, [])
 
         # The mac ports should both be removed since they're the only ones in the builder list.
@@ -844,7 +901,7 @@
             'fast/dom/missing-image.html': set(['txt', 'png']),
         }
 
-        self.command.execute(self.options, [], self.tool)
+        self.command.execute(self.options(), [], self.tool)
 
         self.assertEqual(self.tool.executive.calls, [
             [
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/mock_tool.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/mock_tool.py
index 97aac7f..2229b5c 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/mock_tool.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/mock_tool.py
@@ -26,19 +26,9 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-import optparse
-
 from webkitpy.common.host_mock import MockHost
 
 
-# TODO(qyearsley): Replace uses of this with using optparse.Values directly (crbug.com/626679).
-class MockOptions(optparse.Values):
-
-    def __init__(self, **kwargs):
-        # Not using super because optparse.Values is an old-style class.
-        optparse.Values.__init__(self, defaults=kwargs)
-
-
 class MockWebKitPatch(MockHost):
 
     def __init__(self, *args, **kwargs):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py
index 7ef3d60..4a8641df 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py
@@ -288,10 +288,8 @@
             webkit-patch rebaseline-from-try-jobs.
         """
         finder = WebKitFinder(self._host.filesystem)
-        tests = self._host.executive.run_command(['git', 'diff', 'master', '--name-only'])
-        for test in tests.splitlines():
-            if self.is_js_test(finder, test):
-                tests_to_rebaseline, tests_results = self.get_tests_to_rebaseline(finder, test, tests_results)
+        tests = self._host.executive.run_command(['git', 'diff', 'master', '--name-only']).splitlines()
+        tests_to_rebaseline, tests_results = self.get_tests_to_rebaseline(finder, tests, tests_results)
         if tests_to_rebaseline:
             webkit_patch = self._host.filesystem.join(finder.chromium_base(), finder.webkit_base(),
                                                       finder.path_to_script('webkit-patch'))
@@ -299,14 +297,32 @@
                                               'rebaseline-from-try-jobs', '-v'] + tests_to_rebaseline)
         return tests_results
 
-    def get_tests_to_rebaseline(self, webkit_finder, test_name, tests_results):
+    def get_tests_to_rebaseline(self, webkit_finder, tests, tests_results):
+        """Gets test to rebaseline.
+
+        Creates a list of tests to rebaseline depending on the tests' platform specific
+        results. This function also removes the platform key form the tests_results
+        dictionary if 'actual' results not in ['CRASH', 'TIMEOUT'].
+
+        Args:
+            webkit_finder: A WebKitFinder object.
+            tests: A list of new imported tests.
+            tests_results: A dictionary of failing tests results.
+
+        Returns:
+            A set of tests to be rebaselined. These tests are both
+            js tests and test that failed during the try jobs. Also
+            returns an updated tests_results dictionary.
+        """
         tests_to_rebaseline = set()
-        layout_tests_relative_path = self._host.filesystem.relpath(webkit_finder.layout_tests_dir(), webkit_finder.chromium_base())
-        test_path = self._host.filesystem.relpath(test_name, layout_tests_relative_path)
-        for platform in tests_results[test_path].keys():
-            if tests_results[test_path][platform]['actual'] not in ['CRASH', 'TIMEOUT']:
-                del tests_results[test_path][platform]
-                tests_to_rebaseline.add(test_path)
+        layout_tests_rel_path = self._host.filesystem.relpath(webkit_finder.layout_tests_dir(), webkit_finder.chromium_base())
+        for test in tests:
+            test_path = self._host.filesystem.relpath(test, layout_tests_rel_path)
+            if self.is_js_test(webkit_finder, test) and tests_results.get(test_path):
+                for platform in tests_results[test_path].keys():
+                    if tests_results[test_path][platform]['actual'] not in ['CRASH', 'TIMEOUT']:
+                        del tests_results[test_path][platform]
+                        tests_to_rebaseline.add(test_path)
         return list(tests_to_rebaseline), tests_results
 
     def is_js_test(self, webkit_finder, test_path):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
index e84b045..afbc451 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations_unittest.py
@@ -140,11 +140,13 @@
 
     def test_get_test_to_rebaseline(self):
         self.host = MockHost()
+        self.host.filesystem.files['/mock-checkout/imported/fake/test/path.html'] = '''
+                <script src="/resources/testharness.js"></script>'''
         finder = WebKitFinder(self.host.filesystem)
         line_adder = W3CExpectationsLineAdder(self.host)
-        test_name = 'imported/fake/test/path.html'
+        tests = ['imported/fake/test/path.html']
         test_dict = {'../../../imported/fake/test/path.html': self.mock_dict_two['imported/fake/test/path.html']}
         tests_to_rebaseline, tests_results = line_adder.get_tests_to_rebaseline(
-            finder, test_name, test_dict)
+            finder, tests, test_dict)
         self.assertEqual(tests_to_rebaseline, ['../../../imported/fake/test/path.html'])
         self.assertEqual(tests_results, test_dict)
diff --git a/third_party/opus/README.chromium b/third_party/opus/README.chromium
index a69a13e..9ae8035 100644
--- a/third_party/opus/README.chromium
+++ b/third_party/opus/README.chromium
@@ -14,3 +14,5 @@
 Local changes:
 * copy .gitignore from https://git.xiph.org/?p=opus.git;a=tree
 * set 'x' flags: "chmod 750 win32/genversion.bat"
+* Apply patch from
+  https://git.xiph.org/?p=opus.git;a=commit;h=79e8f527b0344b0897a65be35e77f7885bd99409
diff --git a/third_party/opus/src/silk/NLSF_stabilize.c b/third_party/opus/src/silk/NLSF_stabilize.c
index 1fa1ea3..8f3426b 100644
--- a/third_party/opus/src/silk/NLSF_stabilize.c
+++ b/third_party/opus/src/silk/NLSF_stabilize.c
@@ -130,7 +130,7 @@
 
         /* Keep delta_min distance between the NLSFs */
         for( i = 1; i < L; i++ )
-            NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
+            NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], silk_ADD_SAT16( NLSF_Q15[i-1], NDeltaMin_Q15[i] ) );
 
         /* Last NLSF should be no higher than 1 - NDeltaMin[L] */
         NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 989078f..9c8e72ecc 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -698,8 +698,11 @@
       'Windows Dev': 'swarming_gn_debug_bot_minimal_symbols_x64',
     },
 
+    'official.android': {
+      'blimp-engine': '//build/args/bots/official.android/blimp-engine.gn',
+    },
+
     'official.desktop': {
-      'blimp-engine': '//build/args/bots/official.desktop/blimp-engine.gn',
       'mac64': 'gn_official',
       'precise64': 'gn_official',
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 45228a6..5b9a378 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -93278,6 +93278,7 @@
   <int value="2" label="FailedWritingRulesetData"/>
   <int value="3" label="FailedWritingLicense"/>
   <int value="4" label="FailedReplaceFile"/>
+  <int value="5" label="FailedDeletePreexisting"/>
 </enum>
 
 <enum name="SuggestAppsDialogCloseReason" type="int">
@@ -96823,6 +96824,10 @@
       label="A VideoCapture GPU command buffer context"/>
   <suffix name="WebGL" label="A WebGL GPU command buffer context"/>
   <suffix name="Media" label="The media worker command buffer context"/>
+  <suffix name="BlimpRenderCompositor"
+      label="BlimpCompositor compositor command buffer context"/>
+  <suffix name="BlimpRenderWorker"
+      label="BlimpCompositor worker command buffer context"/>
   <affected-histogram name="GPU.ContextLost"/>
 </histogram_suffixes>
 
diff --git a/tools/perf/page_sets/data/system_health_desktop.json b/tools/perf/page_sets/data/system_health_desktop.json
index 9753e23..9600ad1a 100644
--- a/tools/perf/page_sets/data/system_health_desktop.json
+++ b/tools/perf/page_sets/data/system_health_desktop.json
@@ -88,7 +88,14 @@
         "system_health_desktop_022.wpr": [
             "load:search:google",
             "search:portal:google"
+        ],
+        "system_health_desktop_025.wpr": [
+            "browse:media:imgur",
+            "load:media:imgur"
+        ],
+        "system_health_desktop_026.wpr": [
+            "browse:media:youtube"
         ]
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating."
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/data/system_health_desktop_024.wpr.sha1 b/tools/perf/page_sets/data/system_health_desktop_024.wpr.sha1
new file mode 100644
index 0000000..7c1827db
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_desktop_024.wpr.sha1
@@ -0,0 +1 @@
+3412e01ad24e427a2a75bc18b29417b07956903b
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_025.wpr.sha1 b/tools/perf/page_sets/data/system_health_desktop_025.wpr.sha1
new file mode 100644
index 0000000..f3e2e3b
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_desktop_025.wpr.sha1
@@ -0,0 +1 @@
+f052e7e4d9b3bf866de7fb9d81b669a07eea8fb6
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_026.wpr.sha1 b/tools/perf/page_sets/data/system_health_desktop_026.wpr.sha1
new file mode 100644
index 0000000..802c0b3
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_desktop_026.wpr.sha1
@@ -0,0 +1 @@
+dc405dc9723b371a88b8fe1e6c338ca6913560b9
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile.json b/tools/perf/page_sets/data/system_health_mobile.json
index 2782af2..58e2899 100644
--- a/tools/perf/page_sets/data/system_health_mobile.json
+++ b/tools/perf/page_sets/data/system_health_mobile.json
@@ -97,7 +97,17 @@
         "system_health_mobile_029.wpr": [
             "load:search:google",
             "search:portal:google"
+        ],
+        "system_health_mobile_035.wpr": [
+            "browse:media:imgur",
+            "load:media:imgur"
+        ],
+        "system_health_mobile_037.wpr": [
+            "browse:media:youtube"
+        ],
+        "system_health_mobile_040.wpr": [
+            "browse:media:facebook"
         ]
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating."
-}
\ No newline at end of file
+}
diff --git a/tools/perf/page_sets/data/system_health_mobile_034.wpr.sha1 b/tools/perf/page_sets/data/system_health_mobile_034.wpr.sha1
new file mode 100644
index 0000000..98b2d78d
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_034.wpr.sha1
@@ -0,0 +1 @@
+1cc6403ac720816834e20529d9191b66d02bd657
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile_035.wpr.sha1 b/tools/perf/page_sets/data/system_health_mobile_035.wpr.sha1
new file mode 100644
index 0000000..dfc265d
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_035.wpr.sha1
@@ -0,0 +1 @@
+293825494ec5b2e5822373159de7cf89c2b2a5fe
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile_037.wpr.sha1 b/tools/perf/page_sets/data/system_health_mobile_037.wpr.sha1
new file mode 100644
index 0000000..19a26846
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_037.wpr.sha1
@@ -0,0 +1 @@
+ef4693e680826a9c4a57031b946eff9fed1f5e49
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile_038.wpr.sha1 b/tools/perf/page_sets/data/system_health_mobile_038.wpr.sha1
new file mode 100644
index 0000000..f6ecbbf
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_038.wpr.sha1
@@ -0,0 +1 @@
+4c9a09160fad659f836392c246b7de7376bdff41
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile_040.wpr.sha1 b/tools/perf/page_sets/data/system_health_mobile_040.wpr.sha1
new file mode 100644
index 0000000..154f1b6
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_mobile_040.wpr.sha1
@@ -0,0 +1 @@
+0629fa451c90fc06bce47ee89a94a5fa6a4d308b
\ No newline at end of file
diff --git a/tools/perf/page_sets/login_helpers/facebook_login.py b/tools/perf/page_sets/login_helpers/facebook_login.py
index 360cf28..a07ddff 100644
--- a/tools/perf/page_sets/login_helpers/facebook_login.py
+++ b/tools/perf/page_sets/login_helpers/facebook_login.py
@@ -33,3 +33,11 @@
   action_runner.WaitForElement(text='OK')
   action_runner.ClickElement(text='OK')
   action_runner.WaitForNavigate()
+
+
+def LoginWithDesktopSite(
+    action_runner, credential,
+    credentials_path=login_utils.DEFAULT_CREDENTIAL_PATH):
+  # Currently we use the mobile login page also on Desktop because the
+  # Desktop version requires enabled cookies and rejects the login.
+  return LoginWithMobileSite(action_runner, credential, credentials_path)
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index dbc22bc74..25bf5b8 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -16,7 +16,6 @@
 
   IS_SINGLE_PAGE_APP = False
   ITEM_SELECTOR = NotImplemented
-  ITEMS_TO_VISIT = 4
   ABSTRACT_STORY = True
 
   def _WaitForNavigation(self, action_runner):
@@ -38,6 +37,11 @@
     self._WaitForNavigation(action_runner)
 
 
+##############################################################################
+# News browsing stories.
+##############################################################################
+
+
 class _NewsBrowsingStory(_BrowsingStory):
   """Abstract base class for news user stories.
 
@@ -52,6 +56,7 @@
 
   ITEM_READ_TIME_IN_SECONDS = 3
   ITEM_SCROLL_REPEAT = 2
+  ITEMS_TO_VISIT = 4
   MAIN_PAGE_SCROLL_REPEAT = 0
   ABSTRACT_STORY = True
 
@@ -74,11 +79,6 @@
         repeat_count=self.MAIN_PAGE_SCROLL_REPEAT)
 
 
-##############################################################################
-# News browsing stories.
-##############################################################################
-
-
 class CnnStory(_NewsBrowsingStory):
   """The second top website in http://www.alexa.com/topsites/category/News"""
   NAME = 'browse:news:cnn'
@@ -212,3 +212,98 @@
     if has_button:
       action_runner.ClickElement(selector=self._CLOSE_BUTTON_SELECTOR)
     super(WashingtonPostMobileStory, self)._DidLoadDocument(action_runner)
+
+
+##############################################################################
+# Media browsing stories.
+##############################################################################
+
+
+class _MediaBrowsingStory(_BrowsingStory):
+  """Abstract base class for media user stories
+
+  A media story imitates browsing a website with photo or video content:
+  1. Load a page showing a media item
+  2. Click on the next link to go to the next media item
+  3. etc.
+  """
+
+  ABSTRACT_STORY = True
+  ITEM_VIEW_TIME_IN_SECONDS = 3
+  ITEMS_TO_VISIT = 15
+  ITEM_SELECTOR_INDEX = 0
+
+  def _DidLoadDocument(self, action_runner):
+    for _ in xrange(self.ITEMS_TO_VISIT):
+      self._NavigateToItem(action_runner, self.ITEM_SELECTOR_INDEX)
+      self._ViewMediaItem(action_runner)
+
+  def _ViewMediaItem(self, action_runner):
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
+    action_runner.Wait(self.ITEM_VIEW_TIME_IN_SECONDS)
+
+
+class ImgurMobileStory(_MediaBrowsingStory):
+  NAME = 'browse:media:imgur'
+  URL = 'http://imgur.com/gallery/5UlBN'
+  ITEM_SELECTOR = '.Navbar-customAction'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  IS_SINGLE_PAGE_APP = True
+
+
+class ImgurDesktopStory(_MediaBrowsingStory):
+  NAME = 'browse:media:imgur'
+  URL = 'http://imgur.com/gallery/5UlBN'
+  ITEM_SELECTOR = '.navNext'
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  IS_SINGLE_PAGE_APP = True
+
+
+class YouTubeMobileStory(_MediaBrowsingStory):
+  NAME = 'browse:media:youtube'
+  URL = 'https://m.youtube.com/watch?v=QGfhS1hfTWw&autoplay=false'
+  ITEM_SELECTOR = '._mhgb > a'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  IS_SINGLE_PAGE_APP = True
+  ITEM_SELECTOR_INDEX = 3
+
+
+class YouTubeDesktopStory(_MediaBrowsingStory):
+  NAME = 'browse:media:youtube'
+  URL = 'https://www.youtube.com/watch?v=QGfhS1hfTWw&autoplay=false'
+  ITEM_SELECTOR = '.yt-uix-simple-thumb-related'
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+  IS_SINGLE_PAGE_APP = True
+  # A longer view time allows videos to load and play.
+  ITEM_VIEW_TIME_IN_SECONDS = 5
+  ITEMS_TO_VISIT = 8
+  ITEM_SELECTOR_INDEX = 3
+
+
+class FacebookMobileStory(_MediaBrowsingStory):
+  NAME = 'browse:media:facebook'
+  URL = (
+      'https://m.facebook.com/rihanna/photos/a.207477806675.138795.10092511675/10153911739606676/?type=3&source=54&ref=page_internal')
+  ITEM_SELECTOR = '._57-r.touchable'
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+  IS_SINGLE_PAGE_APP = True
+  ITEM_SELECTOR_INDEX = 0
+
+  def _Login(self, action_runner):
+    action_runner.Navigate('https://m.facebook.com/rihanna')
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
+
+
+class FacebookDesktopStory(_MediaBrowsingStory):
+  NAME = 'browse:media:facebook'
+  URL = (
+      'https://www.facebook.com/rihanna/photos/a.207477806675.138795.10092511675/10153911739606676/?type=3&theater')
+  ITEM_SELECTOR = '.snowliftPager.next'
+  # Recording currently does not work. The page gets stuck in the
+  # theater viewer.
+  SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS
+  IS_SINGLE_PAGE_APP = True
+
+  def _Login(self, action_runner):
+    action_runner.Navigate('https://www.facebook.com/rihanna')
+    action_runner.tab.WaitForDocumentReadyStateToBeComplete()
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py
index 65e23e4..90b2dabf 100644
--- a/tools/perf/page_sets/system_health/loading_stories.py
+++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -197,7 +197,7 @@
 
 
 ################################################################################
-# Audio and video.
+# Audio, images, and video.
 ################################################################################
 
 
@@ -244,6 +244,11 @@
                 !== null''')
 
 
+class LoadImgur(_LoadingStory):
+  NAME = 'load:media:imgur'
+  URL = 'http://imgur.com/gallery/5UlBN'
+
+
 ################################################################################
 # Online tools (documents, emails, storage, ...).
 ################################################################################
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 33d4b24d..523ea7c8 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -11,6 +11,8 @@
   output_name = "ui_android"
   sources = [
     "animation_utils.h",
+    "context_provider_factory.cc",
+    "context_provider_factory.h",
     "edge_effect.cc",
     "edge_effect.h",
     "edge_effect_base.cc",
diff --git a/ui/android/DEPS b/ui/android/DEPS
index b288370..5522ce5 100644
--- a/ui/android/DEPS
+++ b/ui/android/DEPS
@@ -3,6 +3,9 @@
   "+cc/layers/layer.h",
   "+cc/layers/ui_resource_layer.h",
   "+cc/output/copy_output_request.h",
+  "+cc/output/context_provider.h",
+  "+cc/output/vulkan_context_provider.h",
+  "+cc/output/vulkan_in_process_context_provider.h",
   "+cc/resources/scoped_ui_resource.h",
   "+cc/resources/ui_resource_client.h",
   "+cc/resources/ui_resource_bitmap.h",
diff --git a/ui/android/context_provider_factory.cc b/ui/android/context_provider_factory.cc
new file mode 100644
index 0000000..0f1981c
--- /dev/null
+++ b/ui/android/context_provider_factory.cc
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/android/context_provider_factory.h"
+
+#include "cc/output/context_provider.h"
+
+namespace ui {
+namespace {
+
+ContextProviderFactory* g_context_provider_factory = nullptr;
+
+}  // namespace
+
+// static
+ContextProviderFactory* ContextProviderFactory::GetInstance() {
+  return g_context_provider_factory;
+}
+
+// static
+void ContextProviderFactory::SetInstance(
+    ContextProviderFactory* context_provider_factory) {
+  DCHECK(!g_context_provider_factory || !context_provider_factory);
+
+  g_context_provider_factory = context_provider_factory;
+}
+
+}  // namespace ui
diff --git a/ui/android/context_provider_factory.h b/ui/android/context_provider_factory.h
new file mode 100644
index 0000000..8ad9d6f
--- /dev/null
+++ b/ui/android/context_provider_factory.h
@@ -0,0 +1,77 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_ANDROID_CONTEXT_PROVIDER_FACTORY_H_
+#define UI_ANDROID_CONTEXT_PROVIDER_FACTORY_H_
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "ui/android/ui_android_export.h"
+
+namespace cc {
+class ContextProvider;
+class GpuMemoryBufferManager;
+class VulkanContextProvider;
+class SharedBitmapManager;
+class SurfaceManager;
+}
+
+namespace gpu {
+namespace gles2 {
+struct ContextCreationAttribHelper;
+}  // namespace gles
+
+struct SharedMemoryLimits;
+class GpuMemoryBufferManager;
+}  // namespace gpu
+
+namespace ui {
+
+// This class is not thread-safe and should only be accessed from the UI thread.
+class UI_ANDROID_EXPORT ContextProviderFactory {
+ public:
+  using ContextProviderCallback =
+      base::Callback<void(const scoped_refptr<cc::ContextProvider>&)>;
+
+  enum class ContextType {
+    BLIMP_RENDER_COMPOSITOR_CONTEXT,
+    BLIMP_RENDER_WORKER_CONTEXT,
+  };
+
+  static ContextProviderFactory* GetInstance();
+
+  // This should only be called once, on startup. Ownership remains with the
+  // caller.
+  static void SetInstance(ContextProviderFactory* context_provider_factory);
+
+  virtual ~ContextProviderFactory(){};
+
+  virtual scoped_refptr<cc::VulkanContextProvider>
+  GetSharedVulkanContextProvider() = 0;
+
+  // Creates an offscreen ContextProvider for the compositor. Any shared
+  // contexts passed here *must* have been created using this factory.
+  // The callback may be triggered synchronously if possible, and will always
+  // have the context provider.
+  virtual void CreateOffscreenContextProvider(
+      ContextType context_type,
+      gpu::SharedMemoryLimits shared_memory_limits,
+      gpu::gles2::ContextCreationAttribHelper attributes,
+      bool support_locking,
+      bool automatic_flushes,
+      cc::ContextProvider* shared_context_provider,
+      ContextProviderCallback result_callback) = 0;
+
+  virtual cc::SurfaceManager* GetSurfaceManager() = 0;
+
+  virtual uint32_t AllocateSurfaceClientId() = 0;
+
+  virtual cc::SharedBitmapManager* GetSharedBitmapManager() = 0;
+
+  virtual gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() = 0;
+};
+
+}  // namespace ui
+
+#endif  // UI_ANDROID_CONTEXT_PROVIDER_FACTORY_H_
diff --git a/ui/app_list/views/search_result_actions_view.cc b/ui/app_list/views/search_result_actions_view.cc
index 7b73b9c..90a6a50 100644
--- a/ui/app_list/views/search_result_actions_view.cc
+++ b/ui/app_list/views/search_result_actions_view.cc
@@ -12,8 +12,8 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/views/border.h"
-#include "ui/views/controls/button/blue_button.h"
 #include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/layout/box_layout.h"
 
 namespace app_list {
@@ -79,11 +79,10 @@
 
 void SearchResultActionsView::CreateBlueButton(
     const SearchResult::Action& action) {
-  views::BlueButton* button = new views::BlueButton(this, action.label_text);
-  button->SetAccessibleName(action.label_text);
+  views::MdTextButton* button =
+      views::MdTextButton::CreateMdButton(this, action.label_text);
+  button->SetCallToAction(true);
   button->SetTooltipText(action.tooltip_text);
-  button->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList(
-      ui::ResourceBundle::SmallBoldFont));
   button->SetFocusBehavior(FocusBehavior::NEVER);
   AddChildView(button);
 }
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index 940b6a9..68f9d25 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -629,14 +629,12 @@
 
 const gfx::FontList& ResourceBundle::GetFontList(FontStyle legacy_style) {
   gfx::Font::Weight font_weight = gfx::Font::Weight::NORMAL;
-  if (legacy_style == BoldFont || legacy_style == SmallBoldFont ||
-      legacy_style == MediumBoldFont || legacy_style == LargeBoldFont)
+  if (legacy_style == BoldFont || legacy_style == MediumBoldFont)
     font_weight = gfx::Font::Weight::BOLD;
 
   int size_delta = 0;
   switch (legacy_style) {
     case SmallFont:
-    case SmallBoldFont:
       size_delta = kSmallFontDelta;
       break;
     case MediumFont:
@@ -644,7 +642,6 @@
       size_delta = kMediumFontDelta;
       break;
     case LargeFont:
-    case LargeBoldFont:
       size_delta = kLargeFontDelta;
       break;
     case BaseFont:
diff --git a/ui/base/resource/resource_bundle.h b/ui/base/resource/resource_bundle.h
index dea3b8f3..1547166 100644
--- a/ui/base/resource/resource_bundle.h
+++ b/ui/base/resource/resource_bundle.h
@@ -56,13 +56,11 @@
   // client code providing their own constant with the desired font size delta.
   enum FontStyle {
     SmallFont,
-    SmallBoldFont,
     BaseFont,
     BoldFont,
     MediumFont,
     MediumBoldFont,
     LargeFont,
-    LargeBoldFont,
   };
 
   enum LoadResources {
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index 0164f68..39e7d2ca 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -490,6 +490,11 @@
   width: 28px;
 }
 
+html[dir='rtl'] .dialog-header button.icon-button > files-toggle-ripple {
+  left: auto;
+  right: 2px;
+}
+
 .dialog-header button.icon-button > .icon {
   background-position: center;
   background-repeat: no-repeat;
diff --git a/ui/file_manager/gallery/css/gallery.css b/ui/file_manager/gallery/css/gallery.css
index 7359948..f26d53b 100644
--- a/ui/file_manager/gallery/css/gallery.css
+++ b/ui/file_manager/gallery/css/gallery.css
@@ -40,6 +40,12 @@
   width: 17px;
 }
 
+html[dir='rtl'] .bubble .pointer {
+  margin: 0 -5px 0 0;
+  left: auto;
+  right: 24px;
+}
+
 .bubble .pointer:not(.bottom) {
   top: -11px;
 }
@@ -61,6 +67,11 @@
   width: 21px;
 }
 
+html[dir='rtl'] .bubble .close-x {
+  right: auto;
+  left: 3px;
+}
+
 .bubble .close-x:hover {
   opacity: 0.7;
 }
@@ -360,6 +371,11 @@
   width: 220px;
 }
 
+html[dir='rtl'] .gallery .toolbar .bubble {
+  left: auto;
+  right: 20px;
+}
+
 .gallery:not([editing]) .toolbar .bubble {
   display: none;
 }
diff --git a/ui/gfx/font_unittest.cc b/ui/gfx/font_unittest.cc
index b93589ddd..a5ac5088 100644
--- a/ui/gfx/font_unittest.cc
+++ b/ui/gfx/font_unittest.cc
@@ -158,6 +158,19 @@
             base::ToLowerASCII(fallback_font.GetActualFontNameForTesting()));
 }
 
+TEST_F(FontTest, DeriveFont) {
+  Font cf("Arial", 8);
+  const int kSizeDelta = 2;
+  Font cf_underlined =
+      cf.Derive(0, cf.GetStyle() | gfx::Font::UNDERLINE, cf.GetWeight());
+  Font cf_underlined_resized = cf_underlined.Derive(
+      kSizeDelta, cf_underlined.GetStyle(), cf_underlined.GetWeight());
+  EXPECT_EQ(cf.GetStyle() | gfx::Font::UNDERLINE,
+            cf_underlined_resized.GetStyle());
+  EXPECT_EQ(cf.GetFontSize() + kSizeDelta, cf_underlined_resized.GetFontSize());
+  EXPECT_EQ(cf.GetWeight(), cf_underlined_resized.GetWeight());
+}
+
 #if defined(OS_WIN)
 TEST_F(FontTest, DeriveResizesIfSizeTooSmall) {
   Font cf("Arial", 8);
diff --git a/ui/gfx/geometry/cubic_bezier.cc b/ui/gfx/geometry/cubic_bezier.cc
index 06b6edd..f438c9e 100644
--- a/ui/gfx/geometry/cubic_bezier.cc
+++ b/ui/gfx/geometry/cubic_bezier.cc
@@ -71,6 +71,10 @@
     end_gradient_ = 0;
 }
 
+// This works by taking taking the derivative of the cubic bezier, on the y
+// axis. We can then solve for where the derivative is zero to find the min
+// and max distance along the line. We the have to solve those in terms of time
+// rather than distance on the x-axis
 void CubicBezier::InitRange(double p1y, double p2y) {
   range_min_ = 0;
   range_max_ = 1;
@@ -112,6 +116,12 @@
   double sol1 = 0;
   double sol2 = 0;
 
+  // If the solution is in the range [0,1] then we include it, otherwise we
+  // ignore it.
+
+  // An interesting fact about these beziers is that they are only
+  // actually evaluated in [0,1]. After that we take the tangent at that point
+  // and linearly project it out.
   if (0 < t1 && t1 < 1)
     sol1 = SampleCurveY(t1);
 
diff --git a/ui/gfx/platform_font_mac.h b/ui/gfx/platform_font_mac.h
index 63a0cbd2..12c9f5a 100644
--- a/ui/gfx/platform_font_mac.h
+++ b/ui/gfx/platform_font_mac.h
@@ -41,6 +41,13 @@
                   int font_size,
                   int font_style,
                   Font::Weight font_weight);
+
+  PlatformFontMac(NativeFont font,
+                  const std::string& font_name,
+                  int font_size,
+                  int font_style,
+                  Font::Weight font_weight);
+
   ~PlatformFontMac() override;
 
   // Calculates and caches the font metrics and inits |render_params_|.
@@ -54,10 +61,10 @@
 
   // The name/size/style trio that specify the font. Initialized in the
   // constructors.
-  std::string font_name_;  // Corresponds to -[NSFont fontFamily].
-  int font_size_;
-  int font_style_;
-  Font::Weight font_weight_;
+  const std::string font_name_;  // Corresponds to -[NSFont fontFamily].
+  const int font_size_;
+  const int font_style_;
+  const Font::Weight font_weight_;
 
   // Cached metrics, generated in CalculateMetrics().
   int height_;
diff --git a/ui/gfx/platform_font_mac.mm b/ui/gfx/platform_font_mac.mm
index 1df9e69..53781f8e 100644
--- a/ui/gfx/platform_font_mac.mm
+++ b/ui/gfx/platform_font_mac.mm
@@ -19,6 +19,22 @@
 
 namespace {
 
+// Returns the font style for |font|. Disregards Font::UNDERLINE, since NSFont
+// does not support it as a trait.
+int GetFontStyleFromNSFont(NSFont* font) {
+  int font_style = Font::NORMAL;
+  NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits];
+  if (traits & NSFontItalicTrait)
+    font_style |= Font::ITALIC;
+  return font_style;
+}
+
+// Returns the Font weight for |font|.
+Font::Weight GetFontWeightFromNSFont(NSFont* font) {
+  NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits];
+  return (traits & NSFontBoldTrait) ? Font::Weight::BOLD : Font::Weight::NORMAL;
+}
+
 // Returns an autoreleased NSFont created with the passed-in specifications.
 NSFont* NSFontWithSpec(const std::string& font_name,
                        int font_size,
@@ -64,31 +80,17 @@
 }
 
 PlatformFontMac::PlatformFontMac(NativeFont native_font)
-    : native_font_([native_font retain]),
-      font_name_(base::SysNSStringToUTF8([native_font_ familyName])),
-      font_size_([native_font_ pointSize]),
-      font_style_(Font::NORMAL),
-      font_weight_(Font::Weight::NORMAL) {
-  NSFontSymbolicTraits traits = [[native_font fontDescriptor] symbolicTraits];
-  if (traits & NSFontItalicTrait)
-    font_style_ |= Font::ITALIC;
-  if (traits & NSFontBoldTrait)
-    font_weight_ = Font::Weight::BOLD;
-
-  CalculateMetricsAndInitRenderParams();
-}
+    : PlatformFontMac(native_font,
+                      base::SysNSStringToUTF8([native_font familyName]),
+                      [native_font pointSize],
+                      GetFontStyleFromNSFont(native_font),
+                      GetFontWeightFromNSFont(native_font)) {}
 
 PlatformFontMac::PlatformFontMac(const std::string& font_name, int font_size)
-    : native_font_([NSFontWithSpec(font_name,
-                                   font_size,
-                                   Font::NORMAL,
-                                   Font::Weight::NORMAL) retain]),
-      font_name_(font_name),
-      font_size_(font_size),
-      font_style_(Font::NORMAL),
-      font_weight_(Font::Weight::NORMAL) {
-  CalculateMetricsAndInitRenderParams();
-}
+    : PlatformFontMac(font_name,
+                      font_size,
+                      Font::NORMAL,
+                      Font::Weight::NORMAL) {}
 
 ////////////////////////////////////////////////////////////////////////////////
 // PlatformFontMac, PlatformFont implementation:
@@ -96,16 +98,26 @@
 Font PlatformFontMac::DeriveFont(int size_delta,
                                  int style,
                                  Font::Weight weight) const {
-  if (native_font_ && style == font_style_ && weight == font_weight_) {
-    // System fonts have special attributes starting with 10.11. They should be
-    // requested using the same descriptor to preserve these attributes.
-    return Font(new PlatformFontMac([NSFont
-        fontWithDescriptor:[native_font_ fontDescriptor]
-                      size:font_size_ + size_delta]));
-  }
+  // For some reason, creating fonts using the NSFontDescriptor API's seem to be
+  // unreliable. Hence use the NSFontManager.
+  NSFont* derived_font = native_font_;
+  NSFontManager* font_manager = [NSFontManager sharedFontManager];
 
-  return Font(
-      new PlatformFontMac(font_name_, font_size_ + size_delta, style, weight));
+  NSFontTraitMask bold_trait_mask =
+      weight >= Font::Weight::BOLD ? NSBoldFontMask : NSUnboldFontMask;
+  derived_font =
+      [font_manager convertFont:derived_font toHaveTrait:bold_trait_mask];
+
+  NSFontTraitMask italic_trait_mask =
+      (style & Font::ITALIC) ? NSItalicFontMask : NSUnitalicFontMask;
+  derived_font =
+      [font_manager convertFont:derived_font toHaveTrait:italic_trait_mask];
+
+  derived_font =
+      [font_manager convertFont:derived_font toSize:font_size_ + size_delta];
+
+  return Font(new PlatformFontMac(derived_font, font_name_,
+                                  font_size_ + size_delta, style, weight));
 }
 
 int PlatformFontMac::GetHeight() {
@@ -159,9 +171,19 @@
                                  int font_size,
                                  int font_style,
                                  Font::Weight font_weight)
-    : native_font_(
-          [NSFontWithSpec(font_name, font_size, font_style, font_weight)
-              retain]),
+    : PlatformFontMac(
+          NSFontWithSpec(font_name, font_size, font_style, font_weight),
+          font_name,
+          font_size,
+          font_style,
+          font_weight) {}
+
+PlatformFontMac::PlatformFontMac(NativeFont font,
+                                 const std::string& font_name,
+                                 int font_size,
+                                 int font_style,
+                                 Font::Weight font_weight)
+    : native_font_([font retain]),
       font_name_(font_name),
       font_size_(font_size),
       font_style_(font_style),
diff --git a/ui/gfx/platform_font_mac_unittest.mm b/ui/gfx/platform_font_mac_unittest.mm
index 362bed4..e65b8b1f 100644
--- a/ui/gfx/platform_font_mac_unittest.mm
+++ b/ui/gfx/platform_font_mac_unittest.mm
@@ -36,6 +36,30 @@
             traits);
 }
 
+TEST(PlatformFontMacTest, DeriveFontUnderline) {
+  // Create a default font.
+  gfx::Font base_font;
+
+  // Make the font underlined.
+  gfx::Font derived_font(base_font.Derive(
+      0, base_font.GetStyle() | gfx::Font::UNDERLINE, base_font.GetWeight()));
+
+  // Validate the derived font properties against its native font instance.
+  NSFontTraitMask traits = [[NSFontManager sharedFontManager]
+      traitsOfFont:derived_font.GetNativeFont()];
+  gfx::Font::Weight actual_weight = (traits & NSFontBoldTrait)
+                                        ? gfx::Font::Weight::BOLD
+                                        : gfx::Font::Weight::NORMAL;
+
+  int actual_style = gfx::Font::UNDERLINE;
+  if (traits & NSFontItalicTrait)
+    actual_style |= gfx::Font::ITALIC;
+
+  EXPECT_TRUE(derived_font.GetStyle() & gfx::Font::UNDERLINE);
+  EXPECT_EQ(derived_font.GetStyle(), actual_style);
+  EXPECT_EQ(derived_font.GetWeight(), actual_weight);
+}
+
 TEST(PlatformFontMacTest, ConstructFromNativeFont) {
   gfx::Font normal_font([NSFont fontWithName:@"Helvetica" size:12]);
   EXPECT_EQ(12, normal_font.GetFontSize());
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn
index 609ad3b..111d07f 100644
--- a/ui/gl/BUILD.gn
+++ b/ui/gl/BUILD.gn
@@ -233,7 +233,7 @@
     ]
 
     if (is_official_build) {
-      include_dirs = [ "//third_party/swiftshader/include" ]
+      include_dirs += [ "//third_party/swiftshader/include" ]
     }
   }
   if (is_mac) {
diff --git a/ui/ozone/platform/drm/ozone_platform_gbm.cc b/ui/ozone/platform/drm/ozone_platform_gbm.cc
index fb276c4..e32d151 100644
--- a/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -17,8 +17,8 @@
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "services/shell/public/cpp/connection.h"
 #include "services/shell/public/cpp/interface_factory.h"
+#include "services/shell/public/cpp/interface_registry.h"
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
 #include "ui/events/ozone/device/device_manager.h"
 #include "ui/events/ozone/evdev/event_factory_evdev.h"
@@ -109,8 +109,8 @@
   std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
     return event_factory_ozone_->CreateSystemInputInjector();
   }
-  void AddInterfaces(shell::Connection* connection) override {
-    connection->AddInterface<ozone::mojom::DeviceCursor>(this);
+  void AddInterfaces(shell::InterfaceRegistry* registry) override {
+    registry->AddInterface<ozone::mojom::DeviceCursor>(this);
   }
   // shell::InterfaceFactory<mojom::ozone::Cursor> implementation.
   void Create(const shell::Identity& remote_identity,
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc
index 4242c988..45205ee9 100644
--- a/ui/ozone/public/ozone_platform.cc
+++ b/ui/ozone/public/ozone_platform.cc
@@ -98,6 +98,6 @@
   InitializeGPU();
 }
 
-void OzonePlatform::AddInterfaces(shell::Connection* connection) {}
+void OzonePlatform::AddInterfaces(shell::InterfaceRegistry* registry) {}
 
 }  // namespace ui
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index 5757660..d904618b 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -16,7 +16,7 @@
 
 namespace shell {
 class Connector;
-class Connection;
+class InterfaceRegistry;
 }
 
 namespace ui {
@@ -104,12 +104,13 @@
 
   // Ozone platform implementations may also choose to expose mojo interfaces to
   // internal functionality. Embedders wishing to take advantage of ozone mojo
-  // implementations must invoke AddInterfaces with a valid shell::Connection*
-  // pointer to export all Mojo interfaces defined within Ozone.
+  // implementations must invoke AddInterfaces with a valid
+  // shell::InterfaceRegistry* pointer to export all Mojo interfaces defined
+  // within Ozone.
   //
   // A default do-nothing implementation is provided to permit platform
   // implementations to opt out of implementing any Mojo interfaces.
-  virtual void AddInterfaces(shell::Connection* connection);
+  virtual void AddInterfaces(shell::InterfaceRegistry* registry);
 
  private:
   virtual void InitializeUI() = 0;
diff --git a/ui/views/controls/button/md_text_button.h b/ui/views/controls/button/md_text_button.h
index 5ada157..8d802c7 100644
--- a/ui/views/controls/button/md_text_button.h
+++ b/ui/views/controls/button/md_text_button.h
@@ -38,6 +38,7 @@
                                int thickness,
                                SkAlpha alpha);
 
+  // See |is_cta_|.
   void SetCallToAction(bool cta);
   void set_bg_color_override(SkColor color) { bg_color_override_ = color; }
 
diff --git a/ui/views/mus/window_manager_connection.h b/ui/views/mus/window_manager_connection.h
index 4cbdcda..71c894f 100644
--- a/ui/views/mus/window_manager_connection.h
+++ b/ui/views/mus/window_manager_connection.h
@@ -62,6 +62,7 @@
   static bool Exists();
 
   shell::Connector* connector() { return connector_; }
+  ui::GpuService* gpu_service() { return gpu_service_.get(); }
 
   ui::Window* NewWindow(
       const std::map<std::string, std::vector<uint8_t>>& properties);
diff --git a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
index 88ca0532..0229a7c 100644
--- a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
+++ b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
@@ -70,19 +70,6 @@
           timing: {
             duration: 150
           }
-        }, {
-          name: 'paper-menu-shrink-width-animation',
-          timing: {
-            delay: 100,
-            duration: 50,
-            easing: SLIDE_CUBIC_BEZIER
-          }
-        }, {
-          name: 'paper-menu-shrink-height-animation',
-          timing: {
-            delay: 200,
-            easing: 'ease-in'
-          }
         }];
       }
     }