diff --git a/DEPS b/DEPS
index dd8be78..1ea71c3c 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,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': 'e4ca362259a36458cce94a5e643a11306037e8d6',
+  'skia_revision': 'e7a364d435843a868dcac2c61d78c34e5d3e326c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -228,7 +228,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + 'a048ce1c9fcc0db50e10a33c463a71d19d29e275', # commit position 15954
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '076b7aeb987954ea3f6267be4a6cca6e32f99074', # commit position 16023
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/ash/aura/wm_shell_aura.cc b/ash/aura/wm_shell_aura.cc
index 1d99a96..1d27a92 100644
--- a/ash/aura/wm_shell_aura.cc
+++ b/ash/aura/wm_shell_aura.cc
@@ -318,6 +318,15 @@
   }
 }
 
+void WmShellAura::SessionStateChanged(session_manager::SessionState state) {
+  // Create the shelf if necessary.
+  WmShell::SessionStateChanged(state);
+
+  // Recreate the keyboard after initial login and after multiprofile login.
+  if (state == session_manager::SessionState::ACTIVE)
+    Shell::GetInstance()->CreateKeyboard();
+}
+
 void WmShellAura::OnDisplayConfigurationChanging() {
   for (auto& observer : display_observers_)
     observer.OnDisplayConfigurationChanging();
diff --git a/ash/aura/wm_shell_aura.h b/ash/aura/wm_shell_aura.h
index f05840b..e0093b73 100644
--- a/ash/aura/wm_shell_aura.h
+++ b/ash/aura/wm_shell_aura.h
@@ -95,6 +95,9 @@
   void OnAttemptToReactivateWindow(aura::Window* request_active,
                                    aura::Window* actual_active) override;
 
+  // SessionStateObserver:
+  void SessionStateChanged(session_manager::SessionState state) override;
+
   // WindowTreeHostManager::Observer:
   void OnDisplayConfigurationChanging() override;
   void OnDisplayConfigurationChanged() override;
diff --git a/ash/common/shelf/shelf_widget.cc b/ash/common/shelf/shelf_widget.cc
index e80b8bf..d735e58 100644
--- a/ash/common/shelf/shelf_widget.cc
+++ b/ash/common/shelf/shelf_widget.cc
@@ -331,6 +331,12 @@
   // Ensure the newly created |shelf_| gets current values.
   background_animator_.Initialize(this);
 
+  // TODO(jamescook): The IsActiveUserSessionStarted() check may not be needed
+  // because the shelf is only created after the first user session is active.
+  // The ShelfView seems to always be visible after login. At the lock screen
+  // the shelf is hidden because its container is hidden. During auto-hide it is
+  // hidden because ShelfWidget is transparent. Some of the ShelfView visibility
+  // code could be simplified. http://crbug.com/674773
   shelf_view_->SetVisible(
       WmShell::Get()->GetSessionStateDelegate()->IsActiveUserSessionStarted());
   shelf_layout_manager_->LayoutShelf();
@@ -342,11 +348,6 @@
   return shelf_view_ && shelf_view_->visible();
 }
 
-void ShelfWidget::SetShelfVisibility(bool visible) {
-  if (shelf_view_)
-    shelf_view_->SetVisible(visible);
-}
-
 bool ShelfWidget::IsShowingAppList() const {
   return GetAppListButton() && GetAppListButton()->is_showing_app_list();
 }
@@ -388,6 +389,9 @@
 }
 
 void ShelfWidget::UpdateIconPositionForPanel(WmWindow* panel) {
+  if (!shelf_view_)
+    return;
+
   WmWindow* shelf_window = WmLookup::Get()->GetWindowForWidget(this);
   shelf_view_->UpdatePanelIconPosition(
       panel->GetIntProperty(WmWindowProperty::SHELF_ID),
@@ -396,6 +400,11 @@
 }
 
 gfx::Rect ShelfWidget::GetScreenBoundsOfItemIconForWindow(WmWindow* window) {
+  // Window animations can be triggered during session restore before the shelf
+  // view is created. In that case, return default empty bounds.
+  if (!shelf_view_)
+    return gfx::Rect();
+
   ShelfID id = window->GetIntProperty(WmWindowProperty::SHELF_ID);
   gfx::Rect bounds(shelf_view_->GetIdealBoundsOfItemIcon(id));
   gfx::Point screen_origin;
diff --git a/ash/common/shelf/shelf_widget.h b/ash/common/shelf/shelf_widget.h
index 688a1c789..7225cce 100644
--- a/ash/common/shelf/shelf_widget.h
+++ b/ash/common/shelf/shelf_widget.h
@@ -29,6 +29,9 @@
 class WmShelf;
 class WmWindow;
 
+// The ShelfWidget manages the shelf view (which contains the shelf icons) and
+// the status area widget. There is one ShelfWidget per display. It is created
+// early during RootWindowController initialization.
 class ASH_EXPORT ShelfWidget : public views::Widget,
                                public views::WidgetObserver,
                                public ShelfBackgroundAnimatorObserver,
@@ -57,11 +60,11 @@
   ShelfLayoutManager* shelf_layout_manager() { return shelf_layout_manager_; }
   StatusAreaWidget* status_area_widget() const { return status_area_widget_; }
 
+  // Creates the shelf view and populates it with icons. Called after the user
+  // session is active (and hence the user profile is available).
   ShelfView* CreateShelfView();
   void PostCreateShelf();
 
-  // Set visibility of the shelf.
-  void SetShelfVisibility(bool visible);
   bool IsShelfVisible() const;
 
   bool IsShowingAppList() const;
@@ -115,7 +118,8 @@
   // |delegate_view_| is the contents view of this widget and is cleaned up
   // during CloseChildWindows of the associated RootWindowController.
   DelegateView* delegate_view_;
-  // View containing the shelf items. Owned by the views hierarchy.
+  // View containing the shelf items. Owned by the views hierarchy. Null when
+  // at the login screen.
   ShelfView* shelf_view_;
   ShelfBackgroundAnimator background_animator_;
   bool activating_as_fallback_;
diff --git a/ash/common/test/test_session_state_delegate.cc b/ash/common/test/test_session_state_delegate.cc
index 28b60f3..9132b8ce 100644
--- a/ash/common/test/test_session_state_delegate.cc
+++ b/ash/common/test/test_session_state_delegate.cc
@@ -161,12 +161,9 @@
 }
 
 void TestSessionStateDelegate::SetHasActiveUser(bool has_active_user) {
-  if (!has_active_user) {
-    session_state_ = session_manager::SessionState::LOGIN_PRIMARY;
-  } else {
-    session_state_ = session_manager::SessionState::ACTIVE;
-    WmShell::Get()->ShowShelf();
-  }
+  session_state_ = has_active_user
+                       ? session_manager::SessionState::ACTIVE
+                       : session_manager::SessionState::LOGIN_PRIMARY;
 }
 
 void TestSessionStateDelegate::SetActiveUserSessionStarted(
diff --git a/ash/common/wm_shell.cc b/ash/common/wm_shell.cc
index 4015512..690780d 100644
--- a/ash/common/wm_shell.cc
+++ b/ash/common/wm_shell.cc
@@ -153,11 +153,6 @@
     root_window->GetRootWindowController()->CreateShelf();
 }
 
-void WmShell::ShowShelf() {
-  for (WmWindow* root_window : GetAllRootWindows())
-    root_window->GetRootWindowController()->ShowShelf();
-}
-
 void WmShell::CreateShelfDelegate() {
   // May be called multiple times as shelves are created and destroyed.
   if (shelf_delegate_)
@@ -274,6 +269,7 @@
       window_cycle_controller_(base::MakeUnique<WindowCycleController>()),
       window_selector_controller_(
           base::MakeUnique<WindowSelectorController>()) {
+  session_controller_->AddSessionStateObserver(this);
 
   prefs::mojom::PreferencesManagerPtr pref_manager_ptr;
   // Can be null in tests.
@@ -284,7 +280,9 @@
   pref_store_ = new preferences::PrefObserverStore(std::move(pref_manager_ptr));
 }
 
-WmShell::~WmShell() {}
+WmShell::~WmShell() {
+  session_controller_->RemoveSessionStateObserver(this);
+}
 
 RootWindowController* WmShell::GetPrimaryRootWindowController() {
   return GetPrimaryRootWindow()->GetRootWindowController();
@@ -418,4 +416,11 @@
   accelerator_controller_ = std::move(accelerator_controller);
 }
 
+void WmShell::SessionStateChanged(session_manager::SessionState state) {
+  // Create the shelf when a session becomes active. It's safe to do this
+  // multiple times (e.g. initial login vs. multiprofile add session).
+  if (state == session_manager::SessionState::ACTIVE)
+    CreateShelf();
+}
+
 }  // namespace ash
diff --git a/ash/common/wm_shell.h b/ash/common/wm_shell.h
index a5589c97..ae07822c 100644
--- a/ash/common/wm_shell.h
+++ b/ash/common/wm_shell.h
@@ -13,6 +13,7 @@
 #include "ash/ash_export.h"
 #include "ash/common/metrics/gesture_action_type.h"
 #include "ash/common/metrics/user_metrics_action.h"
+#include "ash/common/session/session_state_observer.h"
 #include "ash/common/wm/lock_state_observer.h"
 #include "base/observer_list.h"
 #include "components/ui_devtools/devtools_server.h"
@@ -101,7 +102,7 @@
 }
 
 // Similar to ash::Shell. Eventually the two will be merged.
-class ASH_EXPORT WmShell {
+class ASH_EXPORT WmShell : public SessionStateObserver {
  public:
   // This is necessary for a handful of places that is difficult to plumb
   // through context.
@@ -353,12 +354,10 @@
 
   virtual std::unique_ptr<KeyEventWatcher> CreateKeyEventWatcher() = 0;
 
-  // Initializes the appropriate shelves. Does nothing for any existing shelves.
+  // Creates the ShelfView for each display and populates it with items.
+  // TODO(jamescook): Rename this. http://crbug.com/679925
   void CreateShelf();
 
-  // Show shelf view if it was created hidden (before session has started).
-  void ShowShelf();
-
   void CreateShelfDelegate();
 
   // Called after maximize mode has started, windows might still animate though.
@@ -447,7 +446,7 @@
 
  protected:
   explicit WmShell(std::unique_ptr<ShellDelegate> shell_delegate);
-  virtual ~WmShell();
+  ~WmShell() override;
 
   base::ObserverList<ShellObserver>* shell_observers() {
     return &shell_observers_;
@@ -475,6 +474,9 @@
   void SetAcceleratorController(
       std::unique_ptr<AcceleratorController> accelerator_controller);
 
+  // SessionStateObserver:
+  void SessionStateChanged(session_manager::SessionState state) override;
+
  private:
   friend class AcceleratorControllerTest;
   friend class ScopedRootWindowForNewWindows;
diff --git a/ash/mus/test/wm_test_base.cc b/ash/mus/test/wm_test_base.cc
index 7179552..4acbe724d 100644
--- a/ash/mus/test/wm_test_base.cc
+++ b/ash/mus/test/wm_test_base.cc
@@ -7,10 +7,14 @@
 #include <algorithm>
 #include <vector>
 
+#include "ash/common/session/session_controller.h"
+#include "ash/common/wm_shell.h"
 #include "ash/mus/root_window_controller.h"
 #include "ash/mus/test/wm_test_helper.h"
 #include "ash/mus/window_manager.h"
 #include "ash/mus/window_manager_application.h"
+#include "ash/public/cpp/session_types.h"
+#include "ash/public/interfaces/session_controller.mojom.h"
 #include "ash/test/wm_window_aura_test_api.h"
 #include "base/memory/ptr_util.h"
 #include "services/ui/public/cpp/property_type_converters.h"
@@ -165,6 +169,9 @@
       base::MakeUnique<WmWindowAuraTestApi::GlobalMinimumSizeLock>();
   test_helper_.reset(new WmTestHelper);
   test_helper_->Init();
+
+  // Most tests assume the user is logged in (and hence the shelf is created).
+  SimulateUserLogin();
 }
 
 void WmTestBase::TearDown() {
@@ -174,5 +181,29 @@
   zero_duration_mode_.reset();
 }
 
+void WmTestBase::SimulateUserLogin() {
+  SessionController* session_controller = WmShell::Get()->session_controller();
+
+  // Simulate the first user logging in.
+  mojom::UserSessionPtr session = mojom::UserSession::New();
+  session->session_id = 1;
+  session->type = user_manager::USER_TYPE_REGULAR;
+  const std::string email("ash.user@example.com");
+  session->serialized_account_id = AccountId::FromUserEmail(email).Serialize();
+  session->display_name = "Ash User";
+  session->display_email = email;
+  session_controller->UpdateUserSession(std::move(session));
+
+  // Simulate the user session becoming active.
+  mojom::SessionInfoPtr info = mojom::SessionInfo::New();
+  info->max_users = 10;
+  info->can_lock_screen = true;
+  info->should_lock_screen_automatically = false;
+  info->add_user_session_policy = AddUserSessionPolicy::ALLOWED;
+  info->state = session_manager::SessionState::ACTIVE;
+  session_controller->SetSessionInfo(std::move(info));
+}
+
+
 }  // namespace mus
 }  // namespace ash
diff --git a/ash/mus/test/wm_test_base.h b/ash/mus/test/wm_test_base.h
index 24e2c620..ccdc56c 100644
--- a/ash/mus/test/wm_test_base.h
+++ b/ash/mus/test/wm_test_base.h
@@ -82,6 +82,10 @@
  private:
   friend class AshTestImplMus;
 
+  // Simulates the first user logging in and the session becoming active.
+  // Classic ash handles this via AshTestHelper and TestSessionStateDelegate.
+  void SimulateUserLogin();
+
   bool setup_called_ = false;
   bool teardown_called_ = false;
   std::unique_ptr<ui::ScopedAnimationDurationScaleMode> zero_duration_mode_;
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc
index 569c469..bd3a431 100644
--- a/ash/mus/window_manager.cc
+++ b/ash/mus/window_manager.cc
@@ -8,6 +8,7 @@
 
 #include <utility>
 
+#include "ash/common/session/session_controller.h"
 #include "ash/common/wm/container_finder.h"
 #include "ash/common/wm/window_state.h"
 #include "ash/display/screen_position_controller.h"
@@ -139,9 +140,6 @@
                               this, pointer_watcher_event_router_.get()));
   shell_->Initialize(blocking_pool);
   lookup_.reset(new WmLookupMus);
-
-  // TODO: this should be called when logged in. See http://crbug.com/654606.
-  shell_->CreateShelf();
 }
 
 aura::client::ActivationClient* WindowManager::activation_client() {
@@ -228,9 +226,9 @@
       root_window_controller_ptr.get();
   root_window_controllers_.insert(std::move(root_window_controller_ptr));
 
-  // TODO: this should be called when logged in. See http://crbug.com/654606.
-  root_window_controller->ash_root_window_controller()
-      ->CreateShelf();
+  // Create a shelf if a user is already logged in.
+  if (shell_->session_controller()->NumberOfLoggedInUsers())
+    root_window_controller->ash_root_window_controller()->CreateShelf();
 
   for (auto& observer : observers_)
     observer.OnRootWindowControllerAdded(root_window_controller);
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 2eb1dbf9..78b1014 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -371,14 +371,6 @@
   wm_shelf_->shelf_widget()->PostCreateShelf();
 }
 
-void RootWindowController::ShowShelf() {
-  if (!wm_shelf_->IsShelfInitialized())
-    return;
-  // TODO(jamescook): Move this into WmShelf.
-  wm_shelf_->shelf_widget()->SetShelfVisibility(true);
-  wm_shelf_->shelf_widget()->status_area_widget()->Show();
-}
-
 ShelfLayoutManager* RootWindowController::GetShelfLayoutManager() {
   return wm_shelf_->shelf_layout_manager();
 }
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index 910421f..b247545 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -141,10 +141,6 @@
   // Creates the shelf for this root window and notifies observers.
   void CreateShelf();
 
-  // Show shelf view if it was created hidden (before session has started).
-  // TODO(jamescook): Eliminate this and handle show via Shelf.
-  void ShowShelf();
-
   // Get touch HUDs associated with this root window controller.
   TouchHudDebug* touch_hud_debug() const { return touch_hud_debug_; }
   TouchHudProjection* touch_hud_projection() const {
diff --git a/ash/root_window_controller_unittest.cc b/ash/root_window_controller_unittest.cc
index fab0f26..510d1fe 100644
--- a/ash/root_window_controller_unittest.cc
+++ b/ash/root_window_controller_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "ash/aura/wm_window_aura.h"
 #include "ash/common/material_design/material_design_controller.h"
+#include "ash/common/session/session_controller.h"
 #include "ash/common/session/session_state_delegate.h"
 #include "ash/common/system/tray/system_tray_delegate.h"
 #include "ash/common/wm/system_modal_container_layout_manager.h"
@@ -16,7 +17,6 @@
 #include "ash/common/wm_shell.h"
 #include "ash/common/wm_window.h"
 #include "ash/public/cpp/shell_window_ids.h"
-#include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/test/ash_md_test_base.h"
 #include "ash/test/ash_test_base.h"
@@ -970,8 +970,8 @@
   // Track the keyboard container window.
   aura::WindowTracker tracker;
   tracker.Add(keyboard_container);
-  // Mock a login user profile change to reinitialize the keyboard.
-  Shell::GetInstance()->OnLoginUserProfilePrepared();
+  // Reinitialize the keyboard.
+  Shell::GetInstance()->CreateKeyboard();
   // keyboard_container should no longer be present.
   EXPECT_FALSE(tracker.Contains(keyboard_container));
 }
@@ -1005,7 +1005,9 @@
   }
 
   // Mock a login user profile change to reinitialize the keyboard.
-  Shell::GetInstance()->OnLoginUserProfilePrepared();
+  mojom::SessionInfoPtr info = mojom::SessionInfo::New();
+  info->state = session_manager::SessionState::ACTIVE;
+  WmShell::Get()->session_controller()->SetSessionInfo(std::move(info));
   EXPECT_EQ(display::Screen::GetScreen()->GetPrimaryDisplay().work_area(),
             before);
 }
diff --git a/ash/shell.cc b/ash/shell.cc
index fc0b711..c47dbe8 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -273,11 +273,6 @@
     observer.OnLoginStateChanged(status);
 }
 
-void Shell::OnLoginUserProfilePrepared() {
-  wm_shell_->CreateShelf();
-  CreateKeyboard();
-}
-
 void Shell::OnAppTerminating() {
   for (auto& observer : *wm_shell_->shell_observers())
     observer.OnAppTerminating();
diff --git a/ash/shell.h b/ash/shell.h
index 920a205e..f7890a474 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -206,9 +206,6 @@
   // Called when the user logs in.
   void OnLoginStateChanged(LoginStatus status);
 
-  // Called after the logged-in user's profile is ready.
-  void OnLoginUserProfilePrepared();
-
   // Called when the application is exiting.
   void OnAppTerminating();
 
diff --git a/base/at_exit.cc b/base/at_exit.cc
index cfe4cf9..5dcc83c 100644
--- a/base/at_exit.cc
+++ b/base/at_exit.cc
@@ -22,6 +22,8 @@
 // this for thread-safe access, since it will only be modified in testing.
 static AtExitManager* g_top_manager = NULL;
 
+static bool g_disable_managers = false;
+
 AtExitManager::AtExitManager()
     : processing_callbacks_(false), next_manager_(g_top_manager) {
 // If multiple modules instantiate AtExitManagers they'll end up living in this
@@ -39,7 +41,8 @@
   }
   DCHECK_EQ(this, g_top_manager);
 
-  ProcessCallbacksNow();
+  if (!g_disable_managers)
+    ProcessCallbacksNow();
   g_top_manager = next_manager_;
 }
 
@@ -88,6 +91,11 @@
   DCHECK(g_top_manager->stack_.empty());
 }
 
+void AtExitManager::DisableAllAtExitManagers() {
+  AutoLock lock(g_top_manager->lock_);
+  g_disable_managers = true;
+}
+
 AtExitManager::AtExitManager(bool shadow)
     : processing_callbacks_(false), next_manager_(g_top_manager) {
   DCHECK(shadow || !g_top_manager);
diff --git a/base/at_exit.h b/base/at_exit.h
index 02e18ed9..6bf3f503 100644
--- a/base/at_exit.h
+++ b/base/at_exit.h
@@ -49,6 +49,10 @@
   // is possible to register new callbacks after calling this function.
   static void ProcessCallbacksNow();
 
+  // Disable all registered at-exit callbacks. This is used only in a single-
+  // process mode.
+  static void DisableAllAtExitManagers();
+
  protected:
   // This constructor will allow this instance of AtExitManager to be created
   // even if one already exists.  This should only be used for testing!
diff --git a/build/android/gradle/build.gradle.jinja b/build/android/gradle/build.gradle.jinja
index 008a1d9..1475cea3 100644
--- a/build/android/gradle/build.gradle.jinja
+++ b/build/android/gradle/build.gradle.jinja
@@ -74,16 +74,17 @@
 
         main.manifest.srcFile "{{ android_manifest }}"
 
-{% if template_type == 'android_library' %}
-        main {
-{% else %}
-        test {
-{% endif %}
+        {{ sourceSetName }} {
             java.srcDirs = [
 {% for path in java_dirs %}
                 "{{ path }}",
 {% endfor %}
             ]
+            jniLibs.srcDirs = [
+{% for path in jni_libs %}
+                "{{ path }}",
+{% endfor %}
+            ]
         }
     }
 }
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py
index 6a6e850d..d20ec41 100755
--- a/build/android/gradle/generate_gradle.py
+++ b/build/android/gradle/generate_gradle.py
@@ -34,6 +34,8 @@
 
 _JAVA_SUBDIR = 'symlinked-java'
 _SRCJARS_SUBDIR = 'extracted-srcjars'
+_JNI_LIBS_SUBDIR = 'symlinked-libs'
+_ARMEABI_SUBDIR = 'armeabi'
 
 _DEFAULT_TARGETS = [
     # TODO(agrieve): Requires alternate android.jar to compile.
@@ -183,6 +185,13 @@
   return list(found_roots)
 
 
+def _CreateRelativeSymlink(target_path, link_path):
+  link_dir = os.path.dirname(link_path)
+  relpath = os.path.relpath(target_path, link_dir)
+  logging.debug('Creating symlink %s -> %s', link_path, relpath)
+  os.symlink(relpath, link_path)
+
+
 def _CreateSymlinkTree(entry_output_dir, symlink_dir, desired_files,
                        parent_dirs):
   """Creates a directory tree of symlinks to the given files.
@@ -199,9 +208,7 @@
     symlinked_dir = os.path.dirname(symlinked_path)
     if not os.path.exists(symlinked_dir):
       os.makedirs(symlinked_dir)
-    relpath = os.path.relpath(target_path, symlinked_dir)
-    logging.debug('Creating symlink %s -> %s', symlinked_path, relpath)
-    os.symlink(relpath, symlinked_path)
+    _CreateRelativeSymlink(target_path, symlinked_path)
 
 
 def _CreateJavaSourceDir(output_dir, entry_output_dir, java_files):
@@ -239,6 +246,27 @@
   return java_dirs
 
 
+def _CreateJniLibsDir(output_dir, entry_output_dir, so_files):
+  """Creates directory with symlinked .so files if necessary.
+
+  Returns list of JNI libs directories."""
+
+  if so_files:
+    symlink_dir = os.path.join(entry_output_dir, _JNI_LIBS_SUBDIR)
+    shutil.rmtree(symlink_dir, True)
+    abi_dir = os.path.join(symlink_dir, _ARMEABI_SUBDIR)
+    if not os.path.exists(abi_dir):
+      os.makedirs(abi_dir)
+    for so_file in so_files:
+      target_path = os.path.join(output_dir, so_file)
+      symlinked_path = os.path.join(abi_dir, so_file)
+      _CreateRelativeSymlink(target_path, symlinked_path)
+
+    return [symlink_dir]
+
+  return []
+
+
 def _GenerateLocalProperties(sdk_dir):
   """Returns the data for project.properties as a string."""
   return '\n'.join([
@@ -247,8 +275,9 @@
       ''])
 
 
-def _GenerateGradleFile(build_config, build_vars, java_dirs, relativize,
-                        use_gradle_process_resources, jinja_processor):
+def _GenerateGradleFile(build_config, build_vars, java_dirs, jni_libs,
+                        relativize, use_gradle_process_resources,
+                        jinja_processor):
   """Returns the data for a project's build.gradle."""
   deps_info = build_config['deps_info']
   gradle = build_config['gradle']
@@ -288,6 +317,7 @@
                                 _DEFAULT_ANDROID_MANIFEST_PATH)
   variables['android_manifest'] = relativize(android_manifest)
   variables['java_dirs'] = relativize(java_dirs)
+  variables['jni_libs'] = relativize(jni_libs)
   # TODO(agrieve): Add an option to use interface jars and see if that speeds
   # things up at all.
   variables['prebuilts'] = relativize(gradle['dependent_prebuilt_jars'])
@@ -444,8 +474,15 @@
     if srcjars:
       java_dirs.append(os.path.join(entry_output_dir, _SRCJARS_SUBDIR))
 
-    data = _GenerateGradleFile(build_config, build_vars, java_dirs, relativize,
-                               args.use_gradle_process_resources,
+    native_section = build_config.get('native')
+    if native_section:
+      jni_libs = _CreateJniLibsDir(
+          output_dir, entry_output_dir, native_section.get('libraries'))
+    else:
+      jni_libs = []
+
+    data = _GenerateGradleFile(build_config, build_vars, java_dirs, jni_libs,
+                               relativize, args.use_gradle_process_resources,
                                jinja_processor)
     if data:
       project_entries.append(entry)
diff --git a/chrome/browser/android/data_usage/data_use_ui_tab_model_factory.cc b/chrome/browser/android/data_usage/data_use_ui_tab_model_factory.cc
index 4c678d1..b3b252d 100644
--- a/chrome/browser/android/data_usage/data_use_ui_tab_model_factory.cc
+++ b/chrome/browser/android/data_usage/data_use_ui_tab_model_factory.cc
@@ -12,7 +12,9 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace chrome {
@@ -35,6 +37,19 @@
   return io_thread->globals()->external_data_use_observer->GetDataUseTabModel();
 }
 
+void SetRegisterGoogleVariationIDOnIOThread(IOThread* io_thread,
+                                            bool register_google_variation_id) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+  // Avoid null pointer referencing during browser shutdown.
+  if (io_thread && !io_thread->globals() &&
+      io_thread->globals()->external_data_use_observer) {
+    io_thread->globals()
+        ->external_data_use_observer->SetRegisterGoogleVariationID(
+            register_google_variation_id);
+  }
+}
+
 }  // namespace
 
 // static
@@ -64,10 +79,12 @@
 KeyedService* DataUseUITabModelFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   DataUseUITabModel* data_use_ui_tab_model = new DataUseUITabModel();
+  Profile* profile = Profile::FromBrowserContext(context)->GetOriginalProfile();
+  const SigninManager* signin_manager =
+      SigninManagerFactory::GetForProfileIfExists(profile);
 
   // DataUseUITabModel should not be created for incognito profile.
-  DCHECK_EQ(Profile::FromBrowserContext(context)->GetOriginalProfile(),
-            Profile::FromBrowserContext(context));
+  DCHECK_EQ(profile, Profile::FromBrowserContext(context));
 
   // Pass the DataUseTabModel pointer to DataUseUITabModel.
   content::BrowserThread::PostTaskAndReplyWithResult(
@@ -76,6 +93,12 @@
       base::Bind(&chrome::android::DataUseUITabModel::SetDataUseTabModel,
                  data_use_ui_tab_model->GetWeakPtr()));
 
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO, FROM_HERE,
+      base::Bind(&SetRegisterGoogleVariationIDOnIOThread,
+                 g_browser_process->io_thread(),
+                 signin_manager && signin_manager->IsAuthenticated()));
+
   return data_use_ui_tab_model;
 }
 
diff --git a/chrome/browser/android/data_usage/data_use_ui_tab_model_unittest.cc b/chrome/browser/android/data_usage/data_use_ui_tab_model_unittest.cc
index 823e7137..e82bee20 100644
--- a/chrome/browser/android/data_usage/data_use_ui_tab_model_unittest.cc
+++ b/chrome/browser/android/data_usage/data_use_ui_tab_model_unittest.cc
@@ -21,6 +21,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/common/url_constants.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
 #include "components/data_usage/core/data_use_aggregator.h"
 #include "components/data_usage/core/data_use_amortizer.h"
 #include "components/data_usage/core/data_use_annotator.h"
@@ -115,6 +118,11 @@
 
  protected:
   void SetUp() override {
+    profile_manager_.reset(
+        new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
+    EXPECT_TRUE(profile_manager_->SetUp());
+    profile_ = profile_manager_->CreateTestingProfile("p1");
+
     io_task_runner_ = content::BrowserThread::GetTaskRunnerForThread(
         content::BrowserThread::IO);
     ui_task_runner_ = content::BrowserThread::GetTaskRunnerForThread(
@@ -141,6 +149,12 @@
   DataUseUITabModel data_use_ui_tab_model_;
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
+  std::unique_ptr<TestingProfileManager> profile_manager_;
+
+  // Test profile used by the tests is owned by |profile_manager_|.
+  TestingProfile* profile_;
+
   std::unique_ptr<data_usage::DataUseAggregator> data_use_aggregator_;
   std::unique_ptr<ExternalDataUseObserver> external_data_use_observer_;
   std::unique_ptr<TestDataUseTabModel> data_use_tab_model_;
diff --git a/chrome/browser/android/data_usage/external_data_use_observer.cc b/chrome/browser/android/data_usage/external_data_use_observer.cc
index 9c7d3fe7..44ce0df 100644
--- a/chrome/browser/android/data_usage/external_data_use_observer.cc
+++ b/chrome/browser/android/data_usage/external_data_use_observer.cc
@@ -217,6 +217,19 @@
   return data_use_tab_model_;
 }
 
+void ExternalDataUseObserver::SetRegisterGoogleVariationID(
+    bool register_google_variation_id) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  // It is okay to use base::Unretained here since
+  // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed
+  // on UI thread when |this| is destroyed.
+  ui_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&ExternalDataUseObserverBridge::SetRegisterGoogleVariationID,
+                 base::Unretained(external_data_use_observer_bridge_),
+                 register_google_variation_id));
+}
+
 }  // namespace android
 
 }  // namespace chrome
diff --git a/chrome/browser/android/data_usage/external_data_use_observer.h b/chrome/browser/android/data_usage/external_data_use_observer.h
index 4168522..3c4b7c2 100644
--- a/chrome/browser/android/data_usage/external_data_use_observer.h
+++ b/chrome/browser/android/data_usage/external_data_use_observer.h
@@ -78,6 +78,8 @@
     return external_data_use_reporter_;
   }
 
+  void SetRegisterGoogleVariationID(bool register_google_variation_id);
+
  private:
   friend class DataUseTabModelTest;
   friend class DataUseUITabModelTest;
diff --git a/chrome/browser/android/data_usage/external_data_use_observer_bridge.cc b/chrome/browser/android/data_usage/external_data_use_observer_bridge.cc
index 01f57f4..ca929ed4 100644
--- a/chrome/browser/android/data_usage/external_data_use_observer_bridge.cc
+++ b/chrome/browser/android/data_usage/external_data_use_observer_bridge.cc
@@ -61,7 +61,8 @@
 
 ExternalDataUseObserverBridge::ExternalDataUseObserverBridge()
     : construct_time_(base::TimeTicks::Now()),
-      is_first_matching_rule_fetch_(true) {
+      is_first_matching_rule_fetch_(true),
+      register_google_variation_id_(false) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
 
   // Detach from IO thread since rest of ExternalDataUseObserverBridge lives on
@@ -210,7 +211,11 @@
       base::Bind(&ExternalDataUseObserver::ShouldRegisterAsDataUseObserver,
                  external_data_use_observer_, should_register));
 
+  if (!register_google_variation_id_)
+    return;
+
   variations::VariationID variation_id = GetGoogleVariationID();
+
   if (variation_id != variations::EMPTY_ID) {
     // Set variation id for the enabled group if |should_register| is true.
     // Otherwise clear the variation id for the enabled group by setting to
@@ -226,6 +231,12 @@
   }
 }
 
+void ExternalDataUseObserverBridge::SetRegisterGoogleVariationID(
+    bool register_google_variation_id) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  register_google_variation_id_ = register_google_variation_id;
+}
+
 bool RegisterExternalDataUseObserver(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
diff --git a/chrome/browser/android/data_usage/external_data_use_observer_bridge.h b/chrome/browser/android/data_usage/external_data_use_observer_bridge.h
index 9bcb5d81..b8ae223 100644
--- a/chrome/browser/android/data_usage/external_data_use_observer_bridge.h
+++ b/chrome/browser/android/data_usage/external_data_use_observer_bridge.h
@@ -98,6 +98,8 @@
   // should register as a data use observer.
   virtual void ShouldRegisterAsDataUseObserver(bool should_register) const;
 
+  void SetRegisterGoogleVariationID(bool register_google_variation_id);
+
  private:
   // Java listener that provides regular expressions to |this|. Data use
   // reports are submitted to |j_external_data_use_observer_|.
@@ -117,6 +119,9 @@
   // True if matching rules are fetched for the first time.
   bool is_first_matching_rule_fetch_;
 
+  // True if Google variation ID should be registered.
+  bool register_google_variation_id_;
+
   // |io_task_runner_| accesses ExternalDataUseObserver members on IO thread.
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
 
diff --git a/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc b/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc
index b89cd31..1a25c0d5e 100644
--- a/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc
+++ b/chrome/browser/android/data_usage/external_data_use_observer_unittest.cc
@@ -18,6 +18,9 @@
 #include "base/test/histogram_tester.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/android/data_usage/data_use_tab_model.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
 #include "components/data_usage/core/data_use.h"
 #include "components/data_usage/core/data_use_aggregator.h"
 #include "components/sessions/core/session_id.h"
@@ -45,6 +48,11 @@
   void SetUp() override {
     thread_bundle_.reset(new content::TestBrowserThreadBundle(
         content::TestBrowserThreadBundle::IO_MAINLOOP));
+    profile_manager_.reset(
+        new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
+    EXPECT_TRUE(profile_manager_->SetUp());
+    profile_ = profile_manager_->CreateTestingProfile("p1");
+
     io_task_runner_ = content::BrowserThread::GetTaskRunnerForThread(
         content::BrowserThread::IO);
     ui_task_runner_ = content::BrowserThread::GetTaskRunnerForThread(
@@ -121,6 +129,11 @@
   std::unique_ptr<data_usage::DataUseAggregator> data_use_aggregator_;
   std::unique_ptr<ExternalDataUseObserver> external_data_use_observer_;
 
+  std::unique_ptr<TestingProfileManager> profile_manager_;
+
+  // Test profile used by the tests is owned by |profile_manager_|.
+  TestingProfile* profile_;
+
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
 };
diff --git a/chrome/browser/android/data_usage/external_data_use_reporter_unittest.cc b/chrome/browser/android/data_usage/external_data_use_reporter_unittest.cc
index 1c59d91..c1a96bb 100644
--- a/chrome/browser/android/data_usage/external_data_use_reporter_unittest.cc
+++ b/chrome/browser/android/data_usage/external_data_use_reporter_unittest.cc
@@ -20,6 +20,9 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/android/data_usage/data_use_tab_model.h"
 #include "chrome/browser/android/data_usage/external_data_use_observer.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
 #include "components/data_usage/core/data_use.h"
 #include "components/data_usage/core/data_use_aggregator.h"
 #include "components/sessions/core/session_id.h"
@@ -58,6 +61,11 @@
   void SetUp() override {
     thread_bundle_.reset(new content::TestBrowserThreadBundle(
         content::TestBrowserThreadBundle::IO_MAINLOOP));
+    profile_manager_.reset(
+        new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
+    EXPECT_TRUE(profile_manager_->SetUp());
+    profile_ = profile_manager_->CreateTestingProfile("p1");
+
     io_task_runner_ = content::BrowserThread::GetTaskRunnerForThread(
         content::BrowserThread::IO);
     ui_task_runner_ = content::BrowserThread::GetTaskRunnerForThread(
@@ -160,6 +168,11 @@
   std::unique_ptr<data_usage::DataUseAggregator> data_use_aggregator_;
   std::unique_ptr<ExternalDataUseObserver> external_data_use_observer_;
 
+  std::unique_ptr<TestingProfileManager> profile_manager_;
+
+  // Test profile used by the tests is owned by |profile_manager_|.
+  TestingProfile* profile_;
+
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
 };
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index ad1ebe5..a0f3bf2 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -353,6 +353,7 @@
 #if defined(ENABLE_MEDIA_ROUTER)
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/media/router/presentation_service_delegate_impl.h"
+#include "chrome/browser/media/router/receiver_presentation_service_delegate_impl.h"
 #endif  // defined(ENABLE_MEDIA_ROUTER)
 
 #if BUILDFLAG(ENABLE_MEDIA_REMOTING) && defined(ENABLE_MEDIA_ROUTER)
@@ -3124,9 +3125,9 @@
 #endif
 }
 
-content::PresentationServiceDelegate*
-ChromeContentBrowserClient::GetPresentationServiceDelegate(
-      content::WebContents* web_contents) {
+content::ControllerPresentationServiceDelegate*
+ChromeContentBrowserClient::GetControllerPresentationServiceDelegate(
+    content::WebContents* web_contents) {
 #if defined(ENABLE_MEDIA_ROUTER)
   if (media_router::MediaRouterEnabled(web_contents->GetBrowserContext())) {
     return media_router::PresentationServiceDelegateImpl::
@@ -3136,6 +3137,24 @@
   return nullptr;
 }
 
+content::ReceiverPresentationServiceDelegate*
+ChromeContentBrowserClient::GetReceiverPresentationServiceDelegate(
+    content::WebContents* web_contents) {
+#if defined(ENABLE_MEDIA_ROUTER)
+  if (media_router::MediaRouterEnabled(web_contents->GetBrowserContext())) {
+    // ReceiverPresentationServiceDelegateImpl exists only for WebContents
+    // created for offscreen presentations. The WebContents must belong to
+    // an incognito profile.
+    if (auto* impl = media_router::ReceiverPresentationServiceDelegateImpl::
+            FromWebContents(web_contents)) {
+      DCHECK(web_contents->GetBrowserContext()->IsOffTheRecord());
+      return impl;
+    }
+  }
+#endif  // defined(ENABLE_MEDIA_ROUTER)
+  return nullptr;
+}
+
 void ChromeContentBrowserClient::RecordURLMetric(const std::string& metric,
                                                  const GURL& url) {
   if (url.is_valid()) {
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 6d6f8bb..71a64f4 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -292,7 +292,11 @@
                const content::OpenURLParams& params,
                const base::Callback<void(content::WebContents*)>& callback)
       override;
-  content::PresentationServiceDelegate* GetPresentationServiceDelegate(
+  content::ControllerPresentationServiceDelegate*
+  GetControllerPresentationServiceDelegate(
+      content::WebContents* web_contents) override;
+  content::ReceiverPresentationServiceDelegate*
+  GetReceiverPresentationServiceDelegate(
       content::WebContents* web_contents) override;
   void RecordURLMetric(const std::string& metric, const GURL& url) override;
   ScopedVector<content::NavigationThrottle> CreateThrottlesForNavigation(
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager.cc b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
index 4e96f2b..bccc2f7 100644
--- a/chrome/browser/chromeos/login/session/chrome_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/chrome_session_manager.cc
@@ -134,7 +134,6 @@
 
   bool is_running_test = command_line->HasSwitch(::switches::kTestName) ||
                          command_line->HasSwitch(::switches::kTestType);
-
   if (!is_running_test) {
     // Enable CrasAudioHandler logging when chrome restarts after crashing.
     if (chromeos::CrasAudioHandler::IsInitialized())
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
index 75874be..0292ad6 100644
--- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
+++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "ash/common/shelf/wm_shelf.h"
 #include "ash/common/wallpaper/wallpaper_controller.h"
 #include "ash/common/wm_shell.h"
 #include "base/memory/ptr_util.h"
@@ -369,8 +368,6 @@
   // For manager user, move wallpaper to locked container so that windows
   // created during the user image picker step are below it.
   ash::WmShell::Get()->wallpaper_controller()->MoveToLockedContainer();
-  ash::WmShelf::ForWindow(ash::WmShell::Get()->GetPrimaryRootWindow())
-      ->SetAlignment(ash::ShelfAlignment::SHELF_ALIGNMENT_BOTTOM_LOCKED);
 
   controller_->SetManagerProfile(manager_profile);
   if (actor_)
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index 7b4245cf..5de0f25 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -57,6 +57,10 @@
     "presentation_request.h",
     "presentation_service_delegate_impl.cc",
     "presentation_service_delegate_impl.h",
+    "presentation_service_delegate_observers.cc",
+    "presentation_service_delegate_observers.h",
+    "receiver_presentation_service_delegate_impl.cc",
+    "receiver_presentation_service_delegate_impl.h",
     "render_frame_host_id.h",
     "route_message.cc",
     "route_message.h",
diff --git a/chrome/browser/media/router/offscreen_presentation_manager.cc b/chrome/browser/media/router/offscreen_presentation_manager.cc
index 917d1a2ca..0e721ad4 100644
--- a/chrome/browser/media/router/offscreen_presentation_manager.cc
+++ b/chrome/browser/media/router/offscreen_presentation_manager.cc
@@ -38,14 +38,17 @@
     const std::string& presentation_id,
     const GURL& presentation_url,
     const RenderFrameHostId& render_frame_host_id,
-    content::PresentationConnectionPtr controller) {
+    content::PresentationConnectionPtr controller_connection_ptr,
+    content::PresentationConnectionRequest receiver_connection_request) {
   DVLOG(2) << __FUNCTION__ << " [presentation_id]: " << presentation_id
            << ", [render_frame_host_id]: " << render_frame_host_id.second;
   DCHECK(thread_checker_.CalledOnValidThread());
 
   auto* presentation =
       GetOrCreateOffscreenPresentation(presentation_id, presentation_url);
-  presentation->RegisterController(render_frame_host_id, std::move(controller));
+  presentation->RegisterController(render_frame_host_id,
+                                   std::move(controller_connection_ptr),
+                                   std::move(receiver_connection_request));
 }
 
 void OffscreenPresentationManager::UnregisterOffscreenPresentationController(
@@ -62,7 +65,7 @@
   // Remove presentation if no controller and receiver.
   it->second->UnregisterController(render_frame_host_id);
   if (!it->second->IsValid()) {
-    DLOG(WARNING) << __func__ << "no receiver callback has been registered to "
+    DLOG(WARNING) << __func__ << " no receiver callback has been registered to "
                   << "[presentation_id]: " << presentation_id;
     offscreen_presentations_.erase(presentation_id);
   }
@@ -97,14 +100,18 @@
 
 void OffscreenPresentationManager::OffscreenPresentation::RegisterController(
     const RenderFrameHostId& render_frame_host_id,
-    content::PresentationConnectionPtr controller) {
+    content::PresentationConnectionPtr controller_connection_ptr,
+    content::PresentationConnectionRequest receiver_connection_request) {
   if (!receiver_callback_.is_null()) {
     receiver_callback_.Run(
         content::PresentationSessionInfo(presentation_url_, presentation_id_),
-        std::move(controller));
+        std::move(controller_connection_ptr),
+        std::move(receiver_connection_request));
   } else {
-    pending_controllers_.insert(
-        std::make_pair(render_frame_host_id, std::move(controller)));
+    pending_controllers_.insert(std::make_pair(
+        render_frame_host_id, base::MakeUnique<ControllerConnection>(
+                                  std::move(controller_connection_ptr),
+                                  std::move(receiver_connection_request))));
   }
 }
 
@@ -120,7 +127,8 @@
   for (auto& controller : pending_controllers_) {
     receiver_callback.Run(
         content::PresentationSessionInfo(presentation_url_, presentation_id_),
-        std::move(controller.second));
+        std::move(controller.second->controller_connection_ptr),
+        std::move(controller.second->receiver_connection_request));
   }
   receiver_callback_ = receiver_callback;
   pending_controllers_.clear();
@@ -130,4 +138,14 @@
   return !(pending_controllers_.empty() && receiver_callback_.is_null());
 }
 
+OffscreenPresentationManager::OffscreenPresentation::ControllerConnection::
+    ControllerConnection(
+        content::PresentationConnectionPtr controller_connection_ptr,
+        content::PresentationConnectionRequest receiver_connection_request)
+    : controller_connection_ptr(std::move(controller_connection_ptr)),
+      receiver_connection_request(std::move(receiver_connection_request)) {}
+
+OffscreenPresentationManager::OffscreenPresentation::ControllerConnection::
+    ~ControllerConnection() {}
+
 }  // namespace media_router
diff --git a/chrome/browser/media/router/offscreen_presentation_manager.h b/chrome/browser/media/router/offscreen_presentation_manager.h
index df276101..d3a3dab 100644
--- a/chrome/browser/media/router/offscreen_presentation_manager.h
+++ b/chrome/browser/media/router/offscreen_presentation_manager.h
@@ -18,20 +18,6 @@
 
 class GURL;
 
-// TODO(zhaobin): move these back to
-// content/public/browser/presentation_service_delegate.h when they are actually
-// used in content.
-namespace content {
-// TODO(zhaobin): A class stub for blink::mojom::PresentationConnectionPtr.
-// presentation.mojom is under security review. Change this to
-// blink::mojom::PresentationConnectionPtr once that is done.
-class PresentationConnectionPtr {};
-
-using ReceiverConnectionAvailableCallback =
-    base::Callback<void(const content::PresentationSessionInfo&,
-                        PresentationConnectionPtr)>;
-}  // namespace content
-
 namespace media_router {
 // Manages all offscreen presentations started in the associated Profile and
 // facilitates communication between the controllers and the receiver of an
@@ -51,31 +37,36 @@
 //   manager->OnOffscreenPresentationReceiverCreated(presentation_id,
 //       base::Bind(&PresentationServiceImpl::OnReceiverConnectionAvailable));
 //
-// Controller frame establishes connection with the receiver side, resulting
+// Controlling frame establishes connection with the receiver side, resulting
 // in a connection with the two endpoints being the controller
 // PresentationConnectionPtr and receiver PresentationConnectionPtr.
 // Note calling this will trigger receiver frame's
 // PresentationServiceImpl::OnReceiverConnectionAvailable.
 //
 //   manager->RegisterOffscreenPresentationController(
-//       presentation_id, controller_frame_id, controller_ptr);
+//       presentation_id, controller_frame_id, controller_connection_ptr,
+//       receiver_connection_request);
 //
 // Invoked on receiver's PresentationServiceImpl when controller connection is
 // established.
 //
 //   |presentation_receiver_client_|: blink::mojom::PresentationServiceClienPtr
 //   for the presentation receiver.
-//   |PresentationConnectionPtr|: blink::mojom::PresentationConnectionPtr for
-//   blink::PresentationConnection object in render process.
+//   |controller_connection_ptr|: blink::mojom::PresentationConnectionPtr for
+//   blink::PresentationConnection object in controlling frame's render process.
+//   |receiver_connection_request|: Mojo InterfaceRequest to be bind to
+//   blink::PresentationConnection object in receiver frame's render process.
 //   void PresentationServiceImpl::OnReceiverConnectionAvailable(
 //       const content::PresentationSessionInfo& session,
-//       PresentationConnectionPtr&& controller) {
+//       PresentationConnectionPtr controller_connection_ptr,
+//       PresentationConnectionRequest receiver_connection_request) {
 //     presentation_receiver_client_->OnReceiverConnectionAvailable(
 //         blink::mojom::PresentationSessionInfo::From(session_info),
-//         std::move(controller));
+//         std::move(controller_connection_ptr),
+//         std::move(receiver_connection_request));
 //   }
 //
-// Send message from controller/receiver to receiver/controller:
+// Send message from controlling/receiver frame to receiver/controlling frame:
 //
 //   |target_connection_|: member variable of
 //                         blink::mojom::PresentationConnectionPtr type,
@@ -87,9 +78,8 @@
 //     target_connection_->OnSessionMessageReceived(std::move(session_message));
 //   }
 //
-// A controller or receiver leaves the offscreen presentation (e.g.,
-// due to navigation) by unregistering themselves from
-// OffscreenPresentation object.
+// A controller or receiver leaves the offscreen presentation (e.g., due to
+// navigation) by unregistering themselves from OffscreenPresentation object.
 //
 // When the receiver is no longer associated with an offscreen presentation, it
 // shall unregister itself with OffscreenPresentationManager. Unregistration
@@ -108,57 +98,63 @@
  public:
   ~OffscreenPresentationManager() override;
 
-  // Registers controller PresentationConnectionPtr to presentation
-  // with |presentation_id|, |render_frame_id|.
+  // Registers controller PresentationConnectionPtr to presentation with
+  // |presentation_id| and |render_frame_id|.
   // Creates a new presentation if no presentation with |presentation_id|
   // exists.
-  // |controller|: Not owned by this class. Ownership is transferred to the
-  //               presentation receiver via |receiver_callback| passed below.
-  void RegisterOffscreenPresentationController(
+  // |controller_connection_ptr|, |receiver_connection_request|: Not owned by
+  // this class. Ownership is transferred to presentation receiver via
+  // |receiver_callback| passed below.
+  virtual void RegisterOffscreenPresentationController(
       const std::string& presentation_id,
       const GURL& presentation_url,
       const RenderFrameHostId& render_frame_id,
-      content::PresentationConnectionPtr controller);
+      content::PresentationConnectionPtr controller_connection_ptr,
+      content::PresentationConnectionRequest receiver_connection_request);
 
   // Unregisters controller PresentationConnectionPtr to presentation with
   // |presentation_id|, |render_frame_id|. It does nothing if there is no
   // controller that matches the provided arguments. It removes presentation
-  // that matches the arguments if the presentation has no receiver_callback and
-  // any other pending controller.
-  void UnregisterOffscreenPresentationController(
+  // that matches the arguments if the presentation has no |receiver_callback|
+  // and any other pending controller.
+  virtual void UnregisterOffscreenPresentationController(
       const std::string& presentation_id,
       const RenderFrameHostId& render_frame_id);
 
-  // Registers ReceiverConnectionAvailableCallback to presentation
-  // with |presentation_id|.
-  void OnOffscreenPresentationReceiverCreated(
+  // Registers |receiver_callback| to presentation with |presentation_id| and
+  // |presentation_url|.
+  virtual void OnOffscreenPresentationReceiverCreated(
       const std::string& presentation_id,
       const GURL& presentation_url,
       const content::ReceiverConnectionAvailableCallback& receiver_callback);
 
-  // Unregisters the ReceiverConnectionAvailableCallback associated with
+  // Unregisters ReceiverConnectionAvailableCallback associated with
   // |presentation_id|.
-  void OnOffscreenPresentationReceiverTerminated(
+  virtual void OnOffscreenPresentationReceiverTerminated(
       const std::string& presentation_id);
 
  private:
   // Represents an offscreen presentation registered with
-  // OffscreenPresentationManager.
-  // Contains callback to the receiver to inform it of new connections
-  // established from a controller.
-  // Contains set of controllers registered to OffscreenPresentationManager
-  // before corresponding receiver.
+  // OffscreenPresentationManager. Contains callback to the receiver to inform
+  // it of new connections established from a controller. Contains set of
+  // controllers registered to OffscreenPresentationManager before corresponding
+  // receiver.
   class OffscreenPresentation {
    public:
     OffscreenPresentation(const std::string& presentation_id,
                           const GURL& presentation_url);
     ~OffscreenPresentation();
 
-    // Register |controller| with |render_frame_id|. If |receiver_callback_| has
-    // been set, invoke |receiver_callback_| with |controller| as parameter,
-    // else store |controller| in |pending_controllers_| map.
-    void RegisterController(const RenderFrameHostId& render_frame_id,
-                            content::PresentationConnectionPtr controller);
+    // Register controller with |render_frame_id|. If |receiver_callback_| has
+    // been set, invoke |receiver_callback_| with |controller_connection_ptr|
+    // and |receiver_connection_request| as parameter, else creates a
+    // ControllerConnection object with |controller_connection_ptr| and
+    // |receiver_connection_request|, and store it in |pending_controllers_|
+    // map.
+    void RegisterController(
+        const RenderFrameHostId& render_frame_id,
+        content::PresentationConnectionPtr controller_connection_ptr,
+        content::PresentationConnectionRequest receiver_connection_request);
 
     // Unregister controller with |render_frame_id|. Do nothing if there is no
     // pending controller with |render_frame_id|.
@@ -185,10 +181,26 @@
     // Callback to invoke whenever a receiver connection is available.
     content::ReceiverConnectionAvailableCallback receiver_callback_;
 
-    // Contains Mojo pointers to controller PresentationConnections registered
-    // via |RegisterController()| before |receiver_callback_| is set.
+    // Stores controller information.
+    // |controller_connection_ptr|: Mojo::InterfacePtr to
+    // blink::PresentationConnection object in controlling frame;
+    // |receiver_connection_request|: Mojo::InterfaceRequest to be bind to
+    // blink::PresentationConnection object in receiver frame.
+    struct ControllerConnection {
+     public:
+      ControllerConnection(
+          content::PresentationConnectionPtr controller_connection_ptr,
+          content::PresentationConnectionRequest receiver_connection_request);
+      ~ControllerConnection();
+
+      content::PresentationConnectionPtr controller_connection_ptr;
+      content::PresentationConnectionRequest receiver_connection_request;
+    };
+
+    // Contains ControllerConnection objects registered via
+    // |RegisterController()| before |receiver_callback_| is set.
     std::unordered_map<RenderFrameHostId,
-                       content::PresentationConnectionPtr,
+                       std::unique_ptr<ControllerConnection>,
                        RenderFrameHostIdHasher>
         pending_controllers_;
 
@@ -198,6 +210,9 @@
  private:
   friend class OffscreenPresentationManagerFactory;
   friend class OffscreenPresentationManagerTest;
+  friend class MockOffscreenPresentationManager;
+  FRIEND_TEST_ALL_PREFIXES(PresentationServiceDelegateImplTest,
+                           ConnectToOffscreenPresentation);
 
   // Used by OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext.
   OffscreenPresentationManager();
diff --git a/chrome/browser/media/router/offscreen_presentation_manager_factory.cc b/chrome/browser/media/router/offscreen_presentation_manager_factory.cc
index c5e3e5db..5965e25 100644
--- a/chrome/browser/media/router/offscreen_presentation_manager_factory.cc
+++ b/chrome/browser/media/router/offscreen_presentation_manager_factory.cc
@@ -39,6 +39,12 @@
       service_factory.Get().GetServiceForBrowserContext(context, true));
 }
 
+// static
+OffscreenPresentationManagerFactory*
+OffscreenPresentationManagerFactory::GetInstanceForTest() {
+  return &service_factory.Get();
+}
+
 OffscreenPresentationManagerFactory::OffscreenPresentationManagerFactory()
     : BrowserContextKeyedServiceFactory(
           "OffscreenPresentationManager",
diff --git a/chrome/browser/media/router/offscreen_presentation_manager_factory.h b/chrome/browser/media/router/offscreen_presentation_manager_factory.h
index 3fd8f3f..96232db 100644
--- a/chrome/browser/media/router/offscreen_presentation_manager_factory.h
+++ b/chrome/browser/media/router/offscreen_presentation_manager_factory.h
@@ -31,6 +31,9 @@
   static OffscreenPresentationManager* GetOrCreateForBrowserContext(
       content::BrowserContext* context);
 
+  // For test use only.
+  static OffscreenPresentationManagerFactory* GetInstanceForTest();
+
  private:
   friend struct base::DefaultLazyInstanceTraits<
       OffscreenPresentationManagerFactory>;
diff --git a/chrome/browser/media/router/offscreen_presentation_manager_unittest.cc b/chrome/browser/media/router/offscreen_presentation_manager_unittest.cc
index 6af4ab643..4563517 100644
--- a/chrome/browser/media/router/offscreen_presentation_manager_unittest.cc
+++ b/chrome/browser/media/router/offscreen_presentation_manager_unittest.cc
@@ -26,13 +26,14 @@
  public:
   void OnReceiverConnectionAvailable(
       const content::PresentationSessionInfo& session_info,
-      content::PresentationConnectionPtr connection_ptr) {
-    OnReceiverConnectionAvailableRaw(session_info, connection_ptr);
+      content::PresentationConnectionPtr controller_conn,
+      content::PresentationConnectionRequest receiver_conn_request) {
+    OnReceiverConnectionAvailableRaw(session_info, controller_conn.get());
   }
 
   MOCK_METHOD2(OnReceiverConnectionAvailableRaw,
                void(const content::PresentationSessionInfo&,
-                    content::PresentationConnectionPtr));
+                    blink::mojom::PresentationConnection*));
 };
 
 class OffscreenPresentationManagerTest : public ::testing::Test {
@@ -56,22 +57,25 @@
 
   void RegisterController(const std::string& presentation_id,
                           content::PresentationConnectionPtr controller) {
+    content::PresentationConnectionRequest receiver_conn_request;
     manager()->RegisterOffscreenPresentationController(
         presentation_id, presentation_url_, render_frame_host_id_,
-        std::move(controller));
+        std::move(controller), std::move(receiver_conn_request));
   }
 
   void RegisterController(const RenderFrameHostId& render_frame_id,
                           content::PresentationConnectionPtr controller) {
+    content::PresentationConnectionRequest receiver_conn_request;
     manager()->RegisterOffscreenPresentationController(
         kPresentationId, presentation_url_, render_frame_id,
-        std::move(controller));
+        std::move(controller), std::move(receiver_conn_request));
   }
 
   void RegisterController(content::PresentationConnectionPtr controller) {
+    content::PresentationConnectionRequest receiver_conn_request;
     manager()->RegisterOffscreenPresentationController(
         kPresentationId, presentation_url_, render_frame_host_id_,
-        std::move(controller));
+        std::move(controller), std::move(receiver_conn_request));
   }
 
   void RegisterReceiver(
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc
index 156a9bb5c..59e441a 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc
@@ -20,6 +20,8 @@
 #include "chrome/browser/media/router/media_router_factory.h"
 #include "chrome/browser/media/router/media_sink.h"
 #include "chrome/browser/media/router/media_source_helper.h"
+#include "chrome/browser/media/router/offscreen_presentation_manager.h"
+#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
 #include "chrome/browser/media/router/presentation_media_sinks_observer.h"
 #include "chrome/browser/media/router/route_message.h"
 #include "chrome/browser/media/router/route_message_observer.h"
@@ -30,6 +32,7 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/presentation_session.h"
+#include "url/gurl.h"
 
 #if !defined(OS_ANDROID)
 #include "chrome/browser/profiles/profile.h"
@@ -193,8 +196,7 @@
     MediaRouter* router)
     : render_frame_host_id_(render_frame_host_id),
       web_contents_(web_contents),
-      router_(router),
-      delegate_observer_(nullptr) {
+      router_(router) {
   DCHECK(web_contents_);
   DCHECK(router_);
 }
@@ -202,11 +204,6 @@
 PresentationFrame::~PresentationFrame() {
 }
 
-void PresentationFrame::OnPresentationServiceDelegateDestroyed() const {
-  if (delegate_observer_)
-    delegate_observer_->OnDelegateDestroyed();
-}
-
 void PresentationFrame::OnPresentationSessionStarted(
     const content::PresentationSessionInfo& session,
     const MediaRoute& route) {
@@ -458,10 +455,7 @@
   DCHECK(router_);
 }
 
-PresentationFrameManager::~PresentationFrameManager() {
-  for (auto& frame : presentation_frames_)
-    frame.second->OnPresentationServiceDelegateDestroyed();
-}
+PresentationFrameManager::~PresentationFrameManager() {}
 
 void PresentationFrameManager::OnPresentationSessionStarted(
     const RenderFrameHostId& render_frame_host_id,
@@ -568,22 +562,6 @@
   }
 }
 
-void PresentationFrameManager::AddDelegateObserver(
-    const RenderFrameHostId& render_frame_host_id,
-    DelegateObserver* observer) {
-  auto* presentation_frame = GetOrAddPresentationFrame(render_frame_host_id);
-  presentation_frame->set_delegate_observer(observer);
-}
-
-void PresentationFrameManager::RemoveDelegateObserver(
-    const RenderFrameHostId& render_frame_host_id) {
-  const auto it = presentation_frames_.find(render_frame_host_id);
-  if (it != presentation_frames_.end()) {
-    it->second->set_delegate_observer(nullptr);
-    presentation_frames_.erase(it);
-  }
-}
-
 void PresentationFrameManager::AddDefaultPresentationRequestObserver(
     PresentationServiceDelegateImpl::DefaultPresentationRequestObserver*
         observer) {
@@ -688,14 +666,12 @@
                                                   int render_frame_id,
                                                   DelegateObserver* observer) {
   DCHECK(observer);
-  frame_manager_->AddDelegateObserver(
-      RenderFrameHostId(render_process_id, render_frame_id), observer);
+  observers_.AddObserver(render_process_id, render_frame_id, observer);
 }
 
 void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id,
                                                      int render_frame_id) {
-  frame_manager_->RemoveDelegateObserver(
-      RenderFrameHostId(render_process_id, render_frame_id));
+  observers_.RemoveObserver(render_process_id, render_frame_id);
 }
 
 bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener(
@@ -935,6 +911,22 @@
       state_changed_cb);
 }
 
+void PresentationServiceDelegateImpl::ConnectToOffscreenPresentation(
+    int render_process_id,
+    int render_frame_id,
+    const content::PresentationSessionInfo& session,
+    content::PresentationConnectionPtr controller_connection_ptr,
+    content::PresentationConnectionRequest receiver_connection_request) {
+  RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id);
+  auto* const offscreen_presentation_manager =
+      OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
+          web_contents_);
+  offscreen_presentation_manager->RegisterOffscreenPresentationController(
+      session.presentation_id, session.presentation_url, render_frame_host_id,
+      std::move(controller_connection_ptr),
+      std::move(receiver_connection_request));
+}
+
 void PresentationServiceDelegateImpl::OnRouteResponse(
     const PresentationRequest& presentation_request,
     const RouteRequestResult& result) {
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.h b/chrome/browser/media/router/presentation_service_delegate_impl.h
index bc15dd09..36b3203c 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl.h
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/media/router/media_router.h"
 #include "chrome/browser/media/router/media_source.h"
 #include "chrome/browser/media/router/presentation_request.h"
+#include "chrome/browser/media/router/presentation_service_delegate_observers.h"
 #include "chrome/browser/media/router/render_frame_host_id.h"
 #include "content/public/browser/presentation_service_delegate.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -48,7 +49,7 @@
 // and is managed by the associated WebContents.
 class PresentationServiceDelegateImpl
     : public content::WebContentsUserData<PresentationServiceDelegateImpl>,
-      public content::PresentationServiceDelegate {
+      public content::ControllerPresentationServiceDelegate {
  public:
   // Observer interface for listening to default presentation request
   // changes for the WebContents.
@@ -132,6 +133,13 @@
       const content::PresentationSessionInfo& connection,
       const content::PresentationConnectionStateChangedCallback&
           state_changed_cb) override;
+  void ConnectToOffscreenPresentation(
+      int render_process_id,
+      int render_frame_id,
+      const content::PresentationSessionInfo& session,
+      content::PresentationConnectionPtr controller_connection_ptr,
+      content::PresentationConnectionRequest receiver_connection_request)
+      override;
 
   // Callback invoked when a default PresentationRequest is started from a
   // browser-initiated dialog.
@@ -211,6 +219,7 @@
   MediaRouter* router_;
 
   std::unique_ptr<PresentationFrameManager> frame_manager_;
+  PresentationServiceDelegateObservers observers_;
 
   base::WeakPtrFactory<PresentationServiceDelegateImpl> weak_factory_;
 
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
index 10686bc..d4543441 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl_unittest.cc
@@ -9,6 +9,8 @@
 #include "chrome/browser/media/router/media_source_helper.h"
 #include "chrome/browser/media/router/mock_media_router.h"
 #include "chrome/browser/media/router/mock_screen_availability_listener.h"
+#include "chrome/browser/media/router/offscreen_presentation_manager.h"
+#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
 #include "chrome/browser/media/router/route_request_result.h"
 #include "chrome/browser/media/router/test_helper.h"
 #include "chrome/browser/profiles/profile.h"
@@ -21,6 +23,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/presentation_session.h"
 #include "content/public/test/web_contents_tester.h"
+#include "mojo/public/cpp/bindings/binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/origin.h"
 
@@ -66,6 +69,39 @@
                void(const content::PresentationError& error));
 };
 
+class MockOffscreenPresentationManager : public OffscreenPresentationManager {
+ public:
+  void RegisterOffscreenPresentationController(
+      const std::string& presentation_id,
+      const GURL& presentation_url,
+      const RenderFrameHostId& render_frame_id,
+      content::PresentationConnectionPtr controller,
+      content::PresentationConnectionRequest) override {
+    RegisterOffscreenPresentationController(presentation_id, presentation_url,
+                                            render_frame_id);
+  }
+
+  MOCK_METHOD3(RegisterOffscreenPresentationController,
+               void(const std::string& presentation_id,
+                    const GURL& presentation_url,
+                    const RenderFrameHostId& render_frame_id));
+  MOCK_METHOD2(UnregisterOffscreenPresentationController,
+               void(const std::string& presentation_id,
+                    const RenderFrameHostId& render_frame_id));
+  MOCK_METHOD3(OnOffscreenPresentationReceiverCreated,
+               void(const std::string& presentation_id,
+                    const GURL& presentation_url,
+                    const content::ReceiverConnectionAvailableCallback&
+                        receiver_callback));
+  MOCK_METHOD1(OnOffscreenPresentationReceiverTerminated,
+               void(const std::string& presentation_id));
+};
+
+std::unique_ptr<KeyedService> BuildMockOffscreenPresentationManager(
+    content::BrowserContext* context) {
+  return base::MakeUnique<MockOffscreenPresentationManager>();
+}
+
 class PresentationServiceDelegateImplTest
     : public ChromeRenderViewHostTestHarness {
  public:
@@ -449,6 +485,34 @@
       main_frame_process_id_, main_frame_routing_id_, &listener1_));
 }
 
+TEST_F(PresentationServiceDelegateImplTest, ConnectToOffscreenPresentation) {
+  content::RenderFrameHost* main_frame = GetWebContents()->GetMainFrame();
+  ASSERT_TRUE(main_frame);
+  int render_process_id = main_frame->GetProcess()->GetID();
+  int render_frame_id = main_frame->GetRoutingID();
+  std::string presentation_id = "presentation_id";
+  GURL presentation_url = GURL("http://www.example.com/presentation.html");
+  content::PresentationSessionInfo session_info(presentation_url,
+                                                presentation_id);
+
+  OffscreenPresentationManagerFactory::GetInstanceForTest()->SetTestingFactory(
+      profile(), &BuildMockOffscreenPresentationManager);
+  MockOffscreenPresentationManager* mock_offscreen_manager =
+      static_cast<MockOffscreenPresentationManager*>(
+          OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
+              profile()));
+  EXPECT_CALL(*mock_offscreen_manager,
+              RegisterOffscreenPresentationController(
+                  presentation_id, presentation_url,
+                  RenderFrameHostId(render_process_id, render_frame_id)));
+
+  content::PresentationConnectionPtr connection_ptr;
+  content::PresentationConnectionRequest connection_request;
+  delegate_impl_->ConnectToOffscreenPresentation(
+      render_process_id, render_frame_id, session_info,
+      std::move(connection_ptr), std::move(connection_request));
+}
+
 #if !defined(OS_ANDROID)
 TEST_F(PresentationServiceDelegateImplTest, AutoJoinRequest) {
   GURL frame_url(kFrameUrl);
diff --git a/chrome/browser/media/router/presentation_service_delegate_observers.cc b/chrome/browser/media/router/presentation_service_delegate_observers.cc
new file mode 100644
index 0000000..48595382
--- /dev/null
+++ b/chrome/browser/media/router/presentation_service_delegate_observers.cc
@@ -0,0 +1,31 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "chrome/browser/media/router/presentation_service_delegate_observers.h"
+
+namespace media_router {
+
+PresentationServiceDelegateObservers::PresentationServiceDelegateObservers() {}
+
+PresentationServiceDelegateObservers::~PresentationServiceDelegateObservers() {
+  for (auto& observer_pair : observers_)
+    observer_pair.second->OnDelegateDestroyed();
+}
+
+void PresentationServiceDelegateObservers::AddObserver(
+    int render_process_id,
+    int render_frame_id,
+    content::PresentationServiceDelegate::Observer* observer) {
+  DCHECK(observer);
+
+  RenderFrameHostId rfh_id(render_process_id, render_frame_id);
+  DCHECK(!base::ContainsKey(observers_, rfh_id));
+  observers_[rfh_id] = observer;
+}
+
+void PresentationServiceDelegateObservers::RemoveObserver(int render_process_id,
+                                                          int render_frame_id) {
+  observers_.erase(RenderFrameHostId(render_process_id, render_frame_id));
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/presentation_service_delegate_observers.h b/chrome/browser/media/router/presentation_service_delegate_observers.h
new file mode 100644
index 0000000..2783d2b0
--- /dev/null
+++ b/chrome/browser/media/router/presentation_service_delegate_observers.h
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_SERVICE_DELEGATE_OBSERVERS_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_SERVICE_DELEGATE_OBSERVERS_H_
+
+#include <map>
+
+#include "chrome/browser/media/router/render_frame_host_id.h"
+#include "content/public/browser/presentation_service_delegate.h"
+
+namespace media_router {
+
+class PresentationServiceDelegateObservers {
+ public:
+  PresentationServiceDelegateObservers();
+  virtual ~PresentationServiceDelegateObservers();
+
+  // Registers an observer associated with frame with |render_process_id|
+  // and |render_frame_id| with this class to listen for updates.
+  // This class does not own the observer.
+  // It is an error to add an observer if there is already an observer for that
+  // frame.
+  virtual void AddObserver(
+      int render_process_id,
+      int render_frame_id,
+      content::PresentationServiceDelegate::Observer* observer);
+
+  // Unregisters the observer associated with the frame with |render_process_id|
+  // and |render_frame_id|.
+  // The observer will no longer receive updates.
+  virtual void RemoveObserver(int render_process_id, int render_frame_id);
+
+ private:
+  std::map<RenderFrameHostId, content::PresentationServiceDelegate::Observer*>
+      observers_;
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_SERVICE_DELEGATE_OBSERVERS_H_
diff --git a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc
new file mode 100644
index 0000000..6b964e1
--- /dev/null
+++ b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc
@@ -0,0 +1,74 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/router/receiver_presentation_service_delegate_impl.h"
+
+#include "chrome/browser/media/router/offscreen_presentation_manager.h"
+#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+    media_router::ReceiverPresentationServiceDelegateImpl);
+
+using content::RenderFrameHost;
+
+namespace media_router {
+
+// static
+void ReceiverPresentationServiceDelegateImpl::CreateForWebContents(
+    content::WebContents* web_contents,
+    const std::string& presentation_id) {
+  DCHECK(web_contents);
+
+  if (FromWebContents(web_contents))
+    return;
+
+  web_contents->SetUserData(UserDataKey(),
+                            new ReceiverPresentationServiceDelegateImpl(
+                                web_contents, presentation_id));
+}
+
+void ReceiverPresentationServiceDelegateImpl::AddObserver(
+    int render_process_id,
+    int render_frame_id,
+    content::PresentationServiceDelegate::Observer* observer) {
+  DCHECK(observer);
+  observers_.AddObserver(render_process_id, render_frame_id, observer);
+}
+
+void ReceiverPresentationServiceDelegateImpl::RemoveObserver(
+    int render_process_id,
+    int render_frame_id) {
+  observers_.RemoveObserver(render_process_id, render_frame_id);
+}
+
+void ReceiverPresentationServiceDelegateImpl::Reset(int render_process_id,
+                                                    int render_frame_id) {
+  DVLOG(2) << __FUNCTION__ << render_process_id << ", " << render_frame_id;
+  offscreen_presentation_manager_->OnOffscreenPresentationReceiverTerminated(
+      presentation_id_);
+}
+
+ReceiverPresentationServiceDelegateImpl::
+    ReceiverPresentationServiceDelegateImpl(content::WebContents* web_contents,
+                                            const std::string& presentation_id)
+    : web_contents_(web_contents),
+      presentation_id_(presentation_id),
+      offscreen_presentation_manager_(
+          OffscreenPresentationManagerFactory::GetOrCreateForWebContents(
+              web_contents_)) {
+  DCHECK(web_contents_);
+  DCHECK(!presentation_id.empty());
+  DCHECK(offscreen_presentation_manager_);
+}
+
+void ReceiverPresentationServiceDelegateImpl::
+    RegisterReceiverConnectionAvailableCallback(
+        const content::ReceiverConnectionAvailableCallback&
+            receiver_available_callback) {
+  offscreen_presentation_manager_->OnOffscreenPresentationReceiverCreated(
+      presentation_id_, web_contents_->GetLastCommittedURL(),
+      receiver_available_callback);
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.h b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.h
new file mode 100644
index 0000000..5985fd3
--- /dev/null
+++ b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.h
@@ -0,0 +1,76 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_ROUTER_RECEIVER_PRESENTATION_SERVICE_DELEGATE_IMPL_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_RECEIVER_PRESENTATION_SERVICE_DELEGATE_IMPL_H_
+
+#include <string>
+
+#include "chrome/browser/media/router/presentation_service_delegate_observers.h"
+#include "content/public/browser/presentation_service_delegate.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+namespace media_router {
+
+class OffscreenPresentationManager;
+
+// Implements the receiver side of Presentation API for offscreen presentation.
+// Created with offscreen WebContents for an offscreen presentation. Each
+// instance is tied to a single offscreen presentation whose ID is given during
+// construction. As such, the receiver APIs are contextual with the offscreen
+// presentation. Only the main frame of the offscreen WebContents is allowed to
+// make receiver Presentation API requests; requests made from any other frame
+// will be rejected.
+class ReceiverPresentationServiceDelegateImpl
+    : public content::WebContentsUserData<
+          ReceiverPresentationServiceDelegateImpl>,
+      public content::ReceiverPresentationServiceDelegate {
+ public:
+  // Creates an instance of ReceiverPresentationServiceDelegateImpl under
+  // |web_contents| and registers it as the receiver of the offscreen
+  // presentation |presentation_id| with OffscreenPresentationManager.
+  // No-op if a ReceiverPresentationServiceDelegateImpl instance already
+  // exists under |web_contents|. This class does not take ownership of
+  // |web_contents|.
+  static void CreateForWebContents(content::WebContents* web_contents,
+                                   const std::string& presentation_id);
+
+  // content::ReceiverPresentationServiceDelegate implementation.
+  void AddObserver(
+      int render_process_id,
+      int render_frame_id,
+      content::PresentationServiceDelegate::Observer* observer) override;
+  void RemoveObserver(int render_process_id, int render_frame_id) override;
+  void Reset(int render_process_id, int render_frame_id) override;
+  void RegisterReceiverConnectionAvailableCallback(
+      const content::ReceiverConnectionAvailableCallback&
+          receiver_available_callback) override;
+
+ private:
+  friend class content::WebContentsUserData<
+      ReceiverPresentationServiceDelegateImpl>;
+
+  ReceiverPresentationServiceDelegateImpl(content::WebContents* web_contents,
+                                          const std::string& presentation_id);
+
+  // Reference to the WebContents that owns this instance.
+  content::WebContents* const web_contents_;
+
+  const std::string presentation_id_;
+
+  // This is an unowned pointer to the OffscreenPresentationManager.
+  OffscreenPresentationManager* const offscreen_presentation_manager_;
+
+  PresentationServiceDelegateObservers observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(ReceiverPresentationServiceDelegateImpl);
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_RECEIVER_PRESENTATION_SERVICE_DELEGATE_IMPL_H_
diff --git a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
index c152a273..8ffe884d 100644
--- a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
+++ b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
@@ -18,10 +18,12 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/test_launcher_utils.h"
 #include "components/prefs/pref_service.h"
 #include "components/sessions/core/serialized_navigation_entry_test_helper.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
+#include "ui/wm/core/wm_core_switches.h"
 
 namespace {
 const char* test_app_popup_name1 = "TestApp1";
@@ -33,8 +35,16 @@
   ~SessionRestoreTestChromeOS() override {}
 
  protected:
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    InProcessBrowserTest::SetUpCommandLine(command_line);
+  void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
+    base::CommandLine default_command_line(base::CommandLine::NO_PROGRAM);
+    InProcessBrowserTest::SetUpDefaultCommandLine(&default_command_line);
+
+    // Animations have caused crashes in session restore in the past but are
+    // usually disabled in tests. Remove --wm-window-animations-disabled to
+    // re-enable animations.
+    test_launcher_utils::RemoveCommandLineSwitch(
+        default_command_line, wm::switches::kWindowAnimationsDisabled,
+        command_line);
   }
 
   Browser* CreateBrowserWithParams(Browser::CreateParams params) {
@@ -161,3 +171,33 @@
   EXPECT_EQ(4u, total_count);
   EXPECT_EQ(2u, maximized_count);
 }
+
+// Test for crash when restoring minimized windows. http://crbug.com/679513.
+IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_RestoreMinimized) {
+  // One browser window is always created by default.
+  ASSERT_TRUE(browser());
+  browser()->window()->Minimize();
+
+  Browser* browser2 = CreateBrowserWithParams(Browser::CreateParams(profile()));
+  browser2->window()->Minimize();
+
+  EXPECT_TRUE(browser()->window()->IsMinimized());
+  EXPECT_TRUE(browser2->window()->IsMinimized());
+
+  TurnOnSessionRestore();
+}
+
+IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, RestoreMinimized) {
+  size_t total_count = 0;
+  size_t minimized_count = 0;
+  for (auto* browser : *BrowserList::GetInstance()) {
+    ++total_count;
+    if (browser->window()->IsMinimized())
+      ++minimized_count;
+  }
+  EXPECT_EQ(2u, total_count);
+  // Chrome OS always activates the last browser window on login, which results
+  // in one window being restored. This seems reasonable as it reminds users
+  // they have a browser running instead of just showing them an empty desktop.
+  EXPECT_EQ(1u, minimized_count);
+}
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc
index 1805ff7a..383874b 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -565,7 +565,6 @@
       // chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED instead.
       if (shelf_delegate_)
         shelf_delegate_->OnUserProfileReadyToSwitch(profile);
-      ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
       break;
     }
     case chrome::NOTIFICATION_SESSION_STARTED:
@@ -573,7 +572,6 @@
       // start.
       if (user_manager::UserManager::Get()->GetLoggedInUsers().size() < 2)
         InitAfterFirstSessionStart();
-      ash::WmShell::Get()->ShowShelf();
       break;
     default:
       NOTREACHED() << "Unexpected notification " << type;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
index efb63e6..4553737d 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
@@ -42,6 +42,7 @@
 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
+#include "chrome/browser/ui/ash/session_controller_client.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -192,7 +193,11 @@
   ~LauncherPlatformAppBrowserTest() override {}
 
   void RunTestOnMainThreadLoop() override {
+    // Ensure ash starts the session and creates the shelf and controller.
+    SessionControllerClient::FlushForTesting();
+
     controller_ = GetChromeLauncherControllerImpl();
+    ASSERT_TRUE(controller_);
     return extensions::PlatformAppBrowserTest::RunTestOnMainThreadLoop();
   }
 
@@ -259,10 +264,14 @@
   ~ShelfAppBrowserTest() override {}
 
   void RunTestOnMainThreadLoop() override {
+    // Ensure ash starts the session and creates the shelf and controller.
+    SessionControllerClient::FlushForTesting();
+
     shelf_ =
         ash::WmShelf::ForWindow(ash::WmShell::Get()->GetPrimaryRootWindow());
     model_ = ash::WmShell::Get()->shelf_model();
     controller_ = GetChromeLauncherControllerImpl();
+    ASSERT_TRUE(controller_);
     return ExtensionBrowserTest::RunTestOnMainThreadLoop();
   }
 
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc
index e7d4d41f..b197390 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.cc
@@ -10,6 +10,10 @@
 
 namespace chrome {
 
+MultiUserWindowManagerStub::MultiUserWindowManagerStub() {}
+
+MultiUserWindowManagerStub::~MultiUserWindowManagerStub() {}
+
 void MultiUserWindowManagerStub::SetWindowOwner(aura::Window* window,
                                                 const AccountId& account_id) {
   NOTIMPLEMENTED();
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h
index f7e1be3b..a6153f55 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_stub.h
@@ -19,8 +19,8 @@
 // This is the implementation of MultiUserWindowManager for single user mode.
 class MultiUserWindowManagerStub : public MultiUserWindowManager {
  public:
-  MultiUserWindowManagerStub() {}
-  ~MultiUserWindowManagerStub() override {}
+  MultiUserWindowManagerStub();
+  ~MultiUserWindowManagerStub() override;
 
   // MultiUserWindowManager overrides:
   void SetWindowOwner(aura::Window* window,
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc
index b171cf2f..fad60d4 100644
--- a/chrome/browser/ui/ash/session_controller_client.cc
+++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -34,6 +34,8 @@
 
 namespace {
 
+SessionControllerClient* g_instance = nullptr;
+
 uint32_t GetSessionId(const User* user) {
   const UserList logged_in_users = UserManager::Get()->GetLoggedInUsers();
   // TODO(xiyuan): Update with real session id when user session tracking
@@ -83,9 +85,15 @@
   SendSessionInfoIfChanged();
   // User sessions and their order will be sent via UserSessionStateObserver
   // even for crash-n-restart.
+
+  DCHECK(!g_instance);
+  g_instance = this;
 }
 
 SessionControllerClient::~SessionControllerClient() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+
   SessionManager::Get()->RemoveObserver(this);
   UserManager::Get()->RemoveSessionStateObserver(this);
 }
@@ -225,6 +233,11 @@
   DoSwitchActiveUser(account_id);
 }
 
+// static
+void SessionControllerClient::FlushForTesting() {
+  g_instance->session_controller_.FlushForTesting();
+}
+
 void SessionControllerClient::OnSessionStateChanged() {
   SendSessionInfoIfChanged();
 }
diff --git a/chrome/browser/ui/ash/session_controller_client.h b/chrome/browser/ui/ash/session_controller_client.h
index d97bc6b..c2d22c9 100644
--- a/chrome/browser/ui/ash/session_controller_client.h
+++ b/chrome/browser/ui/ash/session_controller_client.h
@@ -50,6 +50,9 @@
   static void DoSwitchActiveUser(const AccountId& account_id);
   static void DoCycleActiveUser(bool next_user);
 
+  // Flushes the mojo pipe to ash.
+  static void FlushForTesting();
+
  private:
   // Connects or reconnects to the |session_controller_| interface and set
   // this object as its client.
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc
index 8fbaf0a..21ae18e 100644
--- a/chrome/browser/ui/browser_browsertest.cc
+++ b/chrome/browser/ui/browser_browsertest.cc
@@ -2562,6 +2562,13 @@
 }
 
 IN_PROC_BROWSER_TEST_F(BrowserTest, GetSizeForNewRenderView) {
+  // Force an initial resize. This works around a test-only problem on Chrome OS
+  // where the shelf may not be created before the initial test browser window
+  // opens, which leads to sizing issues in WebContents resize.
+  browser()->window()->SetBounds(gfx::Rect(10, 20, 600, 400));
+  // Let the message loop run so that resize actually takes effect.
+  content::RunAllPendingInMessageLoop();
+
   // The instant extended NTP has javascript that does not work with
   // ui_test_utils::NavigateToURL.  The NTP rvh reloads when the browser tries
   // to navigate away from the page, which causes the WebContents to end up in
@@ -2685,6 +2692,7 @@
 #endif
   EXPECT_EQ(exp_commit_size, rwhv_commit_size2);
   EXPECT_EQ(exp_commit_size, wcv_commit_size2);
+
   gfx::Size exp_final_size(initial_wcv_size);
   exp_final_size.Enlarge(wcv_resize_insets.width(),
                          wcv_resize_insets.height() + height_inset);
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
index ddb0dba..b015a05 100644
--- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
@@ -6,11 +6,7 @@
 
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
-#include "base/command_line.h"
-#include "base/lazy_instance.h"
-#include "base/macros.h"
 #include "base/memory/ptr_util.h"
-#include "build/build_config.h"
 #include "chrome/browser/chrome_browser_main.h"
 #include "chrome/browser/ui/ash/ash_init.h"
 #include "chrome/browser/ui/ash/ash_util.h"
@@ -19,25 +15,20 @@
 #include "chrome/browser/ui/ash/chrome_shell_content_state.h"
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_mus.h"
 #include "chrome/browser/ui/ash/media_client.h"
-#include "chrome/browser/ui/views/ash/tab_scrubber.h"
-#include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h"
-#include "chrome/browser/ui/views/frame/immersive_context_mus.h"
-#include "chrome/browser/ui/views/frame/immersive_handler_factory_mus.h"
-#include "chrome/common/chrome_switches.h"
-#include "ui/aura/env.h"
-#include "ui/keyboard/content/keyboard.h"
-#include "ui/keyboard/keyboard_controller.h"
-#include "ui/wm/core/capture_controller.h"
-#include "ui/wm/core/wm_state.h"
-
-#if defined(OS_CHROMEOS)
 #include "chrome/browser/ui/ash/session_controller_client.h"
 #include "chrome/browser/ui/ash/system_tray_client.h"
 #include "chrome/browser/ui/ash/volume_controller.h"
 #include "chrome/browser/ui/ash/vpn_list_forwarder.h"
+#include "chrome/browser/ui/views/ash/tab_scrubber.h"
+#include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h"
+#include "chrome/browser/ui/views/frame/immersive_context_mus.h"
+#include "chrome/browser/ui/views/frame/immersive_handler_factory_mus.h"
 #include "chrome/browser/ui/views/select_file_dialog_extension.h"
 #include "chrome/browser/ui/views/select_file_dialog_extension_factory.h"
-#endif  // defined(OS_CHROMEOS)
+#include "ui/keyboard/content/keyboard.h"
+#include "ui/keyboard/keyboard_controller.h"
+#include "ui/wm/core/capture_controller.h"
+#include "ui/wm/core/wm_state.h"
 
 ChromeBrowserMainExtraPartsAsh::ChromeBrowserMainExtraPartsAsh(
     ChromeBrowserMainExtraPartsViews* extra_parts_views)
@@ -55,10 +46,7 @@
     immersive_handler_factory_ = base::MakeUnique<ImmersiveHandlerFactoryMus>();
   }
 
-#if defined(OS_CHROMEOS)
-  // TODO(xiyuan): Update after SesssionStateDelegate is deprecated.
-  if (chrome::IsRunningInMash())
-    session_controller_client_ = base::MakeUnique<SessionControllerClient>();
+  session_controller_client_ = base::MakeUnique<SessionControllerClient>();
 
   // Must be available at login screen, so initialize before profile.
   system_tray_client_ = base::MakeUnique<SystemTrayClient>();
@@ -72,7 +60,6 @@
   keyboard::InitializeKeyboard();
 
   ui::SelectFileDialog::SetFactory(new SelectFileDialogExtensionFactory);
-#endif  // defined(OS_CHROMEOS)
 }
 
 void ChromeBrowserMainExtraPartsAsh::PostProfileInit() {
@@ -101,7 +88,6 @@
 }
 
 void ChromeBrowserMainExtraPartsAsh::PostMainMessageLoopRun() {
-#if defined(OS_CHROMEOS)
   vpn_list_forwarder_.reset();
   volume_controller_.reset();
   new_window_client_.reset();
@@ -109,6 +95,6 @@
   media_client_.reset();
   cast_config_client_media_router_.reset();
   session_controller_client_.reset();
-#endif
+
   chrome::CloseAsh();
 }
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
index 9cf426a..36c6bab6 100644
--- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
+++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h
@@ -23,6 +23,8 @@
 class VolumeController;
 class VpnListForwarder;
 
+// Browser initialization for Ash. Only runs on Chrome OS.
+// TODO(jamescook): Fold this into ChromeBrowserMainPartsChromeOS.
 class ChromeBrowserMainExtraPartsAsh : public ChromeBrowserMainExtraParts {
  public:
   explicit ChromeBrowserMainExtraPartsAsh(
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc
index 1f9609d..9d870e3a 100644
--- a/content/browser/presentation/presentation_service_impl.cc
+++ b/content/browser/presentation/presentation_service_impl.cc
@@ -117,9 +117,11 @@
 PresentationServiceImpl::PresentationServiceImpl(
     RenderFrameHost* render_frame_host,
     WebContents* web_contents,
-    PresentationServiceDelegate* delegate)
+    ControllerPresentationServiceDelegate* controller_delegate,
+    ReceiverPresentationServiceDelegate* receiver_delegate)
     : WebContentsObserver(web_contents),
-      delegate_(delegate),
+      controller_delegate_(controller_delegate),
+      receiver_delegate_(receiver_delegate),
       start_session_request_id_(kInvalidRequestSessionId),
       weak_factory_(this) {
   DCHECK(render_frame_host);
@@ -130,13 +132,17 @@
   render_frame_id_ = render_frame_host->GetRoutingID();
   DVLOG(2) << "PresentationServiceImpl: "
            << render_process_id_ << ", " << render_frame_id_;
-  if (delegate_)
-    delegate_->AddObserver(render_process_id_, render_frame_id_, this);
+
+  if (auto* delegate = GetPresentationServiceDelegate())
+    delegate->AddObserver(render_process_id_, render_frame_id_, this);
 }
 
 PresentationServiceImpl::~PresentationServiceImpl() {
-  if (delegate_)
-    delegate_->RemoveObserver(render_process_id_, render_frame_id_);
+  DVLOG(2) << __FUNCTION__ << ": " << render_process_id_ << ", "
+           << render_frame_id_;
+
+  if (auto* delegate = GetPresentationServiceDelegate())
+    delegate->RemoveObserver(render_process_id_, render_frame_id_);
 }
 
 // static
@@ -148,13 +154,21 @@
       WebContents::FromRenderFrameHost(render_frame_host);
   DCHECK(web_contents);
 
+  auto* browser = GetContentClient()->browser();
+  auto* receiver_delegate =
+      browser->GetReceiverPresentationServiceDelegate(web_contents);
+
+  // In current implementation, web_contents can be controller or receiver
+  // but not both.
+  auto* controller_delegate =
+      receiver_delegate
+          ? nullptr
+          : browser->GetControllerPresentationServiceDelegate(web_contents);
+
   // This object will be deleted when the RenderFrameHost is about to be
   // deleted (RenderFrameDeleted).
   PresentationServiceImpl* impl = new PresentationServiceImpl(
-      render_frame_host,
-      web_contents,
-      GetContentClient()->browser()->GetPresentationServiceDelegate(
-          web_contents));
+      render_frame_host, web_contents, controller_delegate, receiver_delegate);
   impl->Bind(std::move(request));
 }
 
@@ -169,11 +183,17 @@
   DCHECK(!client_.get());
   // TODO(imcheng): Set ErrorHandler to listen for errors.
   client_ = std::move(client);
+
+  if (receiver_delegate_) {
+    receiver_delegate_->RegisterReceiverConnectionAvailableCallback(
+        base::Bind(&PresentationServiceImpl::OnReceiverConnectionAvailable,
+                   weak_factory_.GetWeakPtr()));
+  }
 }
 
 void PresentationServiceImpl::ListenForScreenAvailability(const GURL& url) {
   DVLOG(2) << "ListenForScreenAvailability " << url.spec();
-  if (!delegate_) {
+  if (!controller_delegate_) {
     client_->OnScreenAvailabilityUpdated(url, false);
     return;
   }
@@ -183,10 +203,8 @@
 
   std::unique_ptr<ScreenAvailabilityListenerImpl> listener(
       new ScreenAvailabilityListenerImpl(url, this));
-  if (delegate_->AddScreenAvailabilityListener(
-      render_process_id_,
-      render_frame_id_,
-      listener.get())) {
+  if (controller_delegate_->AddScreenAvailabilityListener(
+          render_process_id_, render_frame_id_, listener.get())) {
     screen_availability_listeners_[url] = std::move(listener);
   } else {
     DVLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request.";
@@ -196,14 +214,14 @@
 void PresentationServiceImpl::StopListeningForScreenAvailability(
     const GURL& url) {
   DVLOG(2) << "StopListeningForScreenAvailability " << url.spec();
-  if (!delegate_)
+  if (!controller_delegate_)
     return;
 
   auto listener_it = screen_availability_listeners_.find(url);
   if (listener_it == screen_availability_listeners_.end())
     return;
 
-  delegate_->RemoveScreenAvailabilityListener(
+  controller_delegate_->RemoveScreenAvailabilityListener(
       render_process_id_, render_frame_id_, listener_it->second.get());
   screen_availability_listeners_.erase(listener_it);
 }
@@ -212,7 +230,7 @@
     const std::vector<GURL>& presentation_urls,
     const NewSessionCallback& callback) {
   DVLOG(2) << "StartSession";
-  if (!delegate_) {
+  if (!controller_delegate_) {
     callback.Run(
         blink::mojom::PresentationSessionInfoPtr(),
         blink::mojom::PresentationError::From(PresentationError(
@@ -229,7 +247,7 @@
 
   start_session_request_id_ = GetNextRequestSessionId();
   pending_start_session_cb_.reset(new NewSessionCallbackWrapper(callback));
-  delegate_->StartSession(
+  controller_delegate_->StartSession(
       render_process_id_, render_frame_id_, presentation_urls,
       base::Bind(&PresentationServiceImpl::OnStartSessionSucceeded,
                  weak_factory_.GetWeakPtr(), start_session_request_id_),
@@ -242,7 +260,7 @@
     const base::Optional<std::string>& presentation_id,
     const NewSessionCallback& callback) {
   DVLOG(2) << "JoinSession";
-  if (!delegate_) {
+  if (!controller_delegate_) {
     callback.Run(blink::mojom::PresentationSessionInfoPtr(),
                  blink::mojom::PresentationError::From(PresentationError(
                      PRESENTATION_ERROR_NO_PRESENTATION_FOUND,
@@ -255,7 +273,7 @@
     InvokeNewSessionCallbackWithError(callback);
     return;
   }
-  delegate_->JoinSession(
+  controller_delegate_->JoinSession(
       render_process_id_, render_frame_id_, presentation_urls,
       presentation_id.value_or(std::string()),
       base::Bind(&PresentationServiceImpl::OnJoinSessionSucceeded,
@@ -277,8 +295,8 @@
 
 void PresentationServiceImpl::ListenForConnectionStateChangeAndChangeState(
     const PresentationSessionInfo& connection) {
-  if (delegate_) {
-    delegate_->ListenForConnectionStateChange(
+  if (controller_delegate_) {
+    controller_delegate_->ListenForConnectionStateChange(
         render_process_id_, render_frame_id_, connection,
         base::Bind(&PresentationServiceImpl::OnConnectionStateChanged,
                    weak_factory_.GetWeakPtr(), connection));
@@ -352,14 +370,14 @@
 void PresentationServiceImpl::SetDefaultPresentationUrls(
     const std::vector<GURL>& presentation_urls) {
   DVLOG(2) << "SetDefaultPresentationUrls";
-  if (!delegate_)
+  if (!controller_delegate_)
     return;
 
   if (default_presentation_urls_ == presentation_urls)
     return;
 
   default_presentation_urls_ = presentation_urls;
-  delegate_->SetDefaultPresentationUrls(
+  controller_delegate_->SetDefaultPresentationUrls(
       render_process_id_, render_frame_id_, presentation_urls,
       base::Bind(&PresentationServiceImpl::OnDefaultPresentationStarted,
                  weak_factory_.GetWeakPtr()));
@@ -369,17 +387,18 @@
     blink::mojom::PresentationSessionInfoPtr session,
     blink::mojom::ConnectionMessagePtr connection_message,
     const SendConnectionMessageCallback& callback) {
-  DVLOG(2) << "SendConnectionMessage";
+  DVLOG(2) << "SendConnectionMessage"
+           << " [id]: " << session->id;
   DCHECK(!connection_message.is_null());
   // send_message_callback_ should be null by now, otherwise resetting of
   // send_message_callback_ with new callback will drop the old callback.
-  if (!delegate_ || send_message_callback_) {
+  if (!controller_delegate_ || send_message_callback_) {
     callback.Run(false);
     return;
   }
 
   send_message_callback_.reset(new SendConnectionMessageCallback(callback));
-  delegate_->SendMessage(
+  controller_delegate_->SendMessage(
       render_process_id_, render_frame_id_,
       session.To<PresentationSessionInfo>(),
       GetPresentationConnectionMessage(std::move(connection_message)),
@@ -400,16 +419,17 @@
     const GURL& presentation_url,
     const std::string& presentation_id) {
   DVLOG(2) << "CloseConnection " << presentation_id;
-  if (delegate_)
-    delegate_->CloseConnection(render_process_id_, render_frame_id_,
-                               presentation_id);
+  if (controller_delegate_)
+    controller_delegate_->CloseConnection(render_process_id_, render_frame_id_,
+                                          presentation_id);
 }
 
 void PresentationServiceImpl::Terminate(const GURL& presentation_url,
                                         const std::string& presentation_id) {
   DVLOG(2) << "Terminate " << presentation_id;
-  if (delegate_)
-    delegate_->Terminate(render_process_id_, render_frame_id_, presentation_id);
+  if (controller_delegate_)
+    controller_delegate_->Terminate(render_process_id_, render_frame_id_,
+                                    presentation_id);
 }
 
 void PresentationServiceImpl::OnConnectionStateChanged(
@@ -440,26 +460,50 @@
          render_frame_host->GetRoutingID() == render_frame_id_;
 }
 
+PresentationServiceDelegate*
+PresentationServiceImpl::GetPresentationServiceDelegate() {
+  return receiver_delegate_
+             ? static_cast<PresentationServiceDelegate*>(receiver_delegate_)
+             : static_cast<PresentationServiceDelegate*>(controller_delegate_);
+}
+
 void PresentationServiceImpl::ListenForConnectionMessages(
     blink::mojom::PresentationSessionInfoPtr session) {
   DVLOG(2) << "ListenForConnectionMessages";
-  if (!delegate_)
+  if (!controller_delegate_)
     return;
 
   PresentationSessionInfo session_info(session.To<PresentationSessionInfo>());
-  delegate_->ListenForConnectionMessages(
+  controller_delegate_->ListenForConnectionMessages(
       render_process_id_, render_frame_id_, session_info,
       base::Bind(&PresentationServiceImpl::OnConnectionMessages,
                  weak_factory_.GetWeakPtr(), session_info));
 }
 
+void PresentationServiceImpl::SetPresentationConnection(
+    blink::mojom::PresentationSessionInfoPtr session,
+    blink::mojom::PresentationConnectionPtr controller_connection_ptr,
+    blink::mojom::PresentationConnectionRequest receiver_connection_request) {
+  DVLOG(2) << "SetPresentationConnection";
+
+  if (!controller_delegate_)
+    return;
+
+  PresentationSessionInfo session_info(session.To<PresentationSessionInfo>());
+  controller_delegate_->ConnectToOffscreenPresentation(
+      render_process_id_, render_frame_id_, session_info,
+      std::move(controller_connection_ptr),
+      std::move(receiver_connection_request));
+}
+
 void PresentationServiceImpl::OnConnectionMessages(
     const PresentationSessionInfo& session,
     const std::vector<std::unique_ptr<PresentationConnectionMessage>>& messages,
     bool pass_ownership) {
   DCHECK(client_);
 
-  DVLOG(2) << "OnConnectionMessages";
+  DVLOG(2) << "OnConnectionMessages"
+           << " [id]: " << session.presentation_id;
   std::vector<blink::mojom::ConnectionMessagePtr> mojo_messages(
       messages.size());
   std::transform(
@@ -474,6 +518,18 @@
       std::move(mojo_messages));
 }
 
+void PresentationServiceImpl::OnReceiverConnectionAvailable(
+    const content::PresentationSessionInfo& session_info,
+    PresentationConnectionPtr controller_connection_ptr,
+    PresentationConnectionRequest receiver_connection_request) {
+  DVLOG(2) << "PresentationServiceImpl::OnReceiverConnectionAvailable";
+
+  client_->OnReceiverConnectionAvailable(
+      blink::mojom::PresentationSessionInfo::From(session_info),
+      std::move(controller_connection_ptr),
+      std::move(receiver_connection_request));
+}
+
 void PresentationServiceImpl::DidNavigateAnyFrame(
     content::RenderFrameHost* render_frame_host,
     const content::LoadCommittedDetails& details,
@@ -519,8 +575,9 @@
 
 void PresentationServiceImpl::Reset() {
   DVLOG(2) << "PresentationServiceImpl::Reset";
-  if (delegate_)
-    delegate_->Reset(render_process_id_, render_frame_id_);
+
+  if (auto* delegate = GetPresentationServiceDelegate())
+    delegate->Reset(render_process_id_, render_frame_id_);
 
   default_presentation_urls_.clear();
 
@@ -547,7 +604,8 @@
 
 void PresentationServiceImpl::OnDelegateDestroyed() {
   DVLOG(2) << "PresentationServiceImpl::OnDelegateDestroyed";
-  delegate_ = nullptr;
+  controller_delegate_ = nullptr;
+  receiver_delegate_ = nullptr;
   Reset();
 }
 
diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h
index 0525315..0868dda 100644
--- a/content/browser/presentation/presentation_service_impl.h
+++ b/content/browser/presentation/presentation_service_impl.h
@@ -95,6 +95,10 @@
                            ListenForConnectionStateChangeAndChangeState);
   FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
                            ListenForConnectionClose);
+  FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
+                           SetPresentationConnection);
+  FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
+                           ReceiverPresentationServiceDelegate);
 
   // Maximum number of pending JoinSession requests at any given time.
   static const int kMaxNumQueuedSessionRequests = 10;
@@ -143,12 +147,17 @@
 
   // |render_frame_host|: The RFH this instance is associated with.
   // |web_contents|: The WebContents to observe.
-  // |delegate|: Where Presentation API requests are delegated to. Not owned
-  // by this class.
+  // |controller_delegate|: Where Presentation API requests are delegated to in
+  // controller frame. Set to nullptr if current frame is receiver frame. Not
+  // owned by this class.
+  // |receiver_delegate|: Where Presentation API requests are delegated to in
+  // receiver frame. Set to nullptr if current frame is controller frame. Not
+  // owned by this class.
   PresentationServiceImpl(
       RenderFrameHost* render_frame_host,
       WebContents* web_contents,
-      PresentationServiceDelegate* delegate);
+      ControllerPresentationServiceDelegate* controller_delegate,
+      ReceiverPresentationServiceDelegate* receiver_delegate);
 
   // PresentationService implementation.
   void SetDefaultPresentationUrls(
@@ -171,6 +180,11 @@
                  const std::string& presentation_id) override;
   void ListenForConnectionMessages(
       blink::mojom::PresentationSessionInfoPtr session) override;
+  void SetPresentationConnection(
+      blink::mojom::PresentationSessionInfoPtr session,
+      blink::mojom::PresentationConnectionPtr controller_connection_ptr,
+      blink::mojom::PresentationConnectionRequest receiver_connection_request)
+      override;
 
   // Creates a binding between this object and |request|.
   void Bind(mojo::InterfaceRequest<blink::mojom::PresentationService> request);
@@ -236,6 +250,14 @@
           messages,
       bool pass_ownership);
 
+  // A callback registered to OffscreenPresentationManager when
+  // the PresentationServiceImpl for the presentation receiver is initialized.
+  // Calls |client_| to create a new PresentationConnection on receiver page.
+  void OnReceiverConnectionAvailable(
+      const content::PresentationSessionInfo& session_info,
+      PresentationConnectionPtr controller_connection_ptr,
+      PresentationConnectionRequest receiver_connection_request);
+
   // Associates a JoinSession |callback| with a unique request ID and
   // stores it in a map.
   // Returns a positive value on success.
@@ -250,9 +272,19 @@
   // Returns true if this object is associated with |render_frame_host|.
   bool FrameMatches(content::RenderFrameHost* render_frame_host) const;
 
-  // Embedder-specific delegate to forward Presentation requests to.
-  // May be null if embedder does not support Presentation API.
-  PresentationServiceDelegate* delegate_;
+  // Returns |controller_delegate| if current frame is controller frame; Returns
+  // |receiver_delegate| if current frame is receiver frame.
+  PresentationServiceDelegate* GetPresentationServiceDelegate();
+
+  // Embedder-specific delegate for controller to forward Presentation requests
+  // to. Must be nullptr if current page is receiver page or
+  // embedder does not support Presentation API .
+  ControllerPresentationServiceDelegate* controller_delegate_;
+
+  // Embedder-specific delegate for receiver to forward Presentation requests
+  // to. Must be nullptr if current page is receiver page or
+  // embedder does not support Presentation API.
+  ReceiverPresentationServiceDelegate* receiver_delegate_;
 
   // Proxy to the PresentationServiceClient to send results (e.g., screen
   // availability) to.
diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc
index fbe3bb7..e0028b7 100644
--- a/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -43,12 +43,19 @@
   return expected.Equals(arg);
 }
 
-// Matches PresentationSessionInfo passed by reference.
+// Matches blink::mojom::PresentationSessionInfo passed by reference.
 MATCHER_P(SessionInfoEquals, expected, "") {
   blink::mojom::PresentationSessionInfo& expected_value = expected;
   return expected_value.Equals(arg);
 }
 
+// Matches content::PresentationSessionInfo passed by reference.
+MATCHER_P(ContentSessionInfoEquals, expected, "") {
+  const content::PresentationSessionInfo& expected_value = expected;
+  return expected_value.presentation_url == arg.presentation_url &&
+         expected_value.presentation_id == arg.presentation_id;
+}
+
 const char kPresentationId[] = "presentationId";
 const char kPresentationUrl1[] = "http://foo.com/index.html";
 const char kPresentationUrl2[] = "http://example.com/index.html";
@@ -59,12 +66,13 @@
 
 }  // namespace
 
-class MockPresentationServiceDelegate : public PresentationServiceDelegate {
+class MockPresentationServiceDelegate
+    : public ControllerPresentationServiceDelegate {
  public:
   MOCK_METHOD3(AddObserver,
-      void(int render_process_id,
-           int render_frame_id,
-           PresentationServiceDelegate::Observer* observer));
+               void(int render_process_id,
+                    int render_frame_id,
+                    PresentationServiceDelegate::Observer* observer));
   MOCK_METHOD2(RemoveObserver,
       void(int render_process_id, int render_frame_id));
 
@@ -139,6 +147,22 @@
                     const content::PresentationConnectionStateChangedCallback&
                         state_changed_cb));
 
+  void ConnectToOffscreenPresentation(
+      int render_process_id,
+      int render_frame_id,
+      const content::PresentationSessionInfo& session,
+      PresentationConnectionPtr controller_conn_ptr,
+      PresentationConnectionRequest receiver_conn_request) override {
+    RegisterOffscreenPresentationConnectionRaw(
+        render_process_id, render_frame_id, session, controller_conn_ptr.get());
+  }
+
+  MOCK_METHOD4(RegisterOffscreenPresentationConnectionRaw,
+               void(int render_process_id,
+                    int render_frame_id,
+                    const content::PresentationSessionInfo& session,
+                    blink::mojom::PresentationConnection* connection));
+
   void set_screen_availability_listening_supported(bool value) {
     screen_availability_listening_supported_ = value;
   }
@@ -147,6 +171,32 @@
   bool screen_availability_listening_supported_ = true;
 };
 
+class MockReceiverPresentationServiceDelegate
+    : public ReceiverPresentationServiceDelegate {
+ public:
+  MOCK_METHOD3(AddObserver,
+               void(int render_process_id,
+                    int render_frame_id,
+                    PresentationServiceDelegate::Observer* observer));
+  MOCK_METHOD2(RemoveObserver,
+               void(int render_process_id, int render_frame_id));
+  MOCK_METHOD2(Reset, void(int render_process_id, int routing_id));
+  MOCK_METHOD1(RegisterReceiverConnectionAvailableCallback,
+               void(const content::ReceiverConnectionAvailableCallback&));
+};
+
+class MockPresentationConnection : public blink::mojom::PresentationConnection {
+ public:
+  void OnMessage(blink::mojom::ConnectionMessagePtr message,
+                 const base::Callback<void(bool)>& send_message_cb) override {
+    OnConnectionMessageReceived(*message);
+  }
+  MOCK_METHOD1(OnConnectionMessageReceived,
+               void(const blink::mojom::ConnectionMessage& message));
+  MOCK_METHOD1(DidChangeState,
+               void(blink::mojom::PresentationConnectionState state));
+};
+
 class MockPresentationServiceClient
     : public blink::mojom::PresentationServiceClient {
  public:
@@ -190,7 +240,10 @@
                void(const blink::mojom::PresentationSessionInfo& session_info));
 
   void OnReceiverConnectionAvailable(
-      blink::mojom::PresentationSessionInfoPtr session_info) override {
+      blink::mojom::PresentationSessionInfoPtr session_info,
+      blink::mojom::PresentationConnectionPtr controller_conn_ptr,
+      blink::mojom::PresentationConnectionRequest receiver_conn_request)
+      override {
     OnReceiverConnectionAvailable(*session_info);
   }
   MOCK_METHOD1(OnReceiverConnectionAvailable,
@@ -214,7 +267,7 @@
     TestRenderFrameHost* render_frame_host = contents()->GetMainFrame();
     render_frame_host->InitializeRenderFrameIfNeeded();
     service_impl_.reset(new PresentationServiceImpl(
-        render_frame_host, contents(), &mock_delegate_));
+        render_frame_host, contents(), &mock_delegate_, nullptr));
     service_impl_->Bind(std::move(request));
 
     blink::mojom::PresentationServiceClientPtr client_ptr;
@@ -373,6 +426,7 @@
   }
 
   MockPresentationServiceDelegate mock_delegate_;
+  MockReceiverPresentationServiceDelegate mock_receiver_delegate_;
 
   std::unique_ptr<PresentationServiceImpl> service_impl_;
   mojo::InterfacePtr<blink::mojom::PresentationService> service_ptr_;
@@ -666,6 +720,59 @@
   RunListenForConnectionMessages(text_msg, binary_data, false);
 }
 
+TEST_F(PresentationServiceImplTest, SetPresentationConnection) {
+  blink::mojom::PresentationSessionInfoPtr session(
+      blink::mojom::PresentationSessionInfo::New());
+  session->url = presentation_url1_;
+  session->id = kPresentationId;
+
+  blink::mojom::PresentationConnectionPtr connection;
+  MockPresentationConnection mock_presentation_connection;
+  mojo::Binding<blink::mojom::PresentationConnection> connection_binding(
+      &mock_presentation_connection, mojo::MakeRequest(&connection));
+  blink::mojom::PresentationConnectionPtr receiver_connection;
+  auto request = mojo::MakeRequest(&receiver_connection);
+
+  content::PresentationSessionInfo expected(presentation_url1_,
+                                            kPresentationId);
+  EXPECT_CALL(mock_delegate_,
+              RegisterOffscreenPresentationConnectionRaw(
+                  _, _, ContentSessionInfoEquals(ByRef(expected)), _));
+
+  service_impl_->SetPresentationConnection(
+      std::move(session), std::move(connection), std::move(request));
+}
+
+TEST_F(PresentationServiceImplTest, ReceiverPresentationServiceDelegate) {
+  MockReceiverPresentationServiceDelegate mock_receiver_delegate;
+
+  PresentationServiceImpl service_impl(contents()->GetMainFrame(), contents(),
+                                       nullptr, &mock_receiver_delegate);
+
+  ReceiverConnectionAvailableCallback callback;
+  EXPECT_CALL(mock_receiver_delegate,
+              RegisterReceiverConnectionAvailableCallback(_))
+      .WillOnce(SaveArg<0>(&callback));
+
+  blink::mojom::PresentationServiceClientPtr client_ptr;
+  client_binding_.reset(
+      new mojo::Binding<blink::mojom::PresentationServiceClient>(
+          &mock_client_, mojo::MakeRequest(&client_ptr)));
+  service_impl.controller_delegate_ = nullptr;
+  service_impl.SetClient(std::move(client_ptr));
+  EXPECT_FALSE(callback.is_null());
+
+  // NO-OP for ControllerPresentationServiceDelegate API functions
+  EXPECT_CALL(mock_delegate_, ListenForConnectionMessages(_, _, _, _)).Times(0);
+
+  blink::mojom::PresentationSessionInfoPtr session(
+      blink::mojom::PresentationSessionInfo::New());
+  session->url = GURL(kPresentationUrl1);
+  session->id = kPresentationId;
+
+  service_impl.ListenForConnectionMessages(std::move(session));
+}
+
 TEST_F(PresentationServiceImplTest, StartSessionInProgress) {
   EXPECT_CALL(mock_delegate_, StartSession(_, _, presentation_urls_, _, _))
       .Times(1);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 62d85d63..408da27d 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1689,7 +1689,6 @@
     switches::kDisableLocalStorage,
     switches::kDisableLogging,
     switches::kDisableMediaSuspend,
-    switches::kDisableMojoServiceWorker,
     switches::kDisableNotifications,
     switches::kDisableOverlayScrollbar,
     switches::kDisablePepper3DImageChromium,
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index 1f89e03..240bd4f 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -153,18 +153,20 @@
   StalledInStartWorkerHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
   ~StalledInStartWorkerHelper() override{};
 
-  void OnStartWorker(int embedded_worker_id,
-                     int64_t service_worker_version_id,
-                     const GURL& scope,
-                     const GURL& script_url,
-                     bool pause_after_download) override {
+  void OnStartWorker(
+      int embedded_worker_id,
+      int64_t service_worker_version_id,
+      const GURL& scope,
+      const GURL& script_url,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request) override {
     if (force_stall_in_start_) {
       // Do nothing to simulate a stall in the worker process.
       return;
     }
-    EmbeddedWorkerTestHelper::OnStartWorker(embedded_worker_id,
-                                            service_worker_version_id, scope,
-                                            script_url, pause_after_download);
+    EmbeddedWorkerTestHelper::OnStartWorker(
+        embedded_worker_id, service_worker_version_id, scope, script_url,
+        pause_after_download, std::move(request));
   }
 
   void set_force_stall_in_start(bool force_stall_in_start) {
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index b2f80213..93abef4 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -61,26 +61,17 @@
 class EmbeddedWorkerTestHelper::MockEmbeddedWorkerSetup
     : public mojom::EmbeddedWorkerSetup {
  public:
-  explicit MockEmbeddedWorkerSetup(
-      const base::WeakPtr<EmbeddedWorkerTestHelper>& helper)
-      : helper_(helper) {}
-
   static void Create(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
                      mojom::EmbeddedWorkerSetupRequest request) {
-    mojo::MakeStrongBinding(base::MakeUnique<MockEmbeddedWorkerSetup>(helper),
-                            std::move(request));
+    // TODO(shimazu): Remove this mock after EmbeddedWorkerSetup is removed.
+    NOTREACHED();
   }
 
   void AttachServiceWorkerEventDispatcher(
       int32_t thread_id,
       mojom::ServiceWorkerEventDispatcherRequest request) override {
-    if (!helper_)
-      return;
-    helper_->OnSetupMojo(thread_id, std::move(request));
+    NOTREACHED();
   }
-
- private:
-  base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
 };
 
 EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
@@ -101,18 +92,10 @@
 
   EmbeddedWorkerInstance* worker =
       helper_->registry()->GetWorker(params.embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
 
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker, helper_->AsWeakPtr(),
-                 params.embedded_worker_id, params.service_worker_version_id,
-                 params.scope, params.script_url, params.pause_after_download));
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE,
-      base::Bind(&EmbeddedWorkerTestHelper::OnSetupMojo, helper_->AsWeakPtr(),
-                 worker->thread_id(), base::Passed(&dispatcher_request)));
+  helper_->OnStartWorkerStub(params, std::move(dispatcher_request));
 }
 
 void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StopWorker(
@@ -127,7 +110,7 @@
   // is removed right after sending StopWorker.
   if (worker)
     EXPECT_EQ(EmbeddedWorkerStatus::STOPPING, worker->status());
-  callback.Run();
+  helper_->OnStopWorkerStub(callback);
 }
 
 // static
@@ -256,10 +239,8 @@
 bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
-    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker, OnStartWorkerStub)
     IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload,
                         OnResumeAfterDownloadStub)
-    IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorkerStub)
     IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_MessageToWorker,
                         OnMessageToWorkerStub)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -298,11 +279,18 @@
   return info;
 }
 
-void EmbeddedWorkerTestHelper::OnStartWorker(int embedded_worker_id,
-                                             int64_t service_worker_version_id,
-                                             const GURL& scope,
-                                             const GURL& script_url,
-                                             bool pause_after_download) {
+void EmbeddedWorkerTestHelper::OnStartWorker(
+    int embedded_worker_id,
+    int64_t service_worker_version_id,
+    const GURL& scope,
+    const GURL& script_url,
+    bool pause_after_download,
+    mojom::ServiceWorkerEventDispatcherRequest request) {
+  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+  ASSERT_TRUE(worker);
+  MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), worker->thread_id(),
+                                           std::move(request));
+
   embedded_worker_id_service_worker_version_id_map_[embedded_worker_id] =
       service_worker_version_id;
   SimulateWorkerReadyForInspection(embedded_worker_id);
@@ -318,9 +306,10 @@
   SimulateWorkerStarted(embedded_worker_id);
 }
 
-void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
+void EmbeddedWorkerTestHelper::OnStopWorker(
+    const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback& callback) {
   // By default just notify the sender that the worker is stopped.
-  SimulateWorkerStopped(embedded_worker_id);
+  callback.Run();
 }
 
 bool EmbeddedWorkerTestHelper::OnMessageToWorker(int thread_id,
@@ -339,13 +328,6 @@
   return handled;
 }
 
-void EmbeddedWorkerTestHelper::OnSetupMojo(
-    int thread_id,
-    mojom::ServiceWorkerEventDispatcherRequest dispatcher_request) {
-  MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), thread_id,
-                                           std::move(dispatcher_request));
-}
-
 void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id,
                                                int request_id) {
   SimulateSend(new ServiceWorkerHostMsg_ActivateEventFinished(
@@ -403,7 +385,7 @@
 void EmbeddedWorkerTestHelper::SimulateWorkerReadyForInspection(
     int embedded_worker_id) {
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   registry()->OnWorkerReadyForInspection(worker->process_id(),
                                          embedded_worker_id);
 }
@@ -428,7 +410,7 @@
 void EmbeddedWorkerTestHelper::SimulateWorkerScriptLoaded(
     int embedded_worker_id) {
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   registry()->OnWorkerScriptLoaded(worker->process_id(), embedded_worker_id);
 }
 
@@ -437,7 +419,7 @@
     int embedded_worker_id) {
   thread_id_embedded_worker_id_map_[thread_id] = embedded_worker_id;
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   registry()->OnWorkerThreadStarted(worker->process_id(), thread_id,
                                     embedded_worker_id);
 }
@@ -446,20 +428,20 @@
     int embedded_worker_id,
     bool success) {
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   registry()->OnWorkerScriptEvaluated(worker->process_id(), embedded_worker_id,
                                       success);
 }
 
 void EmbeddedWorkerTestHelper::SimulateWorkerStarted(int embedded_worker_id) {
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   registry()->OnWorkerStarted(worker->process_id(), embedded_worker_id);
 }
 
 void EmbeddedWorkerTestHelper::SimulateWorkerStopped(int embedded_worker_id) {
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  if (worker != NULL)
+  if (worker)
     registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
 }
 
@@ -469,16 +451,18 @@
 }
 
 void EmbeddedWorkerTestHelper::OnStartWorkerStub(
-    const EmbeddedWorkerStartParams& params) {
+    const EmbeddedWorkerStartParams& params,
+    mojom::ServiceWorkerEventDispatcherRequest request) {
   EmbeddedWorkerInstance* worker =
       registry()->GetWorker(params.embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
       base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker, AsWeakPtr(),
                  params.embedded_worker_id, params.service_worker_version_id,
-                 params.scope, params.script_url, params.pause_after_download));
+                 params.scope, params.script_url, params.pause_after_download,
+                 base::Passed(&request)));
 }
 
 void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
@@ -490,12 +474,11 @@
                             AsWeakPtr(), embedded_worker_id));
 }
 
-void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
-  EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+void EmbeddedWorkerTestHelper::OnStopWorkerStub(
+    const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback& callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnStopWorker,
-                            AsWeakPtr(), embedded_worker_id));
+                            AsWeakPtr(), callback));
 }
 
 void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
@@ -503,7 +486,7 @@
     int embedded_worker_id,
     const IPC::Message& message) {
   EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
-  ASSERT_TRUE(worker != NULL);
+  ASSERT_TRUE(worker);
   EXPECT_EQ(worker->thread_id(), thread_id);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
diff --git a/content/browser/service_worker/embedded_worker_test_helper.h b/content/browser/service_worker/embedded_worker_test_helper.h
index 108327d1..74c6a73 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/content/browser/service_worker/embedded_worker_test_helper.h
@@ -154,29 +154,27 @@
   static net::HttpResponseInfo CreateHttpResponseInfo();
 
  protected:
-  // Called when StartWorker, StopWorker and SendMessageToWorker message
-  // is sent to the embedded worker. Override if necessary. By default
-  // they verify given parameters and:
-  // - OnStartWorker calls SimulateWorkerStarted
-  // - OnStopWorker calls SimulateWorkerStoped
-  // - OnSendMessageToWorker calls the message's respective On*Event handler
-  virtual void OnStartWorker(int embedded_worker_id,
-                             int64_t service_worker_version_id,
-                             const GURL& scope,
-                             const GURL& script_url,
-                             bool pause_after_download);
+  // StartWorker IPC handler routed through MockEmbeddedWorkerInstanceClient.
+  // This simulates each legacy IPC sent from the renderer and binds |request|
+  // to MockServiceWorkerEventDispatcher by default.
+  virtual void OnStartWorker(
+      int embedded_worker_id,
+      int64_t service_worker_version_id,
+      const GURL& scope,
+      const GURL& script_url,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request);
   virtual void OnResumeAfterDownload(int embedded_worker_id);
-  virtual void OnStopWorker(int embedded_worker_id);
+  // StopWorker IPC handler routed through MockEmbeddedWorkerInstanceClient.
+  // This calls StopWorkerCallback by default.
+  virtual void OnStopWorker(
+      const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback& callback);
+  // The legacy IPC message handler. This passes the messages to their
+  // respective On*Event handler by default.
   virtual bool OnMessageToWorker(int thread_id,
                                  int embedded_worker_id,
                                  const IPC::Message& message);
 
-  // Called to setup mojo for a new embedded worker. Override to register
-  // interfaces the worker should expose to the browser.
-  virtual void OnSetupMojo(
-      int thread_id,
-      mojom::ServiceWorkerEventDispatcherRequest dispatcher_request);
-
   // On*Event handlers. Called by the default implementation of
   // OnMessageToWorker when events are sent to the embedded
   // worker. By default they just return success via
@@ -196,8 +194,8 @@
                            int request_id,
                            const PushEventPayload& payload);
 
-  // These functions simulate sending an EmbeddedHostMsg message to the
-  // browser.
+  // These functions simulate sending an EmbeddedHostMsg message through the
+  // legacy IPC system to the browser.
   void SimulateWorkerReadyForInspection(int embedded_worker_id);
   void SimulateWorkerScriptCached(int embedded_worker_id);
   void SimulateWorkerScriptLoaded(int embedded_worker_id);
@@ -213,9 +211,11 @@
   class MockEmbeddedWorkerSetup;
   class MockServiceWorkerEventDispatcher;
 
-  void OnStartWorkerStub(const EmbeddedWorkerStartParams& params);
+  void OnStartWorkerStub(const EmbeddedWorkerStartParams& params,
+                         mojom::ServiceWorkerEventDispatcherRequest request);
   void OnResumeAfterDownloadStub(int embedded_worker_id);
-  void OnStopWorkerStub(int embedded_worker_id);
+  void OnStopWorkerStub(
+      const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback& callback);
   void OnMessageToWorkerStub(int thread_id,
                              int embedded_worker_id,
                              const IPC::Message& message);
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index eb826b2..249e254 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -46,11 +46,13 @@
   ~FailureHelper() override {}
 
  protected:
-  void OnStartWorker(int embedded_worker_id,
-                     int64_t service_worker_version_id,
-                     const GURL& scope,
-                     const GURL& script_url,
-                     bool pause_after_download) override {
+  void OnStartWorker(
+      int embedded_worker_id,
+      int64_t service_worker_version_id,
+      const GURL& scope,
+      const GURL& script_url,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request) override {
     SimulateWorkerStopped(embedded_worker_id);
   }
 };
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index b4385433..638b46b 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -86,11 +86,13 @@
  public:
   FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
 
-  void OnStartWorker(int embedded_worker_id,
-                     int64_t service_worker_version_id,
-                     const GURL& scope,
-                     const GURL& script_url,
-                     bool pause_after_download) override {
+  void OnStartWorker(
+      int embedded_worker_id,
+      int64_t service_worker_version_id,
+      const GURL& scope,
+      const GURL& script_url,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request) override {
     EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
     registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
   }
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 363722f..fb6924c 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -370,11 +370,13 @@
  public:
   FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
 
-  void OnStartWorker(int embedded_worker_id,
-                     int64_t service_worker_version_id,
-                     const GURL& scope,
-                     const GURL& script_url,
-                     bool pause_after_download) override {
+  void OnStartWorker(
+      int embedded_worker_id,
+      int64_t service_worker_version_id,
+      const GURL& scope,
+      const GURL& script_url,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request) override {
     EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
     registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
   }
@@ -829,11 +831,13 @@
   }
 
   // EmbeddedWorkerTestHelper overrides
-  void OnStartWorker(int embedded_worker_id,
-                     int64_t version_id,
-                     const GURL& scope,
-                     const GURL& script,
-                     bool pause_after_download) override {
+  void OnStartWorker(
+      int embedded_worker_id,
+      int64_t version_id,
+      const GURL& scope,
+      const GURL& script,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request) override {
     const std::string kMockScriptBody = "mock_script";
     const uint64_t kMockScriptSize = 19284;
     ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
@@ -883,8 +887,9 @@
           EmbeddedWorkerTestHelper::CreateHttpResponseInfo());
     }
 
-    EmbeddedWorkerTestHelper::OnStartWorker(
-        embedded_worker_id, version_id, scope, script, pause_after_download);
+    EmbeddedWorkerTestHelper::OnStartWorker(embedded_worker_id, version_id,
+                                            scope, script, pause_after_download,
+                                            std::move(request));
   }
 
   void OnResumeAfterDownload(int embedded_worker_id) override {
@@ -939,11 +944,13 @@
   EvictIncumbentVersionHelper() {}
   ~EvictIncumbentVersionHelper() override {}
 
-  void OnStartWorker(int embedded_worker_id,
-                     int64_t version_id,
-                     const GURL& scope,
-                     const GURL& script,
-                     bool pause_after_download) override {
+  void OnStartWorker(
+      int embedded_worker_id,
+      int64_t version_id,
+      const GURL& scope,
+      const GURL& script,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request) override {
     ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
     ServiceWorkerRegistration* registration =
         context()->GetLiveRegistration(version->registration_id());
@@ -956,7 +963,8 @@
           make_scoped_refptr(registration->active_version()));
     }
     UpdateJobTestHelper::OnStartWorker(embedded_worker_id, version_id, scope,
-                                       script, pause_after_download);
+                                       script, pause_after_download,
+                                       std::move(request));
   }
 
   void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 0584a87..49294d9 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -1110,9 +1110,11 @@
     int request_id,
     ServiceWorkerStatusCode status,
     base::Time dispatch_event_time) {
-  // Copy error callback before calling FinishRequest.
   PendingRequest* request = pending_requests_.Lookup(request_id);
-  DCHECK(request) << "Invalid request id";
+  // |request| will be null when the request has been timed out.
+  if (!request)
+    return;
+  // Copy error callback before calling FinishRequest.
   StatusCallback callback = request->error_callback;
 
   FinishRequest(request_id, status == SERVICE_WORKER_OK, dispatch_event_time);
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 0e26f68..57ac261 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -449,7 +449,7 @@
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_RunningWorker);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
                            StaleUpdate_DoNotDeferTimer);
-  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestTimeout);
+  FRIEND_TEST_ALL_PREFIXES(ServiceWorkerRequestTimeoutTest, RequestTimeout);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerFailToStartTest, Timeout);
   FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionBrowserTest,
                            TimeoutStartingWorker);
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index c63ee7c..5639e4d 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -307,11 +307,13 @@
 
   enum class StartMode { STALL, FAIL, SUCCEED };
 
-  void OnStartWorker(int embedded_worker_id,
-                     int64_t service_worker_version_id,
-                     const GURL& scope,
-                     const GURL& script_url,
-                     bool pause_after_download) override {
+  void OnStartWorker(
+      int embedded_worker_id,
+      int64_t service_worker_version_id,
+      const GURL& scope,
+      const GURL& script_url,
+      bool pause_after_download,
+      mojom::ServiceWorkerEventDispatcherRequest request) override {
     switch (mode_) {
       case StartMode::STALL:
         break;  // Do nothing.
@@ -322,9 +324,9 @@
         mock_instance_clients()->at(current_mock_instance_index_).reset();
         break;
       case StartMode::SUCCEED:
-        MessageReceiver::OnStartWorker(embedded_worker_id,
-                                       service_worker_version_id, scope,
-                                       script_url, pause_after_download);
+        MessageReceiver::OnStartWorker(
+            embedded_worker_id, service_worker_version_id, scope, script_url,
+            pause_after_download, std::move(request));
         break;
     }
     current_mock_instance_index_++;
@@ -388,7 +390,9 @@
   }
   ~MessageReceiverDisallowStop() override {}
 
-  void OnStopWorker(int embedded_worker_id) override {
+  void OnStopWorker(
+      const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback& callback)
+      override {
     // Do nothing.
   }
 
@@ -830,8 +834,71 @@
   EXPECT_EQ(run_time, version_->update_timer_.desired_run_time());
 }
 
-TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
-  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK;  // dummy value
+class MessageReceiverControlEvents : public MessageReceiver {
+ public:
+  MessageReceiverControlEvents() : MessageReceiver() {}
+  ~MessageReceiverControlEvents() override {}
+
+  void OnExtendableMessageEvent(
+      mojom::ExtendableMessageEventPtr event,
+      const mojom::ServiceWorkerEventDispatcher::
+          DispatchExtendableMessageEventCallback& callback) override {
+    EXPECT_FALSE(extendable_message_event_callback_);
+    extendable_message_event_callback_ = callback;
+  }
+
+  void OnStopWorker(
+      const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback& callback)
+      override {
+    EXPECT_FALSE(stop_worker_callback_);
+    stop_worker_callback_ = callback;
+  }
+
+  const mojom::ServiceWorkerEventDispatcher::
+      DispatchExtendableMessageEventCallback&
+      extendable_message_event_callback() {
+    return extendable_message_event_callback_;
+  }
+
+  const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback&
+  stop_worker_callback() {
+    return stop_worker_callback_;
+  }
+
+ private:
+  mojom::ServiceWorkerEventDispatcher::DispatchExtendableMessageEventCallback
+      extendable_message_event_callback_;
+  mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback stop_worker_callback_;
+};
+
+class ServiceWorkerRequestTimeoutTest : public ServiceWorkerVersionTest {
+ protected:
+  ServiceWorkerRequestTimeoutTest() : ServiceWorkerVersionTest() {}
+
+  std::unique_ptr<MessageReceiver> GetMessageReceiver() override {
+    return base::MakeUnique<MessageReceiverControlEvents>();
+  }
+
+  const mojom::ServiceWorkerEventDispatcher::
+      DispatchExtendableMessageEventCallback&
+      extendable_message_event_callback() {
+    return static_cast<MessageReceiverControlEvents*>(helper_.get())
+        ->extendable_message_event_callback();
+  }
+
+  const mojom::EmbeddedWorkerInstanceClient::StopWorkerCallback&
+  stop_worker_callback() {
+    return static_cast<MessageReceiverControlEvents*>(helper_.get())
+        ->stop_worker_callback();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRequestTimeoutTest);
+};
+
+TEST_F(ServiceWorkerRequestTimeoutTest, RequestTimeout) {
+  ServiceWorkerStatusCode error_status =
+      SERVICE_WORKER_ERROR_NETWORK;  // dummy value
   version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
 
   version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
@@ -841,22 +908,47 @@
   // Create a request.
   int request_id =
       version_->StartRequest(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
-                             CreateReceiverOnCurrentThread(&status));
+                             CreateReceiverOnCurrentThread(&error_status));
+
+  // Dispatch a dummy event whose response will be received by SWVersion.
+  EXPECT_FALSE(extendable_message_event_callback());
+  version_->event_dispatcher()->DispatchExtendableMessageEvent(
+      mojom::ExtendableMessageEvent::New(),
+      base::Bind(&ServiceWorkerVersion::OnSimpleEventFinished, version_,
+                 request_id));
   base::RunLoop().RunUntilIdle();
+  // The renderer should have received an ExtendableMessageEvent request.
+  EXPECT_TRUE(extendable_message_event_callback());
 
   // Callback has not completed yet.
-  EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
+  EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, error_status);
   EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status());
 
   // Simulate timeout.
+  EXPECT_FALSE(stop_worker_callback());
   EXPECT_TRUE(version_->timeout_timer_.IsRunning());
   version_->SetAllRequestExpirations(base::TimeTicks::Now());
   version_->timeout_timer_.user_task().Run();
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
-  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
+
+  // The renderer should have received a StopWorker request.
+  EXPECT_TRUE(stop_worker_callback());
+  // The request should have timed out.
+  EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, error_status);
+  // Calling FinishRequest should be no-op, since the request timed out.
   EXPECT_FALSE(version_->FinishRequest(request_id, true /* was_handled */,
                                        base::Time::Now()));
+
+  // Simulate the renderer aborting the pending event.
+  // This should not crash: https://crbug.com/676984.
+  extendable_message_event_callback().Run(SERVICE_WORKER_ERROR_ABORT,
+                                          base::Time::Now());
+  base::RunLoop().RunUntilIdle();
+
+  // Simulate the renderer stopping the worker.
+  stop_worker_callback().Run();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version_->running_status());
 }
 
 TEST_F(ServiceWorkerVersionTest, RequestNowTimeout) {
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index ea529e53..1d01ac8 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -32,6 +32,7 @@
 #include "ui/base/dragdrop/cocoa_dnd_util.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
+#include "ui/gfx/mac/coordinate_conversion.h"
 
 using blink::WebDragOperation;
 using blink::WebDragOperationsMask;
@@ -163,11 +164,7 @@
     bounds = [window convertRectToScreen:bounds];
   }
 
-  // Flip y to account for screen flip.
-  NSScreen* screen = [[NSScreen screens] firstObject];
-  bounds.origin.y = [screen frame].size.height - bounds.origin.y
-      - bounds.size.height;
-  *out = gfx::Rect(NSRectToCGRect(bounds));
+  *out = gfx::ScreenRectFromNSRect(bounds);
 }
 
 void WebContentsViewMac::StartDragging(
diff --git a/content/child/child_process.cc b/content/child/child_process.cc
index 2763ee03..7c5b408 100644
--- a/content/child/child_process.cc
+++ b/content/child/child_process.cc
@@ -67,11 +67,15 @@
   // notice shutdown before the render process begins waiting for them to exit.
   shutdown_event_.Signal();
 
-  // Kill the main thread object before nulling child_process, since
-  // destruction code might depend on it.
   if (main_thread_) {  // null in unittests.
     main_thread_->Shutdown();
-    main_thread_.reset();
+    if (main_thread_->ShouldBeDestroyed()) {
+      main_thread_.reset();
+    } else {
+      // Leak the main_thread_. See a comment in
+      // RenderThreadImpl::ShouldBeDestroyed.
+      main_thread_.release();
+    }
   }
 
   g_lazy_tls.Pointer()->Set(NULL);
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc
index 1c4275c97..d2c4660 100644
--- a/content/child/child_thread_impl.cc
+++ b/content/child/child_thread_impl.cc
@@ -598,6 +598,10 @@
   WebFileSystemImpl::DeleteThreadSpecificInstance();
 }
 
+bool ChildThreadImpl::ShouldBeDestroyed() {
+  return true;
+}
+
 void ChildThreadImpl::OnChannelConnected(int32_t peer_pid) {
   channel_connected_factory_.reset();
 }
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h
index 11c96112..6dc64263 100644
--- a/content/child/child_thread_impl.h
+++ b/content/child/child_thread_impl.h
@@ -82,6 +82,8 @@
   // should be joined in Shutdown().
   ~ChildThreadImpl() override;
   virtual void Shutdown();
+  // Returns true if the thread should be destroyed.
+  virtual bool ShouldBeDestroyed();
 
   // IPC::Sender implementation:
   bool Send(IPC::Message* msg) override;
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 022ed81..ae50243 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -373,8 +373,14 @@
   return base::GenerateGUID();
 }
 
-PresentationServiceDelegate*
-ContentBrowserClient::GetPresentationServiceDelegate(
+ControllerPresentationServiceDelegate*
+ContentBrowserClient::GetControllerPresentationServiceDelegate(
+    WebContents* web_contents) {
+  return nullptr;
+}
+
+ReceiverPresentationServiceDelegate*
+ContentBrowserClient::GetReceiverPresentationServiceDelegate(
     WebContents* web_contents) {
   return nullptr;
 }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 343b875..f7b4300 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -112,6 +112,7 @@
 class BrowserPpapiHost;
 class BrowserURLHandler;
 class ClientCertificateDelegate;
+class ControllerPresentationServiceDelegate;
 class DevToolsManagerDelegate;
 class GpuProcessHost;
 class MediaObserver;
@@ -119,8 +120,8 @@
 class NavigationHandle;
 class NavigationUIData;
 class PlatformNotificationService;
-class PresentationServiceDelegate;
 class QuotaPermissionContext;
+class ReceiverPresentationServiceDelegate;
 class RenderFrameHost;
 class RenderProcessHost;
 class RenderViewHost;
@@ -724,10 +725,17 @@
       RenderFrameHost* render_frame_host,
       blink::WebPageVisibilityState* visibility_state) {}
 
-  // Allows an embedder to provide its own PresentationServiceDelegate
+  // Allows an embedder to provide its own ControllerPresentationServiceDelegate
   // implementation. Returns nullptr if unavailable.
-  virtual PresentationServiceDelegate* GetPresentationServiceDelegate(
-      WebContents* web_contents);
+  virtual ControllerPresentationServiceDelegate*
+  GetControllerPresentationServiceDelegate(WebContents* web_contents);
+
+  // Allows an embedder to provide its own ReceiverPresentationServiceDelegate
+  // implementation. Returns nullptr if unavailable. Only WebContents created
+  // for offscreen presentations should be passed to this API. The WebContents
+  // must belong to an incognito profile.
+  virtual ReceiverPresentationServiceDelegate*
+  GetReceiverPresentationServiceDelegate(WebContents* web_contents);
 
   // Allows programmatic opening of a new tab/window without going through
   // another WebContents. For example, from a Worker. |callback| will be
diff --git a/content/public/browser/presentation_service_delegate.h b/content/public/browser/presentation_service_delegate.h
index 2ea8b0fd..55e2f4c1 100644
--- a/content/public/browser/presentation_service_delegate.h
+++ b/content/public/browser/presentation_service_delegate.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_PUBLIC_BROWSER_PRESENTATION_SERVICE_DELEGATE_H_
 #define CONTENT_PUBLIC_BROWSER_PRESENTATION_SERVICE_DELEGATE_H_
 
+#include <map>
 #include <memory>
 #include <string>
 #include <vector>
@@ -13,6 +14,7 @@
 #include "content/common/content_export.h"
 #include "content/public/common/presentation_connection_message.h"
 #include "content/public/common/presentation_session.h"
+#include "third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h"
 
 class GURL;
 
@@ -49,8 +51,17 @@
 using PresentationConnectionStateChangedCallback =
     base::Callback<void(const PresentationConnectionStateChangeInfo&)>;
 
-// An interface implemented by embedders to handle presentation API calls
-// forwarded from PresentationServiceImpl.
+using PresentationConnectionPtr = blink::mojom::PresentationConnectionPtr;
+using PresentationConnectionRequest =
+    blink::mojom::PresentationConnectionRequest;
+
+using ReceiverConnectionAvailableCallback =
+    base::Callback<void(const content::PresentationSessionInfo&,
+                        PresentationConnectionPtr,
+                        PresentationConnectionRequest)>;
+
+// Base class for ControllerPresentationServiceDelegate and
+// ReceiverPresentationServiceDelegate.
 class CONTENT_EXPORT PresentationServiceDelegate {
  public:
   // Observer interface to listen for changes to PresentationServiceDelegate.
@@ -63,8 +74,6 @@
     virtual ~Observer() {}
   };
 
-  using SendMessageCallback = base::Callback<void(bool)>;
-
   virtual ~PresentationServiceDelegate() {}
 
   // Registers an observer associated with frame with |render_process_id|
@@ -81,6 +90,20 @@
   // The observer will no longer receive updates.
   virtual void RemoveObserver(int render_process_id, int render_frame_id) = 0;
 
+  // Resets the presentation state for the frame given by |render_process_id|
+  // and |render_frame_id|.
+  // This unregisters all screen availability associated with the given frame,
+  // and clears the default presentation URL for the frame.
+  virtual void Reset(int render_process_id, int render_frame_id) = 0;
+};
+
+// An interface implemented by embedders to handle Presentation API calls
+// forwarded from PresentationServiceImpl.
+class CONTENT_EXPORT ControllerPresentationServiceDelegate
+    : public PresentationServiceDelegate {
+ public:
+  using SendMessageCallback = base::Callback<void(bool)>;
+
   // Registers |listener| to continuously listen for
   // availability updates for a presentation URL, originated from the frame
   // given by |render_process_id| and |render_frame_id|.
@@ -101,14 +124,6 @@
       int render_frame_id,
       PresentationScreenAvailabilityListener* listener) = 0;
 
-  // Resets the presentation state for the frame given by |render_process_id|
-  // and |render_frame_id|.
-  // This unregisters all listeners associated with the given frame, and clears
-  // the default presentation URL and ID set for the frame.
-  virtual void Reset(
-      int render_process_id,
-      int render_frame_id) = 0;
-
   // Sets the default presentation URLs for frame given by |render_process_id|
   // and |render_frame_id|. When the default presentation is started on this
   // frame, |callback| will be invoked with the corresponding
@@ -203,6 +218,34 @@
       int render_frame_id,
       const PresentationSessionInfo& connection,
       const PresentationConnectionStateChangedCallback& state_changed_cb) = 0;
+
+  // Connect |controller_connection| owned by the controlling frame to the
+  // offscreen presentation represented by |session|.
+  // |render_process_id|, |render_frame_id|: ID of originating frame.
+  // |controller_connection|: Pointer to controller's presentation connection,
+  // ownership passed from controlling frame to the offscreen presentation.
+  // |receiver_connection_request|: Mojo InterfaceRequest to be bind to receiver
+  // page's presentation connection.
+  virtual void ConnectToOffscreenPresentation(
+      int render_process_id,
+      int render_frame_id,
+      const PresentationSessionInfo& session,
+      PresentationConnectionPtr controller_connection_ptr,
+      PresentationConnectionRequest receiver_connection_request) = 0;
+};
+
+// An interface implemented by embedders to handle
+// PresentationService calls from a presentation receiver.
+class CONTENT_EXPORT ReceiverPresentationServiceDelegate
+    : public PresentationServiceDelegate {
+ public:
+  // Registers a callback from the embedder when an offscreeen presentation has
+  // been successfully started.
+  // |receiver_available_callback|: Invoked when successfully starting a
+  // offscreen presentation session.
+  virtual void RegisterReceiverConnectionAvailableCallback(
+      const content::ReceiverConnectionAvailableCallback&
+          receiver_available_callback) = 0;
 };
 
 }  // namespace content
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 45d84d67..a9caa2f 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -661,9 +661,6 @@
 // Use a Mojo-based LocalStorage implementation.
 const char kMojoLocalStorage[]              = "mojo-local-storage";
 
-// Disables a Mojo-based ServiceWorker implementation.
-const char kDisableMojoServiceWorker[]      = "disable-mojo-service-worker";
-
 // Mutes audio sent to the audio device so it is not audible during
 // automated testing.
 const char kMuteAudio[]                     = "mute-audio";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index f6eff7de..6c985bfa 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -74,7 +74,6 @@
 CONTENT_EXPORT extern const char kDisableKillAfterBadIPC[];
 CONTENT_EXPORT extern const char kDisableLocalStorage[];
 CONTENT_EXPORT extern const char kDisableLogging[];
-CONTENT_EXPORT extern const char kDisableMojoServiceWorker[];
 CONTENT_EXPORT extern const char kDisableNamespaceSandbox[];
 CONTENT_EXPORT extern const char kDisableNotifications[];
 CONTENT_EXPORT extern const char kDisablePartialRaster[];
diff --git a/content/renderer/presentation/presentation_dispatcher.cc b/content/renderer/presentation/presentation_dispatcher.cc
index 2e084ee..7dcf920b 100644
--- a/content/renderer/presentation/presentation_dispatcher.cc
+++ b/content/renderer/presentation/presentation_dispatcher.cc
@@ -420,7 +420,9 @@
 }
 
 void PresentationDispatcher::OnReceiverConnectionAvailable(
-    blink::mojom::PresentationSessionInfoPtr session_info) {
+    blink::mojom::PresentationSessionInfoPtr session_info,
+    blink::mojom::PresentationConnectionPtr,
+    blink::mojom::PresentationConnectionRequest) {
   if (receiver_) {
     receiver_->onReceiverConnectionAvailable(
         mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info));
diff --git a/content/renderer/presentation/presentation_dispatcher.h b/content/renderer/presentation/presentation_dispatcher.h
index 6b6e1b3..ddcf5e6 100644
--- a/content/renderer/presentation/presentation_dispatcher.h
+++ b/content/renderer/presentation/presentation_dispatcher.h
@@ -146,7 +146,9 @@
       blink::mojom::PresentationSessionInfoPtr session_info,
       blink::mojom::PresentationErrorPtr error);
   void OnReceiverConnectionAvailable(
-      blink::mojom::PresentationSessionInfoPtr) override;
+      blink::mojom::PresentationSessionInfoPtr,
+      blink::mojom::PresentationConnectionPtr,
+      blink::mojom::PresentationConnectionRequest) override;
 
   // Call to PresentationService to send the message in |request|.
   // |session_info| and |message| of |reuqest| will be consumed.
diff --git a/content/renderer/presentation/presentation_dispatcher_unittest.cc b/content/renderer/presentation/presentation_dispatcher_unittest.cc
index 9397f85..3ec39ba 100644
--- a/content/renderer/presentation/presentation_dispatcher_unittest.cc
+++ b/content/renderer/presentation/presentation_dispatcher_unittest.cc
@@ -25,6 +25,7 @@
 using blink::WebString;
 using blink::WebURL;
 using blink::WebVector;
+using blink::mojom::PresentationConnection;
 using blink::mojom::PresentationError;
 using blink::mojom::PresentationErrorPtr;
 using blink::mojom::PresentationErrorType;
@@ -102,6 +103,17 @@
   }
   MOCK_METHOD1(ListenForConnectionMessagesInternal,
                void(PresentationSessionInfo* session_info));
+
+  void SetPresentationConnection(
+      blink::mojom::PresentationSessionInfoPtr session,
+      blink::mojom::PresentationConnectionPtr controller_conn_ptr,
+      blink::mojom::PresentationConnectionRequest receiver_conn_request)
+      override {
+    SetPresentationConnection(session.get(), controller_conn_ptr.get());
+  }
+  MOCK_METHOD2(SetPresentationConnection,
+               void(PresentationSessionInfo* session_info,
+                    PresentationConnection* connection));
 };
 
 class TestWebPresentationConnectionCallback
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index b397ca1..5508305 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/allocator/allocator_extension.h"
+#include "base/at_exit.h"
 #include "base/command_line.h"
 #include "base/debug/crash_logging.h"
 #include "base/lazy_instance.h"
@@ -937,132 +938,31 @@
 }
 
 void RenderThreadImpl::Shutdown() {
-  for (auto& observer : observers_)
-    observer.OnRenderProcessShutdown();
+  // In a multi-process mode, we immediately exit the renderer.
+  // Historically we had a graceful shutdown sequence here but it was
+  // 1) a waste of performance and 2) a source of lots of complicated
+  // crashes caused by shutdown ordering. Immediate exit eliminates
+  // those problems.
+  //
+  // In a single-process mode, we cannot call _exit(0) in Shutdown() because
+  // it will exit the process before the browser side is ready to exit.
+  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kSingleProcess))
+    _exit(0);
+}
 
-  if (memory_observer_) {
-    message_loop()->RemoveTaskObserver(memory_observer_.get());
-    memory_observer_.reset();
-  }
-
-  // Wait for all databases to be closed.
-  if (blink_platform_impl_) {
-    // Crash the process if they fail to close after a generous amount of time.
-    bool all_closed = blink_platform_impl_->web_database_observer_impl()
-        ->WaitForAllDatabasesToClose(base::TimeDelta::FromSeconds(60));
-    CHECK(all_closed);
-  }
-
-  // Shutdown in reverse of the initialization order.
-  if (devtools_agent_message_filter_.get()) {
-    RemoveFilter(devtools_agent_message_filter_.get());
-    devtools_agent_message_filter_ = nullptr;
-  }
-
-  RemoveFilter(audio_input_message_filter_.get());
-  audio_input_message_filter_ = nullptr;
-
-#if BUILDFLAG(ENABLE_WEBRTC)
-  RTCPeerConnectionHandler::DestructAllHandlers();
-  // |peer_connection_factory_| cannot be deleted until after the main message
-  // loop has been destroyed.  This is because there may be pending tasks that
-  // hold on to objects produced by the PC factory that depend on threads owned
-  // by the PC factory.  Once those tasks have been freed, the factory can be
-  // deleted.
-#endif
-  vc_manager_.reset();
-
-  RemoveFilter(db_message_filter_.get());
-  db_message_filter_ = nullptr;
-
-  // Shutdown the file thread if it's running.
-  if (file_thread_)
-    file_thread_->Stop();
-
-  if (compositor_message_filter_.get()) {
-    RemoveFilter(compositor_message_filter_.get());
-    compositor_message_filter_ = nullptr;
-  }
-
-#if defined(OS_ANDROID)
-  if (sync_compositor_message_filter_) {
-    RemoveFilter(sync_compositor_message_filter_.get());
-    sync_compositor_message_filter_ = nullptr;
-  }
-  stream_texture_factory_ = nullptr;
-#endif
-
-  media_thread_.reset();
-
-  blink_platform_impl_->SetCompositorThread(nullptr);
-
-  compositor_thread_.reset();
-
-  // AudioMessageFilter may be accessed on |media_thread_|, so shutdown after.
-  RemoveFilter(audio_message_filter_.get());
-  audio_message_filter_ = nullptr;
-
-  categorized_worker_pool_->Shutdown();
-
-  main_input_callback_.Cancel();
-  input_handler_manager_.reset();
-  if (input_event_filter_.get()) {
-    RemoveFilter(input_event_filter_.get());
-    input_event_filter_ = nullptr;
-  }
-
-  // RemoveEmbeddedWorkerRoute may be called while deleting
-  // EmbeddedWorkerDispatcher. So it must be deleted before deleting
-  // RenderThreadImpl.
-  embedded_worker_dispatcher_.reset();
-
-  // Ramp down IDB before we ramp down WebKit (and V8), since IDB classes might
-  // hold pointers to V8 objects (e.g., via pending requests).
-  main_thread_indexed_db_dispatcher_.reset();
-
-  main_thread_compositor_task_runner_ = nullptr;
-
-  gpu_factories_.clear();
-
-  // Context providers must be released prior to destroying the GPU channel.
-  shared_worker_context_provider_ = nullptr;
-  shared_main_thread_contexts_ = nullptr;
-
-  if (gpu_channel_.get())
-    gpu_channel_->DestroyChannel();
-
-  ChildThreadImpl::Shutdown();
-
-  // Shut down the message loop (if provided when the RenderThreadImpl was
-  // constructed) and the renderer scheduler before shutting down Blink. This
-  // prevents a scenario where a pending task in the message loop accesses Blink
-  // objects after Blink shuts down.
-  renderer_scheduler_->SetRAILModeObserver(nullptr);
-  renderer_scheduler_->Shutdown();
-  if (main_message_loop_)
-    base::RunLoop().RunUntilIdle();
-
-  if (blink_platform_impl_) {
-    blink_platform_impl_->Shutdown();
-    // This must be at the very end of the shutdown sequence.
-    // blink::shutdown() must be called after all strong references from
-    // Chromium to Blink are cleared.
-    blink::shutdown();
-  }
-
-  // Delay shutting down DiscardableSharedMemoryManager until blink::shutdown
-  // is complete, because blink::shutdown destructs Blink Resources and they
-  // may try to unlock their underlying discardable memory.
-  discardable_shared_memory_manager_.reset();
-
-  // The message loop must be cleared after shutting down
-  // the DiscardableSharedMemoryManager, which needs to send messages
-  // to the browser process.
-  main_message_loop_.reset();
-
-  lazy_tls.Pointer()->Set(nullptr);
-
-  base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(this);
+bool RenderThreadImpl::ShouldBeDestroyed() {
+  DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kSingleProcess));
+  // In a single-process mode, it is unsafe to destruct this renderer thread
+  // because we haven't run the shutdown sequence. Hence we leak the render
+  // thread.
+  //
+  // In this case, we also need to disable at-exit callbacks because some of
+  // the at-exit callbacks are expected to run after the renderer thread
+  // has been destructed.
+  base::AtExitManager::DisableAllAtExitManagers();
+  return false;
 }
 
 bool RenderThreadImpl::Send(IPC::Message* msg) {
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 508a1dc0..cf45d73 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -175,6 +175,7 @@
 
   ~RenderThreadImpl() override;
   void Shutdown() override;
+  bool ShouldBeDestroyed() override;
 
   // When initializing WebKit, ensure that any schemes needed for the content
   // module are registered properly.  Static to allow sharing with tests.
diff --git a/content/renderer/render_thread_impl_browsertest.cc b/content/renderer/render_thread_impl_browsertest.cc
index 38c5fc33..dcdc702 100644
--- a/content/renderer/render_thread_impl_browsertest.cc
+++ b/content/renderer/render_thread_impl_browsertest.cc
@@ -10,6 +10,7 @@
 
 #include "base/callback.h"
 #include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
 #include "base/location.h"
 #include "base/memory/discardable_memory.h"
 #include "base/run_loop.h"
@@ -33,6 +34,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_content_client_initializer.h"
+#include "content/public/test/test_launcher.h"
 #include "content/public/test/test_service_manager_context.h"
 #include "content/renderer/render_process_impl.h"
 #include "content/test/mock_render_process.h"
@@ -221,6 +223,17 @@
     thread_->AddFilter(test_msg_filter_.get());
   }
 
+  void TearDown() override {
+    if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+            kSingleProcessTestsFlag)) {
+      // In a single-process mode, we need to avoid destructing mock_process_
+      // because it will call _exit(0) and kill the process before the browser
+      // side is ready to exit.
+      ANNOTATE_LEAKING_OBJECT_PTR(mock_process_.get());
+      mock_process_.release();
+    }
+  }
+
   IPC::Sender* sender() { return channel_.get(); }
 
   scoped_refptr<TestTaskCounter> test_task_counter_;
diff --git a/extensions/common/extension_urls.h b/extensions/common/extension_urls.h
index 95aed71e..755115b 100644
--- a/extensions/common/extension_urls.h
+++ b/extensions/common/extension_urls.h
@@ -8,8 +8,7 @@
 #include <string>
 
 #include "base/strings/string16.h"
-
-class GURL;
+#include "url/gurl.h"
 
 namespace extensions {
 
diff --git a/net/cert/internal/path_builder.cc b/net/cert/internal/path_builder.cc
index 266a2a1..bb4283e 100644
--- a/net/cert/internal/path_builder.cc
+++ b/net/cert/internal/path_builder.cc
@@ -82,6 +82,9 @@
   void AddIssuers(ParsedCertificateList issuers);
   void DoAsyncIssuerQuery();
 
+  // Returns true if |issuers_| contains unconsumed certificates.
+  bool HasCurrentIssuer() const { return cur_issuer_ < issuers_.size(); }
+
   scoped_refptr<ParsedCertificate> cert_;
   CertIssuerSources* cert_issuer_sources_;
   const TrustStore* trust_store_;
@@ -160,7 +163,7 @@
   }
 
   // If there aren't any issuers left, block until async results are ready.
-  if (cur_issuer_ >= issuers_.size()) {
+  if (!HasCurrentIssuer()) {
     if (!did_async_issuer_query_) {
       // Now issue request(s) for async ones (AIA, etc).
       DoAsyncIssuerQuery();
@@ -168,22 +171,21 @@
 
     // TODO(eroman): Rather than blocking on the async requests in FIFO order,
     // consume in the order they become ready.
-    while (cur_async_request_ < pending_async_requests_.size()) {
+    while (!HasCurrentIssuer() &&
+           cur_async_request_ < pending_async_requests_.size()) {
       ParsedCertificateList new_issuers;
       pending_async_requests_[cur_async_request_]->GetNext(&new_issuers);
       if (new_issuers.empty()) {
         // Request is exhausted, no more results pending from that
         // CertIssuerSource.
         pending_async_requests_[cur_async_request_++].reset();
-        continue;
+      } else {
+        AddIssuers(std::move(new_issuers));
       }
-
-      AddIssuers(std::move(new_issuers));
-      break;
     }
   }
 
-  if (cur_issuer_ < issuers_.size()) {
+  if (HasCurrentIssuer()) {
     DVLOG(1) << "CertIssuersIter(" << CertDebugString(cert())
              << "): returning issuer " << cur_issuer_ << " of "
              << issuers_.size();
diff --git a/net/cert/internal/path_builder_unittest.cc b/net/cert/internal/path_builder_unittest.cc
index 56c7ea68..35fe154 100644
--- a/net/cert/internal/path_builder_unittest.cc
+++ b/net/cert/internal/path_builder_unittest.cc
@@ -881,8 +881,6 @@
   EXPECT_EQ(newroot_->der_cert(), path.trust_anchor->cert()->der_cert());
 }
 
-// TODO(eroman): Re-enable these tests
-#if 0
 class MockCertIssuerSourceRequest : public CertIssuerSource::Request {
  public:
   MOCK_METHOD1(GetNext, void(ParsedCertificateList*));
@@ -892,9 +890,8 @@
  public:
   MOCK_METHOD2(SyncGetIssuersOf,
                void(const ParsedCertificate*, ParsedCertificateList*));
-  MOCK_METHOD3(AsyncGetIssuersOf,
-               void(const ParsedCertificate*,
-                    std::unique_ptr<Request>*));
+  MOCK_METHOD2(AsyncGetIssuersOf,
+               void(const ParsedCertificate*, std::unique_ptr<Request>*));
 };
 
 // Helper class to pass the Request to the PathBuilder when it calls
@@ -905,7 +902,6 @@
   CertIssuerSourceRequestMover(std::unique_ptr<CertIssuerSource::Request> req)
       : request_(std::move(req)) {}
   void MoveIt(const ParsedCertificate* cert,
-              const CertIssuerSource::IssuerCallback& issuers_callback,
               std::unique_ptr<CertIssuerSource::Request>* out_req) {
     *out_req = std::move(request_);
   }
@@ -914,10 +910,23 @@
   std::unique_ptr<CertIssuerSource::Request> request_;
 };
 
+// Functor that when called with a ParsedCertificateList* will append the
+// specified certificate.
+class AppendCertToList {
+ public:
+  explicit AppendCertToList(const scoped_refptr<ParsedCertificate>& cert)
+      : cert_(cert) {}
+
+  void operator()(ParsedCertificateList* out) { out->push_back(cert_); }
+
+ private:
+  scoped_refptr<ParsedCertificate> cert_;
+};
+
 // Test that a single CertIssuerSource returning multiple async batches of
 // issuers is handled correctly. Due to the StrictMocks, it also tests that path
 // builder does not request issuers of certs that it shouldn't.
-TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) {
+TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncIssuersFromSingleSource) {
   StrictMock<MockCertIssuerSource> cert_issuer_source;
 
   // Only newroot is a trusted root.
@@ -929,7 +938,6 @@
                                &result);
   path_builder.AddCertIssuerSource(&cert_issuer_source);
 
-  CertIssuerSource::IssuerCallback target_issuers_callback;
   // Create the mock CertIssuerSource::Request...
   std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
       target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
@@ -942,26 +950,15 @@
   {
     ::testing::InSequence s;
     EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
-    EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
-        .WillOnce(
-            DoAll(SaveArg<1>(&target_issuers_callback),
-                  Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
+    EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _))
+        .WillOnce(Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt));
   }
 
-  TestClosure callback;
-  CompletionStatus rv = path_builder.Run(callback.closure());
-  ASSERT_EQ(CompletionStatus::ASYNC, rv);
-
-  ASSERT_FALSE(target_issuers_callback.is_null());
-
-  ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
-
-  // First async batch: return oldintermediate_.
   EXPECT_CALL(*target_issuers_req, GetNext(_))
-      .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_),
-                      Return(CompletionStatus::SYNC)))
-      .WillOnce(
-          DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
+      // First async batch: return oldintermediate_.
+      .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
+      // Second async batch: return newintermediate_.
+      .WillOnce(Invoke(AppendCertToList(newintermediate_)));
   {
     ::testing::InSequence s;
     // oldintermediate_ does not create a valid path, so both sync and async
@@ -969,30 +966,21 @@
     EXPECT_CALL(cert_issuer_source,
                 SyncGetIssuersOf(oldintermediate_.get(), _));
     EXPECT_CALL(cert_issuer_source,
-                AsyncGetIssuersOf(oldintermediate_.get(), _, _));
+                AsyncGetIssuersOf(oldintermediate_.get(), _));
   }
-  target_issuers_callback.Run(target_issuers_req);
-  ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
-  ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
 
-  // Second async batch: return newintermediate_.
-  EXPECT_CALL(*target_issuers_req, GetNext(_))
-      .WillOnce(DoAll(SetArgPointee<0>(newintermediate_),
-                      Return(CompletionStatus::SYNC)))
-      .WillOnce(
-          DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
   // newroot_ is in the trust store, so this path will be completed
   // synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
   EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
-  target_issuers_callback.Run(target_issuers_req);
+
+  // Ensure pathbuilder finished and filled result.
+  path_builder.Run();
+
   // Note that VerifyAndClearExpectations(target_issuers_req) is not called
   // here. PathBuilder could have destroyed it already, so just let the
   // expectations get checked by the destructor.
   ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
 
-  // Ensure pathbuilder finished and filled result.
-  callback.WaitForResult();
-
   EXPECT_TRUE(result.HasValidPath());
   ASSERT_EQ(2U, result.paths.size());
 
@@ -1029,7 +1017,6 @@
                                &result);
   path_builder.AddCertIssuerSource(&cert_issuer_source);
 
-  CertIssuerSource::IssuerCallback target_issuers_callback;
   // Create the mock CertIssuerSource::Request...
   std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
       target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
@@ -1042,26 +1029,22 @@
   {
     ::testing::InSequence s;
     EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
-    EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
-        .WillOnce(
-            DoAll(SaveArg<1>(&target_issuers_callback),
-                  Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
+    EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _))
+        .WillOnce(Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt));
   }
 
-  TestClosure callback;
-  CompletionStatus rv = path_builder.Run(callback.closure());
-  ASSERT_EQ(CompletionStatus::ASYNC, rv);
+  scoped_refptr<ParsedCertificate> oldintermediate_dupe(
+      ParsedCertificate::Create(oldintermediate_->der_cert().AsStringPiece(),
+                                {}, nullptr));
 
-  ASSERT_FALSE(target_issuers_callback.is_null());
-
-  ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
-
-  // First async batch: return oldintermediate_.
   EXPECT_CALL(*target_issuers_req, GetNext(_))
-      .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_),
-                      Return(CompletionStatus::SYNC)))
-      .WillOnce(
-          DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
+      // First async batch: return oldintermediate_.
+      .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
+      // Second async batch: return a different copy of oldintermediate_ again.
+      .WillOnce(Invoke(AppendCertToList(oldintermediate_dupe)))
+      // Third async batch: return newintermediate_.
+      .WillOnce(Invoke(AppendCertToList(newintermediate_)));
+
   {
     ::testing::InSequence s;
     // oldintermediate_ does not create a valid path, so both sync and async
@@ -1069,44 +1052,17 @@
     EXPECT_CALL(cert_issuer_source,
                 SyncGetIssuersOf(oldintermediate_.get(), _));
     EXPECT_CALL(cert_issuer_source,
-                AsyncGetIssuersOf(oldintermediate_.get(), _, _));
+                AsyncGetIssuersOf(oldintermediate_.get(), _));
   }
-  target_issuers_callback.Run(target_issuers_req);
-  ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
-  ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
 
-  // Second async batch: return a different copy of oldintermediate_ again.
-  scoped_refptr<ParsedCertificate> oldintermediate_dupe(
-      ParsedCertificate::Create(oldintermediate_->der_cert().AsStringPiece(),
-                                {}, nullptr));
-  EXPECT_CALL(*target_issuers_req, GetNext(_))
-      .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_dupe),
-                      Return(CompletionStatus::SYNC)))
-      .WillOnce(
-          DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
-  target_issuers_callback.Run(target_issuers_req);
-  // oldintermediate was already processed above, it should not generate any
-  // more requests.
-  ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
-  ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
-
-  // Third async batch: return newintermediate_.
-  EXPECT_CALL(*target_issuers_req, GetNext(_))
-      .WillOnce(DoAll(SetArgPointee<0>(newintermediate_),
-                      Return(CompletionStatus::SYNC)))
-      .WillOnce(
-          DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
   // newroot_ is in the trust store, so this path will be completed
   // synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
   EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
-  target_issuers_callback.Run(target_issuers_req);
-  // Note that VerifyAndClearExpectations(target_issuers_req) is not called
-  // here. PathBuilder could have destroyed it already, so just let the
-  // expectations get checked by the destructor.
-  ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
 
   // Ensure pathbuilder finished and filled result.
-  callback.WaitForResult();
+  path_builder.Run();
+
+  ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
 
   EXPECT_TRUE(result.HasValidPath());
   ASSERT_EQ(2U, result.paths.size());
@@ -1132,8 +1088,6 @@
   EXPECT_EQ(newroot_, path1.trust_anchor->cert());
 }
 
-#endif
-
 }  // namespace
 
 }  // namespace net
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations
index 61f8a3f6..2a1c0fe 100644
--- a/third_party/WebKit/LayoutTests/LeakExpectations
+++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -96,8 +96,6 @@
 crbug.com/506754 virtual/mojo-loading/http/tests/serviceworker/chromium/resolve-after-window-close.html [ Leak ]
 crbug.com/506754 http/tests/serviceworker/chromium/window-close-during-registration.html [ Leak ]
 crbug.com/506754 virtual/mojo-loading/http/tests/serviceworker/chromium/window-close-during-registration.html [ Leak ]
-crbug.com/506754 virtual/disable-mojo-service-worker/http/tests/serviceworker/chromium/resolve-after-window-close.html [ Leak ]
-crbug.com/506754 virtual/disable-mojo-service-worker/http/tests/serviceworker/chromium/window-close-during-registration.html [ Leak ]
 crbug.com/506754 virtual/service-worker-navigation-preload/http/tests/serviceworker/chromium/resolve-after-window-close.html [ Leak ]
 crbug.com/506754 virtual/service-worker-navigation-preload/http/tests/serviceworker/chromium/window-close-during-registration.html [ Leak ]
 
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index cd0c1216..005ce90 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -395,10 +395,8 @@
 
 # Usually plenty fast, but sometimes very slow on windows.
 crbug.com/678498 [ Win ] http/tests/serviceworker/foreign-fetch-cors.html [ Slow ]
-crbug.com/678498 [ Win ] virtual/disable-mojo-service-worker/http/tests/serviceworker/foreign-fetch-cors.html [ Slow ]
 crbug.com/678498 [ Win ] virtual/mojo-loading/http/tests/serviceworker/foreign-fetch-cors.html [ Slow ]
 crbug.com/678498 [ Win ] virtual/service-worker-navigation-preload/http/tests/serviceworker/foreign-fetch-cors.html [ Slow ]
 crbug.com/678496 [ Win ] http/tests/serviceworker/foreign-fetch-basics.html [ Slow ]
-crbug.com/678496 [ Win ] virtual/disable-mojo-service-worker/http/tests/serviceworker/foreign-fetch-basics.html [ Slow ]
 crbug.com/678496 [ Win ] virtual/mojo-loading/http/tests/serviceworker/foreign-fetch-basics.html [ Slow ]
 crbug.com/678496 [ Win ] virtual/service-worker-navigation-preload/http/tests/serviceworker/foreign-fetch-basics.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 7573a12..a7ea530c 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -619,7 +619,6 @@
 # Requires ServiceWorkerNavigationPreload feature enabled. Run under
 # virtual/service-worker-navigation-preload only.
 crbug.com/649558 http/tests/serviceworker/navigation-preload/ [ Skip ]
-crbug.com/649558 virtual/disable-mojo-service-worker/http/tests/serviceworker/navigation-preload/ [ Skip ]
 crbug.com/649558 virtual/mojo-loading/http/tests/serviceworker/navigation-preload/ [ Skip ]
 
 # Run these tests with under virtual/scalefactor... only.
@@ -2386,3 +2385,6 @@
 crbug.com/680043 sensor/ambient-light-sensor.html [ Pass Failure ]
 
 crbug.com/680050 inspector/sources/debugger-ui/watch-expressions-panel-switch.html [ Pass Timeout ]
+
+# When WebAssembly is exposed in V8 (soon), this test has the wrong number of expected Object.getOwnPropertyNames() for global object.
+crbug.com/575167 imported/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects-exceptions.html [ NeedsManualRebaseline ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index 1d1ac66d..7ed1d16 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -316,11 +316,6 @@
     "args": ["--enable-features=AsmJsToWebAssembly"]
   },
   {
-    "prefix": "disable-mojo-service-worker",
-    "base": "http/tests/serviceworker",
-    "args": ["--disable-mojo-service-worker"]
-  },
-  {
     "prefix": "service-worker-navigation-preload",
     "base": "http/tests/serviceworker",
     "args": ["--enable-features=ServiceWorkerNavigationPreload"]
diff --git a/third_party/WebKit/LayoutTests/animations/use-count-SyntheticKeyframesInCompositedCSSAnimation.html b/third_party/WebKit/LayoutTests/animations/use-count-SyntheticKeyframesInCompositedCSSAnimation.html
new file mode 100644
index 0000000..f6b97ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/animations/use-count-SyntheticKeyframesInCompositedCSSAnimation.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<style>
+@keyframes noSyntheticKeyframes {
+  from { color: black; }
+  to { color: green; }
+}
+@keyframes customPropertySyntheticKeyframes {
+  to { --x: pants; }
+}
+@keyframes nonCompositedSyntheticKeyframes {
+  to { color: green; }
+}
+@keyframes compositedSyntheticKeyframes {
+  from {
+    opacity: 0;
+  }
+  to {
+    transform: rotate(45deg);
+    opacity: 1;
+  }
+}
+#target {
+  animation-duration: 1s;
+}
+</style>
+<div id="target"></div>
+<script>
+// From UseCounter.h.
+var SyntheticKeyframesInCompositedCSSAnimation = 664;
+
+function forceStyleRecalc() {
+  getComputedStyle(target).left;
+}
+
+test(() => {
+  forceStyleRecalc();
+  assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'No animations started');
+
+  target.style.animationName = 'noSyntheticKeyframes';
+  forceStyleRecalc();
+  assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'noSyntheticKeyframes');
+
+  target.style.animationName = 'customPropertySyntheticKeyframes';
+  forceStyleRecalc();
+  assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'customPropertySyntheticKeyframes');
+
+  target.style.animationName = 'nonCompositedSyntheticKeyframes';
+  forceStyleRecalc();
+  assert_false(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'nonCompositedSyntheticKeyframes');
+
+  target.style.animationName = 'compositedSyntheticKeyframes';
+  forceStyleRecalc();
+  assert_true(internals.isUseCounted(document, SyntheticKeyframesInCompositedCSSAnimation), 'compositedSyntheticKeyframes');
+}, 'The SyntheticKeyframesInCompositedCSSAnimation use counter should only be triggered by animations with composited properties with neutral keyframes');
+</script>
diff --git a/third_party/WebKit/LayoutTests/editing/input/keyboard_event_without_focus.html b/third_party/WebKit/LayoutTests/editing/input/keyboard_event_without_focus.html
new file mode 100644
index 0000000..e0ccc38d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/input/keyboard_event_without_focus.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
+<script>
+test(() => {
+  if (!window.eventSender) {
+    assert_unreached('This test requires eventSender.');
+    return;
+  }
+
+  assert_selection(
+    '<input value="x"><input type="checkbox">',
+    selection => {
+      const document = selection.document;
+      const textField = document.querySelector('input');
+      textField.select();
+      document.querySelector('input[type=checkbox]').focus();
+      eventSender.keyDown('a');
+      // Insert |textField.value| to HTML for verification
+      textField.appendChild(document.createTextNode(textField.value));
+    },
+    '<input value="x">x</input><input type="checkbox">',
+    'unfocused text field should not insert a charcter by keyboard event');
+
+  assert_selection(
+    '<div contenteditable>|</div><input type="checkbox">',
+    selection => {
+      const document = selection.document;
+      document.querySelector('input[type=checkbox]').focus();
+      eventSender.keyDown('a');
+    },
+    '<div contenteditable>|</div><input type="checkbox">',
+    'unfocused content editable should not insert a charcter by keyboard event');
+  }, 'Keyboard event without focus should not insert a character.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change-expected.txt b/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change-expected.txt
index 22d3287..84faa03b 100644
--- a/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change-expected.txt
@@ -1,4 +1,4 @@
 This tests that when the keyPress event handler changes focus to a new form field,
-that the key will still be inserted in the original field that was the target of the event.
-   
+that the key will not be inserted in the original field that was the target of the event.
+Note: Edge will not inserted. Firefox and WebKit will insert.    
 Test Passed
diff --git a/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change.html b/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change.html
index 4b2ad6a..344c615 100644
--- a/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change.html
+++ b/third_party/WebKit/LayoutTests/fast/events/keypress-focus-change.html
@@ -15,7 +15,7 @@
             eventSender.keyDown("2");
             eventSender.keyDown("3");
         }
-        if (tf0.value == "1" && tf1.value == "23") {
+        if (tf0.value == "" && tf1.value == "23") {
             res.innerHTML = "Test Passed";
         } else {
             res.innerHTML = "Test Failed: first field = " + tf0.value + "  second field = " + tf1.value;
@@ -25,7 +25,8 @@
 </script> 
 <body onload="test()">
     This tests that when the keyPress event handler changes focus to a new form field,<br>
-    that the key will still be inserted in the original field that was the target of the event.<br>
+    that the key will not be inserted in the original field that was the target of the event.<br>
+    Note: Edge will not inserted. Firefox and WebKit will insert.
     <input id="tf0" onkeypress="document.getElementById('fr').contentDocument.getElementById('tf1').focus();">
     <iframe id="fr" style="border: solid thin black;" src="resources/keypress-frame.html"></iframe>
     <br>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js
index dceb07a..08743cc 100644
--- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js
+++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/resources/global-interface-listing-worker.js
@@ -48,6 +48,7 @@
     'Uint8ClampedArray',
     'WeakMap',
     'WeakSet',
+    'WebAssembly',
     'decodeURI',
     'decodeURIComponent',
     'encodeURI',
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
index 621d9975..53baf8a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -1,270 +1,270 @@
-CONSOLE MESSAGE: line 137: interface ByteLengthQueuingStrategy
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method size
-CONSOLE MESSAGE: line 137: interface CSSAngleValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     getter degrees
-CONSOLE MESSAGE: line 137:     getter gradians
-CONSOLE MESSAGE: line 137:     getter radians
-CONSOLE MESSAGE: line 137:     getter turns
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSCalcLength : CSSLengthValue
-CONSOLE MESSAGE: line 137:     getter ch
-CONSOLE MESSAGE: line 137:     getter cm
-CONSOLE MESSAGE: line 137:     getter em
-CONSOLE MESSAGE: line 137:     getter ex
-CONSOLE MESSAGE: line 137:     getter in
-CONSOLE MESSAGE: line 137:     getter mm
-CONSOLE MESSAGE: line 137:     getter pc
-CONSOLE MESSAGE: line 137:     getter percent
-CONSOLE MESSAGE: line 137:     getter pt
-CONSOLE MESSAGE: line 137:     getter px
-CONSOLE MESSAGE: line 137:     getter rem
-CONSOLE MESSAGE: line 137:     getter vh
-CONSOLE MESSAGE: line 137:     getter vmax
-CONSOLE MESSAGE: line 137:     getter vmin
-CONSOLE MESSAGE: line 137:     getter vw
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSImageValue : CSSResourceValue
-CONSOLE MESSAGE: line 137:     getter intrinsicHeight
-CONSOLE MESSAGE: line 137:     getter intrinsicRatio
-CONSOLE MESSAGE: line 137:     getter intrinsicWidth
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSKeywordValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     getter keywordValue
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSLengthValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     static method from
-CONSOLE MESSAGE: line 137:     method add
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method divide
-CONSOLE MESSAGE: line 137:     method multiply
-CONSOLE MESSAGE: line 137:     method subtract
-CONSOLE MESSAGE: line 137: interface CSSMatrixTransformComponent : CSSTransformComponent
-CONSOLE MESSAGE: line 137:     getter a
-CONSOLE MESSAGE: line 137:     getter b
-CONSOLE MESSAGE: line 137:     getter c
-CONSOLE MESSAGE: line 137:     getter d
-CONSOLE MESSAGE: line 137:     getter e
-CONSOLE MESSAGE: line 137:     getter f
-CONSOLE MESSAGE: line 137:     getter m11
-CONSOLE MESSAGE: line 137:     getter m12
-CONSOLE MESSAGE: line 137:     getter m13
-CONSOLE MESSAGE: line 137:     getter m14
-CONSOLE MESSAGE: line 137:     getter m21
-CONSOLE MESSAGE: line 137:     getter m22
-CONSOLE MESSAGE: line 137:     getter m23
-CONSOLE MESSAGE: line 137:     getter m24
-CONSOLE MESSAGE: line 137:     getter m31
-CONSOLE MESSAGE: line 137:     getter m32
-CONSOLE MESSAGE: line 137:     getter m33
-CONSOLE MESSAGE: line 137:     getter m34
-CONSOLE MESSAGE: line 137:     getter m41
-CONSOLE MESSAGE: line 137:     getter m42
-CONSOLE MESSAGE: line 137:     getter m43
-CONSOLE MESSAGE: line 137:     getter m44
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSNumberValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     getter value
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSPerspective : CSSTransformComponent
-CONSOLE MESSAGE: line 137:     getter length
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSPositionValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     getter x
-CONSOLE MESSAGE: line 137:     getter y
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSResourceValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     getter state
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSRotation : CSSTransformComponent
-CONSOLE MESSAGE: line 137:     getter angle
-CONSOLE MESSAGE: line 137:     getter x
-CONSOLE MESSAGE: line 137:     getter y
-CONSOLE MESSAGE: line 137:     getter z
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSScale : CSSTransformComponent
-CONSOLE MESSAGE: line 137:     getter x
-CONSOLE MESSAGE: line 137:     getter y
-CONSOLE MESSAGE: line 137:     getter z
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSSimpleLength : CSSLengthValue
-CONSOLE MESSAGE: line 137:     getter type
-CONSOLE MESSAGE: line 137:     getter value
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSSkew : CSSTransformComponent
-CONSOLE MESSAGE: line 137:     getter ax
-CONSOLE MESSAGE: line 137:     getter ay
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSStyleValue
-CONSOLE MESSAGE: line 137:     static method parse
-CONSOLE MESSAGE: line 137:     getter cssText
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSTransformComponent
-CONSOLE MESSAGE: line 137:     getter cssText
-CONSOLE MESSAGE: line 137:     method asMatrix
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method is2D
-CONSOLE MESSAGE: line 137: interface CSSTransformValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method entries
-CONSOLE MESSAGE: line 137:     method forEach
-CONSOLE MESSAGE: line 137:     method is2D
-CONSOLE MESSAGE: line 137:     method keys
-CONSOLE MESSAGE: line 137:     method values
-CONSOLE MESSAGE: line 137: interface CSSTranslation : CSSTransformComponent
-CONSOLE MESSAGE: line 137:     getter x
-CONSOLE MESSAGE: line 137:     getter y
-CONSOLE MESSAGE: line 137:     getter z
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSURLImageValue : CSSImageValue
-CONSOLE MESSAGE: line 137:     getter url
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CSSUnparsedValue : CSSStyleValue
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method entries
-CONSOLE MESSAGE: line 137:     method forEach
-CONSOLE MESSAGE: line 137:     method keys
-CONSOLE MESSAGE: line 137:     method values
-CONSOLE MESSAGE: line 137: interface CSSVariableReferenceValue
-CONSOLE MESSAGE: line 137:     getter fallback
-CONSOLE MESSAGE: line 137:     getter variable
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface CountQueuingStrategy
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method size
-CONSOLE MESSAGE: line 137: interface DataView
-CONSOLE MESSAGE: line 137:     getter buffer
-CONSOLE MESSAGE: line 137:     getter byteLength
-CONSOLE MESSAGE: line 137:     getter byteOffset
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method getFloat32
-CONSOLE MESSAGE: line 137:     method getFloat64
-CONSOLE MESSAGE: line 137:     method getInt16
-CONSOLE MESSAGE: line 137:     method getInt32
-CONSOLE MESSAGE: line 137:     method getInt8
-CONSOLE MESSAGE: line 137:     method getUint16
-CONSOLE MESSAGE: line 137:     method getUint32
-CONSOLE MESSAGE: line 137:     method getUint8
-CONSOLE MESSAGE: line 137:     method setFloat32
-CONSOLE MESSAGE: line 137:     method setFloat64
-CONSOLE MESSAGE: line 137:     method setInt16
-CONSOLE MESSAGE: line 137:     method setInt32
-CONSOLE MESSAGE: line 137:     method setInt8
-CONSOLE MESSAGE: line 137:     method setUint16
-CONSOLE MESSAGE: line 137:     method setUint32
-CONSOLE MESSAGE: line 137:     method setUint8
-CONSOLE MESSAGE: line 137: interface PaintRenderingContext2D
-CONSOLE MESSAGE: line 137:     getter currentTransform
-CONSOLE MESSAGE: line 137:     getter fillStyle
-CONSOLE MESSAGE: line 137:     getter globalAlpha
-CONSOLE MESSAGE: line 137:     getter globalCompositeOperation
-CONSOLE MESSAGE: line 137:     getter imageSmoothingEnabled
-CONSOLE MESSAGE: line 137:     getter imageSmoothingQuality
-CONSOLE MESSAGE: line 137:     getter lineCap
-CONSOLE MESSAGE: line 137:     getter lineDashOffset
-CONSOLE MESSAGE: line 137:     getter lineJoin
-CONSOLE MESSAGE: line 137:     getter lineWidth
-CONSOLE MESSAGE: line 137:     getter miterLimit
-CONSOLE MESSAGE: line 137:     getter shadowBlur
-CONSOLE MESSAGE: line 137:     getter shadowColor
-CONSOLE MESSAGE: line 137:     getter shadowOffsetX
-CONSOLE MESSAGE: line 137:     getter shadowOffsetY
-CONSOLE MESSAGE: line 137:     getter strokeStyle
-CONSOLE MESSAGE: line 137:     method arc
-CONSOLE MESSAGE: line 137:     method arcTo
-CONSOLE MESSAGE: line 137:     method beginPath
-CONSOLE MESSAGE: line 137:     method bezierCurveTo
-CONSOLE MESSAGE: line 137:     method clearRect
-CONSOLE MESSAGE: line 137:     method clip
-CONSOLE MESSAGE: line 137:     method closePath
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method createLinearGradient
-CONSOLE MESSAGE: line 137:     method createPattern
-CONSOLE MESSAGE: line 137:     method createRadialGradient
-CONSOLE MESSAGE: line 137:     method drawImage
-CONSOLE MESSAGE: line 137:     method ellipse
-CONSOLE MESSAGE: line 137:     method fill
-CONSOLE MESSAGE: line 137:     method fillRect
-CONSOLE MESSAGE: line 137:     method getLineDash
-CONSOLE MESSAGE: line 137:     method isPointInPath
-CONSOLE MESSAGE: line 137:     method isPointInStroke
-CONSOLE MESSAGE: line 137:     method lineTo
-CONSOLE MESSAGE: line 137:     method moveTo
-CONSOLE MESSAGE: line 137:     method quadraticCurveTo
-CONSOLE MESSAGE: line 137:     method rect
-CONSOLE MESSAGE: line 137:     method resetTransform
-CONSOLE MESSAGE: line 137:     method restore
-CONSOLE MESSAGE: line 137:     method rotate
-CONSOLE MESSAGE: line 137:     method save
-CONSOLE MESSAGE: line 137:     method scale
-CONSOLE MESSAGE: line 137:     method setLineDash
-CONSOLE MESSAGE: line 137:     method setTransform
-CONSOLE MESSAGE: line 137:     method stroke
-CONSOLE MESSAGE: line 137:     method strokeRect
-CONSOLE MESSAGE: line 137:     method transform
-CONSOLE MESSAGE: line 137:     method translate
-CONSOLE MESSAGE: line 137:     setter currentTransform
-CONSOLE MESSAGE: line 137:     setter fillStyle
-CONSOLE MESSAGE: line 137:     setter globalAlpha
-CONSOLE MESSAGE: line 137:     setter globalCompositeOperation
-CONSOLE MESSAGE: line 137:     setter imageSmoothingEnabled
-CONSOLE MESSAGE: line 137:     setter imageSmoothingQuality
-CONSOLE MESSAGE: line 137:     setter lineCap
-CONSOLE MESSAGE: line 137:     setter lineDashOffset
-CONSOLE MESSAGE: line 137:     setter lineJoin
-CONSOLE MESSAGE: line 137:     setter lineWidth
-CONSOLE MESSAGE: line 137:     setter miterLimit
-CONSOLE MESSAGE: line 137:     setter shadowBlur
-CONSOLE MESSAGE: line 137:     setter shadowColor
-CONSOLE MESSAGE: line 137:     setter shadowOffsetX
-CONSOLE MESSAGE: line 137:     setter shadowOffsetY
-CONSOLE MESSAGE: line 137:     setter strokeStyle
-CONSOLE MESSAGE: line 137: interface PaintSize
-CONSOLE MESSAGE: line 137:     getter height
-CONSOLE MESSAGE: line 137:     getter width
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface PaintWorkletGlobalScope : WorkletGlobalScope
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface Path2D
-CONSOLE MESSAGE: line 137:     method addPath
-CONSOLE MESSAGE: line 137:     method arc
-CONSOLE MESSAGE: line 137:     method arcTo
-CONSOLE MESSAGE: line 137:     method bezierCurveTo
-CONSOLE MESSAGE: line 137:     method closePath
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method ellipse
-CONSOLE MESSAGE: line 137:     method lineTo
-CONSOLE MESSAGE: line 137:     method moveTo
-CONSOLE MESSAGE: line 137:     method quadraticCurveTo
-CONSOLE MESSAGE: line 137:     method rect
-CONSOLE MESSAGE: line 137: interface ReadableStream
-CONSOLE MESSAGE: line 137:     getter locked
-CONSOLE MESSAGE: line 137:     method cancel
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method getReader
-CONSOLE MESSAGE: line 137:     method tee
-CONSOLE MESSAGE: line 137: interface StylePropertyMap
-CONSOLE MESSAGE: line 137:     method append
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method delete
-CONSOLE MESSAGE: line 137:     method entries
-CONSOLE MESSAGE: line 137:     method forEach
-CONSOLE MESSAGE: line 137:     method get
-CONSOLE MESSAGE: line 137:     method getAll
-CONSOLE MESSAGE: line 137:     method getProperties
-CONSOLE MESSAGE: line 137:     method has
-CONSOLE MESSAGE: line 137:     method keys
-CONSOLE MESSAGE: line 137:     method set
-CONSOLE MESSAGE: line 137:     method values
-CONSOLE MESSAGE: line 137: interface WorkletGlobalScope
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137: interface WritableStream
-CONSOLE MESSAGE: line 137:     getter locked
-CONSOLE MESSAGE: line 137:     method abort
-CONSOLE MESSAGE: line 137:     method constructor
-CONSOLE MESSAGE: line 137:     method getWriter
-CONSOLE MESSAGE: line 137: global object
-CONSOLE MESSAGE: line 137:     attribute console
-CONSOLE MESSAGE: line 137:     method gc
-CONSOLE MESSAGE: line 137:     method registerPaint
+CONSOLE MESSAGE: line 138: interface ByteLengthQueuingStrategy
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method size
+CONSOLE MESSAGE: line 138: interface CSSAngleValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     getter degrees
+CONSOLE MESSAGE: line 138:     getter gradians
+CONSOLE MESSAGE: line 138:     getter radians
+CONSOLE MESSAGE: line 138:     getter turns
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSCalcLength : CSSLengthValue
+CONSOLE MESSAGE: line 138:     getter ch
+CONSOLE MESSAGE: line 138:     getter cm
+CONSOLE MESSAGE: line 138:     getter em
+CONSOLE MESSAGE: line 138:     getter ex
+CONSOLE MESSAGE: line 138:     getter in
+CONSOLE MESSAGE: line 138:     getter mm
+CONSOLE MESSAGE: line 138:     getter pc
+CONSOLE MESSAGE: line 138:     getter percent
+CONSOLE MESSAGE: line 138:     getter pt
+CONSOLE MESSAGE: line 138:     getter px
+CONSOLE MESSAGE: line 138:     getter rem
+CONSOLE MESSAGE: line 138:     getter vh
+CONSOLE MESSAGE: line 138:     getter vmax
+CONSOLE MESSAGE: line 138:     getter vmin
+CONSOLE MESSAGE: line 138:     getter vw
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSImageValue : CSSResourceValue
+CONSOLE MESSAGE: line 138:     getter intrinsicHeight
+CONSOLE MESSAGE: line 138:     getter intrinsicRatio
+CONSOLE MESSAGE: line 138:     getter intrinsicWidth
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSKeywordValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     getter keywordValue
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSLengthValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     static method from
+CONSOLE MESSAGE: line 138:     method add
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method divide
+CONSOLE MESSAGE: line 138:     method multiply
+CONSOLE MESSAGE: line 138:     method subtract
+CONSOLE MESSAGE: line 138: interface CSSMatrixTransformComponent : CSSTransformComponent
+CONSOLE MESSAGE: line 138:     getter a
+CONSOLE MESSAGE: line 138:     getter b
+CONSOLE MESSAGE: line 138:     getter c
+CONSOLE MESSAGE: line 138:     getter d
+CONSOLE MESSAGE: line 138:     getter e
+CONSOLE MESSAGE: line 138:     getter f
+CONSOLE MESSAGE: line 138:     getter m11
+CONSOLE MESSAGE: line 138:     getter m12
+CONSOLE MESSAGE: line 138:     getter m13
+CONSOLE MESSAGE: line 138:     getter m14
+CONSOLE MESSAGE: line 138:     getter m21
+CONSOLE MESSAGE: line 138:     getter m22
+CONSOLE MESSAGE: line 138:     getter m23
+CONSOLE MESSAGE: line 138:     getter m24
+CONSOLE MESSAGE: line 138:     getter m31
+CONSOLE MESSAGE: line 138:     getter m32
+CONSOLE MESSAGE: line 138:     getter m33
+CONSOLE MESSAGE: line 138:     getter m34
+CONSOLE MESSAGE: line 138:     getter m41
+CONSOLE MESSAGE: line 138:     getter m42
+CONSOLE MESSAGE: line 138:     getter m43
+CONSOLE MESSAGE: line 138:     getter m44
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSNumberValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     getter value
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSPerspective : CSSTransformComponent
+CONSOLE MESSAGE: line 138:     getter length
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSPositionValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     getter x
+CONSOLE MESSAGE: line 138:     getter y
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSResourceValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     getter state
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSRotation : CSSTransformComponent
+CONSOLE MESSAGE: line 138:     getter angle
+CONSOLE MESSAGE: line 138:     getter x
+CONSOLE MESSAGE: line 138:     getter y
+CONSOLE MESSAGE: line 138:     getter z
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSScale : CSSTransformComponent
+CONSOLE MESSAGE: line 138:     getter x
+CONSOLE MESSAGE: line 138:     getter y
+CONSOLE MESSAGE: line 138:     getter z
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSSimpleLength : CSSLengthValue
+CONSOLE MESSAGE: line 138:     getter type
+CONSOLE MESSAGE: line 138:     getter value
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSSkew : CSSTransformComponent
+CONSOLE MESSAGE: line 138:     getter ax
+CONSOLE MESSAGE: line 138:     getter ay
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSStyleValue
+CONSOLE MESSAGE: line 138:     static method parse
+CONSOLE MESSAGE: line 138:     getter cssText
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSTransformComponent
+CONSOLE MESSAGE: line 138:     getter cssText
+CONSOLE MESSAGE: line 138:     method asMatrix
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method is2D
+CONSOLE MESSAGE: line 138: interface CSSTransformValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method entries
+CONSOLE MESSAGE: line 138:     method forEach
+CONSOLE MESSAGE: line 138:     method is2D
+CONSOLE MESSAGE: line 138:     method keys
+CONSOLE MESSAGE: line 138:     method values
+CONSOLE MESSAGE: line 138: interface CSSTranslation : CSSTransformComponent
+CONSOLE MESSAGE: line 138:     getter x
+CONSOLE MESSAGE: line 138:     getter y
+CONSOLE MESSAGE: line 138:     getter z
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSURLImageValue : CSSImageValue
+CONSOLE MESSAGE: line 138:     getter url
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CSSUnparsedValue : CSSStyleValue
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method entries
+CONSOLE MESSAGE: line 138:     method forEach
+CONSOLE MESSAGE: line 138:     method keys
+CONSOLE MESSAGE: line 138:     method values
+CONSOLE MESSAGE: line 138: interface CSSVariableReferenceValue
+CONSOLE MESSAGE: line 138:     getter fallback
+CONSOLE MESSAGE: line 138:     getter variable
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface CountQueuingStrategy
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method size
+CONSOLE MESSAGE: line 138: interface DataView
+CONSOLE MESSAGE: line 138:     getter buffer
+CONSOLE MESSAGE: line 138:     getter byteLength
+CONSOLE MESSAGE: line 138:     getter byteOffset
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method getFloat32
+CONSOLE MESSAGE: line 138:     method getFloat64
+CONSOLE MESSAGE: line 138:     method getInt16
+CONSOLE MESSAGE: line 138:     method getInt32
+CONSOLE MESSAGE: line 138:     method getInt8
+CONSOLE MESSAGE: line 138:     method getUint16
+CONSOLE MESSAGE: line 138:     method getUint32
+CONSOLE MESSAGE: line 138:     method getUint8
+CONSOLE MESSAGE: line 138:     method setFloat32
+CONSOLE MESSAGE: line 138:     method setFloat64
+CONSOLE MESSAGE: line 138:     method setInt16
+CONSOLE MESSAGE: line 138:     method setInt32
+CONSOLE MESSAGE: line 138:     method setInt8
+CONSOLE MESSAGE: line 138:     method setUint16
+CONSOLE MESSAGE: line 138:     method setUint32
+CONSOLE MESSAGE: line 138:     method setUint8
+CONSOLE MESSAGE: line 138: interface PaintRenderingContext2D
+CONSOLE MESSAGE: line 138:     getter currentTransform
+CONSOLE MESSAGE: line 138:     getter fillStyle
+CONSOLE MESSAGE: line 138:     getter globalAlpha
+CONSOLE MESSAGE: line 138:     getter globalCompositeOperation
+CONSOLE MESSAGE: line 138:     getter imageSmoothingEnabled
+CONSOLE MESSAGE: line 138:     getter imageSmoothingQuality
+CONSOLE MESSAGE: line 138:     getter lineCap
+CONSOLE MESSAGE: line 138:     getter lineDashOffset
+CONSOLE MESSAGE: line 138:     getter lineJoin
+CONSOLE MESSAGE: line 138:     getter lineWidth
+CONSOLE MESSAGE: line 138:     getter miterLimit
+CONSOLE MESSAGE: line 138:     getter shadowBlur
+CONSOLE MESSAGE: line 138:     getter shadowColor
+CONSOLE MESSAGE: line 138:     getter shadowOffsetX
+CONSOLE MESSAGE: line 138:     getter shadowOffsetY
+CONSOLE MESSAGE: line 138:     getter strokeStyle
+CONSOLE MESSAGE: line 138:     method arc
+CONSOLE MESSAGE: line 138:     method arcTo
+CONSOLE MESSAGE: line 138:     method beginPath
+CONSOLE MESSAGE: line 138:     method bezierCurveTo
+CONSOLE MESSAGE: line 138:     method clearRect
+CONSOLE MESSAGE: line 138:     method clip
+CONSOLE MESSAGE: line 138:     method closePath
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method createLinearGradient
+CONSOLE MESSAGE: line 138:     method createPattern
+CONSOLE MESSAGE: line 138:     method createRadialGradient
+CONSOLE MESSAGE: line 138:     method drawImage
+CONSOLE MESSAGE: line 138:     method ellipse
+CONSOLE MESSAGE: line 138:     method fill
+CONSOLE MESSAGE: line 138:     method fillRect
+CONSOLE MESSAGE: line 138:     method getLineDash
+CONSOLE MESSAGE: line 138:     method isPointInPath
+CONSOLE MESSAGE: line 138:     method isPointInStroke
+CONSOLE MESSAGE: line 138:     method lineTo
+CONSOLE MESSAGE: line 138:     method moveTo
+CONSOLE MESSAGE: line 138:     method quadraticCurveTo
+CONSOLE MESSAGE: line 138:     method rect
+CONSOLE MESSAGE: line 138:     method resetTransform
+CONSOLE MESSAGE: line 138:     method restore
+CONSOLE MESSAGE: line 138:     method rotate
+CONSOLE MESSAGE: line 138:     method save
+CONSOLE MESSAGE: line 138:     method scale
+CONSOLE MESSAGE: line 138:     method setLineDash
+CONSOLE MESSAGE: line 138:     method setTransform
+CONSOLE MESSAGE: line 138:     method stroke
+CONSOLE MESSAGE: line 138:     method strokeRect
+CONSOLE MESSAGE: line 138:     method transform
+CONSOLE MESSAGE: line 138:     method translate
+CONSOLE MESSAGE: line 138:     setter currentTransform
+CONSOLE MESSAGE: line 138:     setter fillStyle
+CONSOLE MESSAGE: line 138:     setter globalAlpha
+CONSOLE MESSAGE: line 138:     setter globalCompositeOperation
+CONSOLE MESSAGE: line 138:     setter imageSmoothingEnabled
+CONSOLE MESSAGE: line 138:     setter imageSmoothingQuality
+CONSOLE MESSAGE: line 138:     setter lineCap
+CONSOLE MESSAGE: line 138:     setter lineDashOffset
+CONSOLE MESSAGE: line 138:     setter lineJoin
+CONSOLE MESSAGE: line 138:     setter lineWidth
+CONSOLE MESSAGE: line 138:     setter miterLimit
+CONSOLE MESSAGE: line 138:     setter shadowBlur
+CONSOLE MESSAGE: line 138:     setter shadowColor
+CONSOLE MESSAGE: line 138:     setter shadowOffsetX
+CONSOLE MESSAGE: line 138:     setter shadowOffsetY
+CONSOLE MESSAGE: line 138:     setter strokeStyle
+CONSOLE MESSAGE: line 138: interface PaintSize
+CONSOLE MESSAGE: line 138:     getter height
+CONSOLE MESSAGE: line 138:     getter width
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface PaintWorkletGlobalScope : WorkletGlobalScope
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface Path2D
+CONSOLE MESSAGE: line 138:     method addPath
+CONSOLE MESSAGE: line 138:     method arc
+CONSOLE MESSAGE: line 138:     method arcTo
+CONSOLE MESSAGE: line 138:     method bezierCurveTo
+CONSOLE MESSAGE: line 138:     method closePath
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method ellipse
+CONSOLE MESSAGE: line 138:     method lineTo
+CONSOLE MESSAGE: line 138:     method moveTo
+CONSOLE MESSAGE: line 138:     method quadraticCurveTo
+CONSOLE MESSAGE: line 138:     method rect
+CONSOLE MESSAGE: line 138: interface ReadableStream
+CONSOLE MESSAGE: line 138:     getter locked
+CONSOLE MESSAGE: line 138:     method cancel
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method getReader
+CONSOLE MESSAGE: line 138:     method tee
+CONSOLE MESSAGE: line 138: interface StylePropertyMap
+CONSOLE MESSAGE: line 138:     method append
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method delete
+CONSOLE MESSAGE: line 138:     method entries
+CONSOLE MESSAGE: line 138:     method forEach
+CONSOLE MESSAGE: line 138:     method get
+CONSOLE MESSAGE: line 138:     method getAll
+CONSOLE MESSAGE: line 138:     method getProperties
+CONSOLE MESSAGE: line 138:     method has
+CONSOLE MESSAGE: line 138:     method keys
+CONSOLE MESSAGE: line 138:     method set
+CONSOLE MESSAGE: line 138:     method values
+CONSOLE MESSAGE: line 138: interface WorkletGlobalScope
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138: interface WritableStream
+CONSOLE MESSAGE: line 138:     getter locked
+CONSOLE MESSAGE: line 138:     method abort
+CONSOLE MESSAGE: line 138:     method constructor
+CONSOLE MESSAGE: line 138:     method getWriter
+CONSOLE MESSAGE: line 138: global object
+CONSOLE MESSAGE: line 138:     attribute console
+CONSOLE MESSAGE: line 138:     method gc
+CONSOLE MESSAGE: line 138:     method registerPaint
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js
index 2c12314..0f2ae2b 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/resources/global-interface-listing-worklet.js
@@ -48,6 +48,7 @@
     'Uint8ClampedArray',
     'WeakMap',
     'WeakSet',
+    'WebAssembly',
     'decodeURI',
     'decodeURIComponent',
     'encodeURI',
diff --git a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
index f7d6294..ed51ed4 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE WARNING: line 94: 'webkitURL' is deprecated. Please use 'URL' instead.
+CONSOLE WARNING: line 95: 'webkitURL' is deprecated. Please use 'URL' instead.
 This test documents all interface attributes and methods on the global window object and element instances.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
index f7d6294..ed51ed4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE WARNING: line 94: 'webkitURL' is deprecated. Please use 'URL' instead.
+CONSOLE WARNING: line 95: 'webkitURL' is deprecated. Please use 'URL' instead.
 This test documents all interface attributes and methods on the global window object and element instances.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/WebKit/LayoutTests/virtual/disable-mojo-service-worker/http/tests/serviceworker/README.txt b/third_party/WebKit/LayoutTests/virtual/disable-mojo-service-worker/http/tests/serviceworker/README.txt
deleted file mode 100644
index 3377d19f..0000000
--- a/third_party/WebKit/LayoutTests/virtual/disable-mojo-service-worker/http/tests/serviceworker/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-This directory is for testing the service workers with mojo by using '--disable-mojo-service-worker' flag.
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
index 8487d96..30546cd 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE WARNING: line 94: 'webkitURL' is deprecated. Please use 'URL' instead.
+CONSOLE WARNING: line 95: 'webkitURL' is deprecated. Please use 'URL' instead.
 This test documents all interface attributes and methods on the global window object and element instances.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
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 697be95..95d13d1f 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE WARNING: line 94: 'webkitURL' is deprecated. Please use 'URL' instead.
+CONSOLE WARNING: line 95: 'webkitURL' is deprecated. Please use 'URL' instead.
 This test documents all interface attributes and methods on the global window object and element instances.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js b/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js
index 5ff26530..0c4f35c 100644
--- a/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js
+++ b/third_party/WebKit/LayoutTests/webexposed/resources/global-interface-listing.js
@@ -74,6 +74,7 @@
     'Uint8ClampedArray',
     'WeakMap',
     'WeakSet',
+    'WebAssembly',
     'decodeURI',
     'decodeURIComponent',
     'encodeURI',
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
index 0eaf581..14e7e7f1 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -229,7 +229,7 @@
       info.GetIsolate(), ExceptionState::SetterContext, "CSSStyleDeclaration",
       getPropertyName(resolveCSSPropertyID(unresolvedProperty)));
   impl->setPropertyInternal(unresolvedProperty, String(), propertyValue, false,
-                            nullptr, exceptionState);
+                            exceptionState);
 
   v8SetReturnValue(info, value);
 }
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator.py b/third_party/WebKit/Source/bindings/scripts/code_generator.py
index cc69d997..e6e1764e 100644
--- a/third_party/WebKit/Source/bindings/scripts/code_generator.py
+++ b/third_party/WebKit/Source/bindings/scripts/code_generator.py
@@ -69,7 +69,7 @@
     if not name:
         return code
 
-    function = 'RuntimeEnabledFeatures::%sEnabled()' % v8_utilities.uncapitalize(name)
+    function = v8_utilities.runtime_enabled_function(name)
     return generate_indented_conditional(code, function)
 
 
@@ -88,6 +88,7 @@
         'format_blink_cpp_source_code': format_blink_cpp_source_code,
         'format_remove_duplicates': format_remove_duplicates,
         'runtime_enabled': runtime_enabled_if,
+        'runtime_enabled_function': v8_utilities.runtime_enabled_function,
         'secure_context': secure_context_if,
         'unique_by': unique_by})
     jinja_env.filters.update(constant_filters())
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
index 4fb4ea48..a0da305 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_utilities.py
@@ -112,6 +112,11 @@
     return name[0].lower() + name[1:]
 
 
+def runtime_enabled_function(name):
+    """Returns a function call of a runtime enabled feature."""
+    return 'RuntimeEnabledFeatures::%sEnabled()' % uncapitalize(name)
+
+
 def unique_by(dict_list, key):
     """Returns elements from a list of dictionaries with unique values for the named key."""
     keys_seen = set()
@@ -294,8 +299,7 @@
         exposed = ('executionContext->%s()' %
                    EXPOSED_EXECUTION_CONTEXT_METHOD[exposure.exposed])
         if exposure.runtime_enabled is not None:
-            runtime_enabled = ('RuntimeEnabledFeatures::%sEnabled()' %
-                               uncapitalize(exposure.runtime_enabled))
+            runtime_enabled = (runtime_enabled_function(exposure.runtime_enabled))
             return '({0} && {1})'.format(exposed, runtime_enabled)
         return exposed
 
diff --git a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
index 4f5907c..bbea073 100644
--- a/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/interface_base.cpp.tmpl
@@ -405,6 +405,13 @@
   interfaceTemplate->SetLength({{interface_length}});
   {% endif %}
   {% endif %}{# is_partial #}
+
+  {% if runtime_enabled_feature_name %}
+  if (!{{runtime_enabled_feature_name | runtime_enabled_function}}) {
+    return;
+  }
+  {% endif %}
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
@@ -427,7 +434,6 @@
   {% endif %}
 
   // Register DOM constants, attributes and operations.
-  {% filter runtime_enabled(runtime_enabled_feature_name) %}
   {% if constants %}
   {{install_constants() | indent(2)}}
   {% endif %}
@@ -443,7 +449,6 @@
   {% if methods | has_method_configuration(is_partial) %}
   V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, {{'%sMethods' % v8_class}}, {{'WTF_ARRAY_LENGTH(%sMethods)' % v8_class}});
   {% endif %}
-  {% endfilter %}
 
   {% if has_access_check_callbacks and not is_partial %}
   // Cross-origin access check
@@ -454,9 +459,9 @@
   instanceTemplate->SetAccessCheckCallbackAndHandler({{cpp_class}}V8Internal::securityCheck, v8::NamedPropertyHandlerConfiguration({{cross_origin_named_getter}}, {{cross_origin_named_setter}}, nullptr, nullptr, {{cross_origin_named_enumerator}}), v8::IndexedPropertyHandlerConfiguration({{cross_origin_indexed_getter}}), v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&{{v8_class}}::wrapperTypeInfo)));
   {% endif %}
 
-  {% for group in runtime_enabled_attributes | groupby('runtime_enabled_feature_name') %}
-  {% filter runtime_enabled(group.list[0].runtime_enabled_feature_name) %}
-  {% for attribute in group.list | unique_by('name') | sort %}
+  {% for feature_name, attribute_list in runtime_enabled_attributes | groupby('runtime_enabled_feature_name') %}
+  {% filter runtime_enabled(feature_name) %}
+  {% for attribute in attribute_list | unique_by('name') | sort %}
   {% if attribute.is_data_type_property %}
   const V8DOMConfiguration::AttributeConfiguration attribute{{attribute.name}}Configuration = {{attribute_configuration(attribute)}};
   V8DOMConfiguration::installAttribute(isolate, world, instanceTemplate, prototypeTemplate, attribute{{attribute.name}}Configuration);
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
index bd899e7..0384cde 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8SVGTestInterface.cpp
@@ -98,6 +98,7 @@
 static void installV8SVGTestInterfaceTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8SVGTestInterface::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8SVGTestInterface::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp
index f088248..bd85132 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestCallbackFunctions.cpp
@@ -298,6 +298,7 @@
 static void installV8TestCallbackFunctionsTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestCallbackFunctions::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestCallbackFunctions::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
index 08ca54e5..70cb4011 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestConstants.cpp
@@ -72,6 +72,7 @@
 static void installV8TestConstantsTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestConstants::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestConstants::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp
index 90cd3a7..ec12c7d5 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestException.cpp
@@ -136,6 +136,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestException::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestException::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestException::constructorCallback);
   interfaceTemplate->SetLength(1);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
index 29634832..7de5c0c6 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexed.cpp
@@ -170,6 +170,7 @@
 static void installV8TestIntegerIndexedTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestIntegerIndexed::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestIntegerIndexed::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
index 83f62083..e31c251 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedGlobal.cpp
@@ -170,6 +170,7 @@
 static void installV8TestIntegerIndexedGlobalTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestIntegerIndexedGlobal::wrapperTypeInfo.interfaceName, V8TestIntegerIndexedGlobal::domTemplateForNamedPropertiesObject(isolate, world), V8TestIntegerIndexedGlobal::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
index c76c2617..00a245b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestIntegerIndexedPrimaryGlobal.cpp
@@ -170,6 +170,7 @@
 static void installV8TestIntegerIndexedPrimaryGlobalTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestIntegerIndexedPrimaryGlobal::wrapperTypeInfo.interfaceName, V8TestIntegerIndexedPrimaryGlobal::domTemplateForNamedPropertiesObject(isolate, world), V8TestIntegerIndexedPrimaryGlobal::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
index bc7958f..c698c8f 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -2647,6 +2647,11 @@
 void V8TestInterface::installV8TestInterfaceTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterface::wrapperTypeInfo.interfaceName, V8TestInterfaceEmpty::domTemplate(isolate, world), V8TestInterface::internalFieldCount);
+
+  if (!RuntimeEnabledFeatures::featureNameEnabled()) {
+    return;
+  }
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
@@ -2655,25 +2660,23 @@
   ALLOW_UNUSED_LOCAL(prototypeTemplate);
 
   // Register DOM constants, attributes and operations.
-  if (RuntimeEnabledFeatures::featureNameEnabled()) {
-    const V8DOMConfiguration::ConstantConfiguration V8TestInterfaceConstants[] = {
-        {"UNSIGNED_LONG", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedLong},
-        {"CONST_JAVASCRIPT", 1, 0, V8DOMConfiguration::ConstantTypeShort},
-        {"IMPLEMENTS_CONSTANT_1", 1, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
-        {"IMPLEMENTS_CONSTANT_2", 2, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
-        {"PARTIAL2_UNSIGNED_SHORT", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
-    };
-    V8DOMConfiguration::installConstants(isolate, interfaceTemplate, prototypeTemplate, V8TestInterfaceConstants, WTF_ARRAY_LENGTH(V8TestInterfaceConstants));
-    if (RuntimeEnabledFeatures::partialFeatureNameEnabled()) {
-      const V8DOMConfiguration::ConstantConfiguration constantPartialUnsignedShortConfiguration = {"PARTIAL_UNSIGNED_SHORT", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedShort};
-      V8DOMConfiguration::installConstant(isolate, interfaceTemplate, prototypeTemplate, constantPartialUnsignedShortConfiguration);
-      const V8DOMConfiguration::ConstantConfiguration constantPartialDoubleConfiguration = {"PARTIAL_DOUBLE", 0, 3.14, V8DOMConfiguration::ConstantTypeDouble};
-      V8DOMConfiguration::installConstant(isolate, interfaceTemplate, prototypeTemplate, constantPartialDoubleConfiguration);
-    }
-    V8DOMConfiguration::installLazyDataAttributes(isolate, world, instanceTemplate, prototypeTemplate, V8TestInterfaceLazyDataAttributes, WTF_ARRAY_LENGTH(V8TestInterfaceLazyDataAttributes));
-    V8DOMConfiguration::installAccessors(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterfaceAccessors, WTF_ARRAY_LENGTH(V8TestInterfaceAccessors));
-    V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterfaceMethods, WTF_ARRAY_LENGTH(V8TestInterfaceMethods));
+  const V8DOMConfiguration::ConstantConfiguration V8TestInterfaceConstants[] = {
+      {"UNSIGNED_LONG", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedLong},
+      {"CONST_JAVASCRIPT", 1, 0, V8DOMConfiguration::ConstantTypeShort},
+      {"IMPLEMENTS_CONSTANT_1", 1, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
+      {"IMPLEMENTS_CONSTANT_2", 2, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
+      {"PARTIAL2_UNSIGNED_SHORT", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
+  };
+  V8DOMConfiguration::installConstants(isolate, interfaceTemplate, prototypeTemplate, V8TestInterfaceConstants, WTF_ARRAY_LENGTH(V8TestInterfaceConstants));
+  if (RuntimeEnabledFeatures::partialFeatureNameEnabled()) {
+    const V8DOMConfiguration::ConstantConfiguration constantPartialUnsignedShortConfiguration = {"PARTIAL_UNSIGNED_SHORT", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedShort};
+    V8DOMConfiguration::installConstant(isolate, interfaceTemplate, prototypeTemplate, constantPartialUnsignedShortConfiguration);
+    const V8DOMConfiguration::ConstantConfiguration constantPartialDoubleConfiguration = {"PARTIAL_DOUBLE", 0, 3.14, V8DOMConfiguration::ConstantTypeDouble};
+    V8DOMConfiguration::installConstant(isolate, interfaceTemplate, prototypeTemplate, constantPartialDoubleConfiguration);
   }
+  V8DOMConfiguration::installLazyDataAttributes(isolate, world, instanceTemplate, prototypeTemplate, V8TestInterfaceLazyDataAttributes, WTF_ARRAY_LENGTH(V8TestInterfaceLazyDataAttributes));
+  V8DOMConfiguration::installAccessors(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterfaceAccessors, WTF_ARRAY_LENGTH(V8TestInterfaceAccessors));
+  V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterfaceMethods, WTF_ARRAY_LENGTH(V8TestInterfaceMethods));
 
   if (RuntimeEnabledFeatures::featureNameEnabled()) {
     const V8DOMConfiguration::AccessorConfiguration accessorconditionalReadOnlyLongAttributeConfiguration = {"conditionalReadOnlyLongAttribute", TestInterfaceImplementationV8Internal::conditionalReadOnlyLongAttributeAttributeGetterCallback, 0, 0, 0, nullptr, 0, v8::DEFAULT, static_cast<v8::PropertyAttribute>(v8::ReadOnly), V8DOMConfiguration::OnPrototype, V8DOMConfiguration::CheckHolder};
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
index c6ba1e7e..edd0f2b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface2.cpp
@@ -628,6 +628,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterface2::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterface2::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterface2::constructorCallback);
   interfaceTemplate->SetLength(0);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
index 9a1b20f..fedb667 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface3.cpp
@@ -274,6 +274,7 @@
 static void installV8TestInterface3Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterface3::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterface3::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
index 6d87a40..a17fe42c2 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCheckSecurity.cpp
@@ -474,6 +474,7 @@
 static void installV8TestInterfaceCheckSecurityTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceCheckSecurity::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceCheckSecurity::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
index b8148e4..0a46fdab 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor.cpp
@@ -385,6 +385,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor::constructorCallback);
   interfaceTemplate->SetLength(0);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
index a9b60dc..2e804ee 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor2.cpp
@@ -238,6 +238,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor2::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor2::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor2::constructorCallback);
   interfaceTemplate->SetLength(1);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
index 62749f4..68993d8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor3.cpp
@@ -91,6 +91,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor3::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor3::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor3::constructorCallback);
   interfaceTemplate->SetLength(1);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
index 2e197d8..7e68032 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceConstructor4.cpp
@@ -124,6 +124,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceConstructor4::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceConstructor4::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterfaceConstructor4::constructorCallback);
   interfaceTemplate->SetLength(1);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
index a0e8cb46..600aaca 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceCustomConstructor.cpp
@@ -74,6 +74,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceCustomConstructor::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceCustomConstructor::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterfaceCustomConstructor::constructorCallback);
   interfaceTemplate->SetLength(0);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
index 250dad7..7abe8b3 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceDocument.cpp
@@ -102,6 +102,7 @@
 static void installV8TestInterfaceDocumentTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceDocument::wrapperTypeInfo.interfaceName, V8Document::domTemplate(isolate, world), V8TestInterfaceDocument::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
index 55f5c3c..f8778e7 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEmpty.cpp
@@ -57,6 +57,7 @@
 static void installV8TestInterfaceEmptyTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceEmpty::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceEmpty::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
index 2dd03b5..57a35cd 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventInitConstructor.cpp
@@ -133,6 +133,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceEventInitConstructor::wrapperTypeInfo.interfaceName, V8Event::domTemplate(isolate, world), V8TestInterfaceEventInitConstructor::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterfaceEventInitConstructor::constructorCallback);
   interfaceTemplate->SetLength(2);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
index 7d35632..4599e4c 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceEventTarget.cpp
@@ -103,6 +103,7 @@
 static void installV8TestInterfaceEventTargetTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceEventTarget::wrapperTypeInfo.interfaceName, V8EventTarget::domTemplate(isolate, world), V8TestInterfaceEventTarget::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
index 82a6864..df42d4b 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceGarbageCollected.cpp
@@ -376,6 +376,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceGarbageCollected::wrapperTypeInfo.interfaceName, V8EventTarget::domTemplate(isolate, world), V8TestInterfaceGarbageCollected::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestInterfaceGarbageCollected::constructorCallback);
   interfaceTemplate->SetLength(1);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
index 13a184d7..200c443a 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor.cpp
@@ -176,6 +176,7 @@
 static void installV8TestInterfaceNamedConstructorTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceNamedConstructor::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceNamedConstructor::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
index 9aabdd634..bac9461 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNamedConstructor2.cpp
@@ -112,6 +112,7 @@
 static void installV8TestInterfaceNamedConstructor2Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceNamedConstructor2::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceNamedConstructor2::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
index 555ecf0e..15d3f122 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
@@ -351,6 +351,7 @@
 static void installV8TestInterfaceNodeTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceNode::wrapperTypeInfo.interfaceName, V8Node::domTemplate(isolate, world), V8TestInterfaceNode::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp
index 81983d6..fec0b1e00 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceOriginTrialEnabled.cpp
@@ -251,6 +251,7 @@
 static void installV8TestInterfaceOriginTrialEnabledTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceOriginTrialEnabled::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceOriginTrialEnabled::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp
index 82dcdcd..d95fc51 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceSecureContext.cpp
@@ -334,6 +334,7 @@
 static void installV8TestInterfaceSecureContextTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterfaceSecureContext::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestInterfaceSecureContext::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
index 9de14aa..f3d131ce 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestNode.cpp
@@ -214,6 +214,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestNode::wrapperTypeInfo.interfaceName, V8Node::domTemplate(isolate, world), V8TestNode::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestNode::constructorCallback);
   interfaceTemplate->SetLength(0);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index 2ef600f8..d482b46 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -11584,6 +11584,7 @@
 static void installV8TestObjectTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestObject::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestObject::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
index 75af08b..bba2b50 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperations.cpp
@@ -177,6 +177,7 @@
 static void installV8TestSpecialOperationsTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestSpecialOperations::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestSpecialOperations::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
index 63434a6..d3d2319 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestSpecialOperationsNotEnumerable.cpp
@@ -91,6 +91,7 @@
 static void installV8TestSpecialOperationsNotEnumerableTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestSpecialOperationsNotEnumerable::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestSpecialOperationsNotEnumerable::internalFieldCount);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
index 66cef44..a7638b60 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestTypedefs.cpp
@@ -360,6 +360,7 @@
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestTypedefs::wrapperTypeInfo.interfaceName, v8::Local<v8::FunctionTemplate>(), V8TestTypedefs::internalFieldCount);
   interfaceTemplate->SetCallHandler(V8TestTypedefs::constructorCallback);
   interfaceTemplate->SetLength(1);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp
index 7e3c7e4..84203557 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface2Partial.cpp
@@ -78,6 +78,7 @@
 void V8TestInterface2Partial::installV8TestInterface2Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8TestInterface2::installV8TestInterface2Template(isolate, world, interfaceTemplate);
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
index 7402dd2..9c2d7bf 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterface5.cpp
@@ -900,6 +900,11 @@
 static void installV8TestInterface5Template(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8DOMConfiguration::initializeDOMInterfaceTemplate(isolate, interfaceTemplate, V8TestInterface5::wrapperTypeInfo.interfaceName, V8TestInterfaceEmpty::domTemplate(isolate, world), V8TestInterface5::internalFieldCount);
+
+  if (!RuntimeEnabledFeatures::featureNameEnabled()) {
+    return;
+  }
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
@@ -908,16 +913,14 @@
   ALLOW_UNUSED_LOCAL(prototypeTemplate);
 
   // Register DOM constants, attributes and operations.
-  if (RuntimeEnabledFeatures::featureNameEnabled()) {
-    const V8DOMConfiguration::ConstantConfiguration V8TestInterface5Constants[] = {
-        {"UNSIGNED_LONG", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedLong},
-        {"CONST_JAVASCRIPT", 1, 0, V8DOMConfiguration::ConstantTypeShort},
-    };
-    V8DOMConfiguration::installConstants(isolate, interfaceTemplate, prototypeTemplate, V8TestInterface5Constants, WTF_ARRAY_LENGTH(V8TestInterface5Constants));
-    V8DOMConfiguration::installLazyDataAttributes(isolate, world, instanceTemplate, prototypeTemplate, V8TestInterface5LazyDataAttributes, WTF_ARRAY_LENGTH(V8TestInterface5LazyDataAttributes));
-    V8DOMConfiguration::installAccessors(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterface5Accessors, WTF_ARRAY_LENGTH(V8TestInterface5Accessors));
-    V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterface5Methods, WTF_ARRAY_LENGTH(V8TestInterface5Methods));
-  }
+  const V8DOMConfiguration::ConstantConfiguration V8TestInterface5Constants[] = {
+      {"UNSIGNED_LONG", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedLong},
+      {"CONST_JAVASCRIPT", 1, 0, V8DOMConfiguration::ConstantTypeShort},
+  };
+  V8DOMConfiguration::installConstants(isolate, interfaceTemplate, prototypeTemplate, V8TestInterface5Constants, WTF_ARRAY_LENGTH(V8TestInterface5Constants));
+  V8DOMConfiguration::installLazyDataAttributes(isolate, world, instanceTemplate, prototypeTemplate, V8TestInterface5LazyDataAttributes, WTF_ARRAY_LENGTH(V8TestInterface5LazyDataAttributes));
+  V8DOMConfiguration::installAccessors(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterface5Accessors, WTF_ARRAY_LENGTH(V8TestInterface5Accessors));
+  V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterface5Methods, WTF_ARRAY_LENGTH(V8TestInterface5Methods));
 
   // Indexed properties
   v8::IndexedPropertyHandlerConfiguration indexedPropertyHandlerConfig(TestInterface5ImplementationV8Internal::indexedPropertyGetterCallback, TestInterface5ImplementationV8Internal::indexedPropertySetterCallback, 0, TestInterface5ImplementationV8Internal::indexedPropertyDeleterCallback, indexedPropertyEnumerator<TestInterface5Implementation>, v8::Local<v8::Value>(), v8::PropertyHandlerFlags::kNone);
diff --git a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
index 539b8e5..5d4b26a8 100644
--- a/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/modules/V8TestInterfacePartial.cpp
@@ -383,6 +383,11 @@
 void V8TestInterfacePartial::installV8TestInterfaceTemplate(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::FunctionTemplate> interfaceTemplate) {
   // Initialize the interface object's template.
   V8TestInterface::installV8TestInterfaceTemplate(isolate, world, interfaceTemplate);
+
+  if (!RuntimeEnabledFeatures::featureNameEnabled()) {
+    return;
+  }
+
   v8::Local<v8::Signature> signature = v8::Signature::New(isolate, interfaceTemplate);
   ALLOW_UNUSED_LOCAL(signature);
   v8::Local<v8::ObjectTemplate> instanceTemplate = interfaceTemplate->InstanceTemplate();
@@ -391,13 +396,11 @@
   ALLOW_UNUSED_LOCAL(prototypeTemplate);
 
   // Register DOM constants, attributes and operations.
-  if (RuntimeEnabledFeatures::featureNameEnabled()) {
-    const V8DOMConfiguration::ConstantConfiguration V8TestInterfaceConstants[] = {
-        {"PARTIAL3_UNSIGNED_SHORT", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
-    };
-    V8DOMConfiguration::installConstants(isolate, interfaceTemplate, prototypeTemplate, V8TestInterfaceConstants, WTF_ARRAY_LENGTH(V8TestInterfaceConstants));
-    V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterfaceMethods, WTF_ARRAY_LENGTH(V8TestInterfaceMethods));
-  }
+  const V8DOMConfiguration::ConstantConfiguration V8TestInterfaceConstants[] = {
+      {"PARTIAL3_UNSIGNED_SHORT", 0, 0, V8DOMConfiguration::ConstantTypeUnsignedShort},
+  };
+  V8DOMConfiguration::installConstants(isolate, interfaceTemplate, prototypeTemplate, V8TestInterfaceConstants, WTF_ARRAY_LENGTH(V8TestInterfaceConstants));
+  V8DOMConfiguration::installMethods(isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate, signature, V8TestInterfaceMethods, WTF_ARRAY_LENGTH(V8TestInterfaceMethods));
 }
 
 void V8TestInterfacePartial::installOriginTrialPartialFeature(v8::Isolate* isolate, const DOMWrapperWorld& world, v8::Local<v8::Object> instance, v8::Local<v8::Object> prototype, v8::Local<v8::Function> interface) {
diff --git a/third_party/WebKit/Source/core/animation/Keyframe.h b/third_party/WebKit/Source/core/animation/Keyframe.h
index 599e3628..bbafe93 100644
--- a/third_party/WebKit/Source/core/animation/Keyframe.h
+++ b/third_party/WebKit/Source/core/animation/Keyframe.h
@@ -73,10 +73,7 @@
     double underlyingFraction() const {
       return m_composite == EffectModel::CompositeReplace ? 0 : 1;
     }
-    virtual bool isNeutral() const {
-      NOTREACHED();
-      return false;
-    }
+    virtual bool isNeutral() const = 0;
     virtual PassRefPtr<PropertySpecificKeyframe> cloneWithOffset(
         double offset) const = 0;
 
diff --git a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp
index 1c02f196..7b531d4a 100644
--- a/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp
+++ b/third_party/WebKit/Source/core/animation/KeyframeEffectModel.cpp
@@ -36,6 +36,7 @@
 #include "core/css/CSSPropertyEquality.h"
 #include "core/css/resolver/StyleResolver.h"
 #include "core/dom/Document.h"
+#include "core/frame/UseCounter.h"
 #include "platform/animation/AnimationUtilities.h"
 #include "platform/geometry/FloatBox.h"
 #include "platform/transforms/TransformationMatrix.h"
@@ -110,15 +111,22 @@
     const ComputedStyle* parentStyle) const {
   m_needsCompositorKeyframesSnapshot = false;
   bool updated = false;
+  bool hasNeutralCompositableKeyframe = false;
   ensureKeyframeGroups();
   for (CSSPropertyID property : CompositorAnimations::compositableProperties) {
     PropertySpecificKeyframeGroup* keyframeGroup =
         m_keyframeGroups->get(PropertyHandle(property));
     if (!keyframeGroup)
       continue;
-    for (auto& keyframe : keyframeGroup->m_keyframes)
+    for (auto& keyframe : keyframeGroup->m_keyframes) {
       updated |= keyframe->populateAnimatableValue(property, element, baseStyle,
                                                    parentStyle);
+      hasNeutralCompositableKeyframe |= keyframe->isNeutral();
+    }
+  }
+  if (updated && hasNeutralCompositableKeyframe) {
+    UseCounter::count(element.document(),
+                      UseCounter::SyntheticKeyframesInCompositedCSSAnimation);
   }
   return updated;
 }
diff --git a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h
index aa02249..c5b67aa 100644
--- a/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h
+++ b/third_party/WebKit/Source/core/animation/animatable/AnimatableValueKeyframe.h
@@ -46,6 +46,7 @@
       return m_value;
     }
 
+    bool isNeutral() const final { return m_value->isNeutral(); }
     PassRefPtr<Keyframe::PropertySpecificKeyframe> neutralKeyframe(
         double offset,
         PassRefPtr<TimingFunction> easing) const final;
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
index c385ff9c..cf626f7 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -172,35 +172,6 @@
   DCHECK(!keyframes.front()->offset());
   DCHECK_EQ(keyframes.back()->offset(), 1);
 
-  // This is used for use counting neutral keyframes running on the compositor.
-  PropertySet allProperties;
-  for (const auto& keyframe : keyframes) {
-    for (const auto& property : keyframe->properties())
-      allProperties.add(property.cssProperty());
-  }
-  const PropertyHandleSet& startKeyframeProperties =
-      startKeyframe->properties();
-  const PropertyHandleSet& endKeyframeProperties = endKeyframe->properties();
-  bool missingStartValues =
-      startKeyframeProperties.size() < allProperties.size();
-  bool missingEndValues = endKeyframeProperties.size() < allProperties.size();
-  if (missingStartValues || missingEndValues) {
-    for (CSSPropertyID property : allProperties) {
-      bool startNeedsValue =
-          missingStartValues &&
-          !startKeyframeProperties.contains(PropertyHandle(property));
-      bool endNeedsValue =
-          missingEndValues &&
-          !endKeyframeProperties.contains(PropertyHandle(property));
-      if (!startNeedsValue && !endNeedsValue)
-        continue;
-      if (CompositorAnimations::isCompositableProperty(property))
-        UseCounter::count(
-            elementForScoping->document(),
-            UseCounter::SyntheticKeyframesInCompositedCSSAnimation);
-    }
-  }
-
   StringKeyframeEffectModel* model =
       StringKeyframeEffectModel::create(keyframes, &keyframes[0]->easing());
   if (animationIndex > 0 && model->hasSyntheticKeyframes())
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp
index 58fc779..560cdf9 100644
--- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp
+++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp
@@ -515,8 +515,7 @@
   return false;
 }
 
-void CSSComputedStyleDeclaration::setProperty(const ExecutionContext*,
-                                              const String& name,
+void CSSComputedStyleDeclaration::setProperty(const String& name,
                                               const String&,
                                               const String&,
                                               ExceptionState& exceptionState) {
@@ -556,7 +555,6 @@
     const String&,
     const String&,
     bool,
-    const ExecutionContext*,
     ExceptionState& exceptionState) {
   // TODO(leviw): This code is currently unreachable, but shouldn't be.
   exceptionState.throwDOMException(
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h
index e66487b..9a67d5d 100644
--- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h
+++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h
@@ -87,8 +87,7 @@
   String getPropertyPriority(const String& propertyName) override;
   String getPropertyShorthand(const String& propertyName) override;
   bool isPropertyImplicit(const String& propertyName) override;
-  void setProperty(const ExecutionContext*,
-                   const String& propertyName,
+  void setProperty(const String& propertyName,
                    const String& value,
                    const String& priority,
                    ExceptionState&) override;
@@ -105,7 +104,6 @@
                            const String& customPropertyName,
                            const String& value,
                            bool important,
-                           const ExecutionContext*,
                            ExceptionState&) override;
 
   bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const override;
diff --git a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h
index bc136ce..e86d46f 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h
+++ b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h
@@ -34,7 +34,6 @@
 class CSSStyleSheet;
 class CSSValue;
 class ExceptionState;
-class ExecutionContext;
 
 class CORE_EXPORT CSSStyleDeclaration
     : public GarbageCollectedFinalized<CSSStyleDeclaration>,
@@ -48,7 +47,7 @@
   virtual CSSRule* parentRule() const = 0;
   String cssFloat() { return getPropertyValueInternal(CSSPropertyFloat); }
   void setCSSFloat(const String& value, ExceptionState& exceptionState) {
-    setPropertyInternal(CSSPropertyFloat, String(), value, false, nullptr,
+    setPropertyInternal(CSSPropertyFloat, String(), value, false,
                         exceptionState);
   }
   virtual String cssText() const = 0;
@@ -59,8 +58,7 @@
   virtual String getPropertyPriority(const String& propertyName) = 0;
   virtual String getPropertyShorthand(const String& propertyName) = 0;
   virtual bool isPropertyImplicit(const String& propertyName) = 0;
-  virtual void setProperty(const ExecutionContext*,
-                           const String& propertyName,
+  virtual void setProperty(const String& propertyName,
                            const String& value,
                            const String& priority,
                            ExceptionState&) = 0;
@@ -80,7 +78,6 @@
                                    const String& propertyValue,
                                    const String& value,
                                    bool important,
-                                   const ExecutionContext*,
                                    ExceptionState&) = 0;
 
   virtual bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const = 0;
diff --git a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl
index 4621a07..630aea050 100644
--- a/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl
+++ b/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl
@@ -31,7 +31,7 @@
     DOMString getPropertyPriority(DOMString property);
     // TODO(foolip): The value and priority arguments should have
     // [TreatNullAs=EmptyString] and should not be nullable.
-    [CallWith=ExecutionContext, CEReactions, RaisesException] void setProperty(DOMString property, DOMString? value, optional DOMString? priority = null);
+    [CEReactions, RaisesException] void setProperty(DOMString property, DOMString? value, optional DOMString? priority = null);
     // void setPropertyValue(DOMString property, [TreatNullAs=EmptyString] DOMString value);
     // void setPropertyPriority(DOMString property, [TreatNullAs=EmptyString] DOMString priority);
     [CEReactions, RaisesException] DOMString removeProperty(DOMString property);
diff --git a/third_party/WebKit/Source/core/css/FontFace.cpp b/third_party/WebKit/Source/core/css/FontFace.cpp
index f199686..2d695fb 100644
--- a/third_party/WebKit/Source/core/css/FontFace.cpp
+++ b/third_party/WebKit/Source/core/css/FontFace.cpp
@@ -388,13 +388,14 @@
 }
 
 ScriptPromise FontFace::load(ScriptState* scriptState) {
-  loadInternal(scriptState->getExecutionContext());
+  if (m_status == Unloaded)
+    m_cssFontFace->load();
   return fontStatusPromise(scriptState);
 }
 
-void FontFace::loadWithCallback(LoadFontCallback* callback,
-                                ExecutionContext* context) {
-  loadInternal(context);
+void FontFace::loadWithCallback(LoadFontCallback* callback) {
+  if (m_status == Unloaded)
+    m_cssFontFace->load();
   addCallback(callback);
 }
 
@@ -407,13 +408,6 @@
     m_callbacks.push_back(callback);
 }
 
-void FontFace::loadInternal(ExecutionContext* context) {
-  if (m_status != Unloaded)
-    return;
-
-  m_cssFontFace->load();
-}
-
 FontTraits FontFace::traits() const {
   FontStretch stretch = FontStretchNormal;
   if (m_stretch) {
diff --git a/third_party/WebKit/Source/core/css/FontFace.h b/third_party/WebKit/Source/core/css/FontFace.h
index f4ed0f6..5f12f10 100644
--- a/third_party/WebKit/Source/core/css/FontFace.h
+++ b/third_party/WebKit/Source/core/css/FontFace.h
@@ -119,7 +119,7 @@
     virtual void notifyError(FontFace*) = 0;
     DEFINE_INLINE_VIRTUAL_TRACE() {}
   };
-  void loadWithCallback(LoadFontCallback*, ExecutionContext*);
+  void loadWithCallback(LoadFontCallback*);
   void addCallback(LoadFontCallback*);
 
   // ScriptWrappable:
@@ -153,7 +153,6 @@
   bool setPropertyFromStyle(const StylePropertySet&, CSSPropertyID);
   bool setPropertyValue(const CSSValue*, CSSPropertyID);
   bool setFamilyValue(const CSSValue&);
-  void loadInternal(ExecutionContext*);
   ScriptPromise fontStatusPromise(ScriptState*);
 
   using LoadedProperty = ScriptPromiseProperty<Member<FontFace>,
diff --git a/third_party/WebKit/Source/core/css/FontFaceSet.cpp b/third_party/WebKit/Source/core/css/FontFaceSet.cpp
index 5893a9f..54c99074 100644
--- a/third_party/WebKit/Source/core/css/FontFaceSet.cpp
+++ b/third_party/WebKit/Source/core/css/FontFaceSet.cpp
@@ -58,7 +58,7 @@
     return new LoadFontPromiseResolver(faces, scriptState);
   }
 
-  void loadFonts(ExecutionContext*);
+  void loadFonts();
   ScriptPromise promise() { return m_resolver->promise(); }
 
   void notifyLoaded(FontFace*) override;
@@ -80,14 +80,14 @@
   Member<ScriptPromiseResolver> m_resolver;
 };
 
-void LoadFontPromiseResolver::loadFonts(ExecutionContext* context) {
+void LoadFontPromiseResolver::loadFonts() {
   if (!m_numLoading) {
     m_resolver->resolve(m_fontFaces);
     return;
   }
 
   for (size_t i = 0; i < m_fontFaces.size(); i++)
-    m_fontFaces[i]->loadWithCallback(this, context);
+    m_fontFaces[i]->loadWithCallback(this);
 }
 
 void LoadFontPromiseResolver::notifyLoaded(FontFace* fontFace) {
@@ -396,7 +396,7 @@
       LoadFontPromiseResolver::create(faces, scriptState);
   ScriptPromise promise = resolver->promise();
   // After this, resolver->promise() may return null.
-  resolver->loadFonts(getExecutionContext());
+  resolver->loadFonts();
   return promise;
 }
 
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
index e740ba1..0af8412 100644
--- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
+++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
@@ -235,7 +235,6 @@
 }
 
 void AbstractPropertySetCSSStyleDeclaration::setProperty(
-    const ExecutionContext* executionContext,
     const String& propertyName,
     const String& value,
     const String& priority,
@@ -249,7 +248,7 @@
     return;
 
   setPropertyInternal(propertyID, propertyName, value, important,
-                      executionContext, exceptionState);
+                      exceptionState);
 }
 
 String AbstractPropertySetCSSStyleDeclaration::removeProperty(
@@ -299,7 +298,6 @@
     const String& customPropertyName,
     const String& value,
     bool important,
-    const ExecutionContext* executionContext,
     ExceptionState&) {
   StyleAttributeMutationScope mutationScope(this);
   willMutate();
@@ -308,15 +306,12 @@
   if (unresolvedProperty == CSSPropertyVariable) {
     AtomicString atomicName(customPropertyName);
 
-    DCHECK(executionContext);
-    const PropertyRegistry* registry =
-        toDocument(executionContext)->propertyRegistry();
-
     bool isAnimationTainted = isKeyframeStyle();
-    didChange = propertySet()
-                    .setProperty(atomicName, registry, value, important,
-                                 contextStyleSheet(), isAnimationTainted)
-                    .didChange;
+    didChange =
+        propertySet()
+            .setProperty(atomicName, propertyRegistry(), value, important,
+                         contextStyleSheet(), isAnimationTainted)
+            .didChange;
   } else {
     didChange = propertySet()
                     .setProperty(unresolvedProperty, value, important,
@@ -382,6 +377,16 @@
   m_propertySet = &propertySet;
 }
 
+PropertyRegistry* StyleRuleCSSStyleDeclaration::propertyRegistry() const {
+  CSSStyleSheet* sheet = m_parentRule->parentStyleSheet();
+  if (!sheet)
+    return nullptr;
+  Node* node = sheet->ownerNode();
+  if (!node)
+    return nullptr;
+  return node->document().propertyRegistry();
+}
+
 DEFINE_TRACE(StyleRuleCSSStyleDeclaration) {
   visitor->trace(m_parentRule);
   PropertySetCSSStyleDeclaration::trace(visitor);
@@ -411,6 +416,11 @@
                          : nullptr;
 }
 
+PropertyRegistry* InlineCSSStyleDeclaration::propertyRegistry() const {
+  return m_parentElement ? m_parentElement->document().propertyRegistry()
+                         : nullptr;
+}
+
 DEFINE_TRACE(InlineCSSStyleDeclaration) {
   visitor->trace(m_parentElement);
   AbstractPropertySetCSSStyleDeclaration::trace(visitor);
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h
index d35e397..a1ce7b9a 100644
--- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h
+++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h
@@ -36,6 +36,7 @@
 class Element;
 class ExceptionState;
 class MutableStylePropertySet;
+class PropertyRegistry;
 class StyleSheetContents;
 
 class AbstractPropertySetCSSStyleDeclaration : public CSSStyleDeclaration {
@@ -53,8 +54,7 @@
   String getPropertyPriority(const String& propertyName) final;
   String getPropertyShorthand(const String& propertyName) final;
   bool isPropertyImplicit(const String& propertyName) final;
-  void setProperty(const ExecutionContext*,
-                   const String& propertyName,
+  void setProperty(const String& propertyName,
                    const String& value,
                    const String& priority,
                    ExceptionState&) final;
@@ -71,7 +71,6 @@
                            const String& customPropertyName,
                            const String& value,
                            bool important,
-                           const ExecutionContext*,
                            ExceptionState&) final;
 
   bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const final;
@@ -81,6 +80,7 @@
   virtual void willMutate() {}
   virtual void didMutate(MutationType) {}
   virtual MutableStylePropertySet& propertySet() const = 0;
+  virtual PropertyRegistry* propertyRegistry() const = 0;
   virtual bool isKeyframeStyle() const { return false; }
 };
 
@@ -98,6 +98,8 @@
     return *m_propertySet;
   }
 
+  PropertyRegistry* propertyRegistry() const override { return nullptr; }
+
   Member<MutableStylePropertySet> m_propertySet;  // Cannot be null
 };
 
@@ -123,6 +125,7 @@
 
   void willMutate() override;
   void didMutate(MutationType) override;
+  PropertyRegistry* propertyRegistry() const final;
 
   Member<CSSRule> m_parentRule;
 };
@@ -141,6 +144,7 @@
   Element* parentElement() const override { return m_parentElement; }
 
   void didMutate(MutationType) override;
+  PropertyRegistry* propertyRegistry() const final;
 
   Member<Element> m_parentElement;
 };
diff --git a/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp b/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
index 761d9a1..c61d0e15 100644
--- a/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
+++ b/third_party/WebKit/Source/core/editing/EditorKeyBindings.cpp
@@ -60,6 +60,18 @@
   if (!behavior().shouldInsertCharacter(*evt) || !canEdit())
     return false;
 
+  const Element* const focusedElement = m_frame->document()->focusedElement();
+  if (!focusedElement) {
+    // We may lose focused element by |command.execute(evt)|.
+    return false;
+  }
+  if (!focusedElement->containsIncludingHostElements(
+          *m_frame->selection().start().computeContainerNode())) {
+    // We should not insert text at selection start if selection doesn't have
+    // focus. See http://crbug.com/89026
+    return false;
+  }
+
   // Return true to prevent default action. e.g. Space key scroll.
   if (dispatchBeforeInputInsertText(evt->target(), keyEvent->text) !=
       DispatchEventResult::NotCanceled)
diff --git a/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp b/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp
index b1a6cc0..84464d11 100644
--- a/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp
+++ b/third_party/WebKit/Source/core/editing/VisiblePositionTest.cpp
@@ -89,14 +89,13 @@
   Position position(paragraph->firstChild(), 1);
 
   VisiblePosition visiblePosition1 = createVisiblePosition(position);
-  div->style()->setProperty(nullptr, "color", "red", "important",
-                            ASSERT_NO_EXCEPTION);
+  div->style()->setProperty("color", "red", "important", ASSERT_NO_EXCEPTION);
   EXPECT_FALSE(visiblePosition1.isValid());
 
   updateAllLifecyclePhases();
 
   VisiblePosition visiblePosition2 = createVisiblePosition(position);
-  div->style()->setProperty(nullptr, "display", "none", "important",
+  div->style()->setProperty("display", "none", "important",
                             ASSERT_NO_EXCEPTION);
   EXPECT_FALSE(visiblePosition2.isValid());
 
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp
index d81d9b37..9166239 100644
--- a/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/RemoveCSSPropertyCommand.cpp
@@ -57,13 +57,12 @@
   // script. Setting to null string removes the property. We don't have internal
   // version of removeProperty.
   m_element->style()->setPropertyInternal(m_property, String(), String(), false,
-                                          nullptr,
                                           IGNORE_EXCEPTION_FOR_TESTING);
 }
 
 void RemoveCSSPropertyCommand::doUnapply() {
   m_element->style()->setPropertyInternal(m_property, String(), m_oldValue,
-                                          m_important, nullptr,
+                                          m_important,
                                           IGNORE_EXCEPTION_FOR_TESTING);
 }
 
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index 5ed814d5..2a32bca 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -689,13 +689,13 @@
       // script.
       if (isEnclosingBlock(element)) {
         element->style()->setPropertyInternal(CSSPropertyDisplay, String(),
-                                              "inline", false, nullptr,
+                                              "inline", false,
                                               IGNORE_EXCEPTION_FOR_TESTING);
       }
       if (element->layoutObject() &&
           element->layoutObject()->style()->isFloating()) {
         element->style()->setPropertyInternal(CSSPropertyFloat, String(),
-                                              "none", false, nullptr,
+                                              "none", false,
                                               IGNORE_EXCEPTION_FOR_TESTING);
       }
     }
diff --git a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
index ee04d67..5956706 100644
--- a/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLMarqueeElement.cpp
@@ -359,11 +359,11 @@
   }
 
   if (isHorizontal()) {
-    m_mover->style()->setProperty(nullptr, "width", "-webkit-max-content",
-                                  "important", ASSERT_NO_EXCEPTION);
+    m_mover->style()->setProperty("width", "-webkit-max-content", "important",
+                                  ASSERT_NO_EXCEPTION);
   } else {
-    m_mover->style()->setProperty(nullptr, "height", "-webkit-max-content",
-                                  "important", ASSERT_NO_EXCEPTION);
+    m_mover->style()->setProperty("height", "-webkit-max-content", "important",
+                                  ASSERT_NO_EXCEPTION);
   }
   CSSStyleDeclaration* moverStyle =
       document().domWindow()->getComputedStyle(m_mover, String());
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp b/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp
index e7dd147..891d157 100644
--- a/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp
+++ b/third_party/WebKit/Source/core/html/parser/HTMLParserThread.cpp
@@ -83,8 +83,7 @@
 void HTMLParserThread::postTask(std::unique_ptr<CrossThreadClosure> closure) {
   ASSERT(isMainThread());
   if (!m_thread) {
-    m_thread = WebThreadSupportingGC::create("HTMLParserThread",
-                                             BlinkGC::PerThreadHeapMode);
+    m_thread = WebThreadSupportingGC::create("HTMLParserThread");
     postTask(crossThreadBind(&HTMLParserThread::setupHTMLParserThread,
                              crossThreadUnretained(this)));
   }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
index 4a33eb8f..7d71f1b 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -117,8 +117,8 @@
   CSSStyleRule* rule = toCSSStyleRule(styleSheet->item(0));
   CSSStyleDeclaration* style = rule->style();
   DummyExceptionStateForTesting exceptionState;
-  style->setProperty(nullptr, longhand, newValue,
-                     style->getPropertyPriority(longhand), exceptionState);
+  style->setProperty(longhand, newValue, style->getPropertyPriority(longhand),
+                     exceptionState);
   return style->getPropertyValue(shorthand);
 }
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp b/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
index 23cf3ff26..ea797969 100644
--- a/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerBackingThread.cpp
@@ -46,16 +46,13 @@
 
 WorkerBackingThread::WorkerBackingThread(const char* name,
                                          bool shouldCallGCOnShutdown)
-    : m_backingThread(
-          WebThreadSupportingGC::create(name, BlinkGC::PerThreadHeapMode)),
+    : m_backingThread(WebThreadSupportingGC::create(name)),
       m_isOwningThread(true),
       m_shouldCallGCOnShutdown(shouldCallGCOnShutdown) {}
 
 WorkerBackingThread::WorkerBackingThread(WebThread* thread,
                                          bool shouldCallGCOnShutdown)
-    : m_backingThread(
-          WebThreadSupportingGC::createForThread(thread,
-                                                 BlinkGC::PerThreadHeapMode)),
+    : m_backingThread(WebThreadSupportingGC::createForThread(thread)),
       m_isOwningThread(false),
       m_shouldCallGCOnShutdown(shouldCallGCOnShutdown) {}
 
diff --git a/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp b/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp
index a5cfed2..969f755 100644
--- a/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp
+++ b/third_party/WebKit/Source/modules/fetch/DataConsumerHandleTestUtil.cpp
@@ -40,8 +40,7 @@
 DataConsumerHandleTestUtil::Thread::Thread(
     const char* name,
     InitializationPolicy initializationPolicy)
-    : m_thread(
-          WebThreadSupportingGC::create(name, BlinkGC::MainThreadHeapMode)),
+    : m_thread(WebThreadSupportingGC::create(name)),
       m_initializationPolicy(initializationPolicy),
       m_waitableEvent(WTF::makeUnique<WaitableEvent>()) {
   m_thread->postTask(
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp
index dcea294..ab29b40 100644
--- a/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp
+++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseThread.cpp
@@ -60,8 +60,7 @@
   ASSERT(isMainThread());
   if (m_thread)
     return;
-  m_thread = WebThreadSupportingGC::create("WebCore: Database",
-                                           BlinkGC::PerThreadHeapMode);
+  m_thread = WebThreadSupportingGC::create("WebCore: Database");
   m_thread->postTask(BLINK_FROM_HERE,
                      crossThreadBind(&DatabaseThread::setupDatabaseThread,
                                      wrapCrossThreadPersistent(this)));
diff --git a/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp b/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp
index bc4ffa7..d6b944a3 100644
--- a/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp
+++ b/third_party/WebKit/Source/platform/WebThreadSupportingGC.cpp
@@ -13,24 +13,18 @@
 namespace blink {
 
 std::unique_ptr<WebThreadSupportingGC> WebThreadSupportingGC::create(
-    const char* name,
-    BlinkGC::ThreadHeapMode threadHeapMode) {
-  return WTF::wrapUnique(
-      new WebThreadSupportingGC(name, nullptr, threadHeapMode));
+    const char* name) {
+  return WTF::wrapUnique(new WebThreadSupportingGC(name, nullptr));
 }
 
 std::unique_ptr<WebThreadSupportingGC> WebThreadSupportingGC::createForThread(
-    WebThread* thread,
-    BlinkGC::ThreadHeapMode threadHeapMode) {
-  return WTF::wrapUnique(
-      new WebThreadSupportingGC(nullptr, thread, threadHeapMode));
+    WebThread* thread) {
+  return WTF::wrapUnique(new WebThreadSupportingGC(nullptr, thread));
 }
 
-WebThreadSupportingGC::WebThreadSupportingGC(
-    const char* name,
-    WebThread* thread,
-    BlinkGC::ThreadHeapMode threadHeapMode)
-    : m_thread(thread), m_threadHeapMode(threadHeapMode) {
+WebThreadSupportingGC::WebThreadSupportingGC(const char* name,
+                                             WebThread* thread)
+    : m_thread(thread) {
   DCHECK(!name || !thread);
 #if DCHECK_IS_ON()
   // We call this regardless of whether an existing thread is given or not,
@@ -53,7 +47,7 @@
 }
 
 void WebThreadSupportingGC::initialize() {
-  ThreadState::attachCurrentThread(m_threadHeapMode);
+  ThreadState::attachCurrentThread();
   m_gcTaskRunner = WTF::makeUnique<GCTaskRunner>(m_thread);
 }
 
diff --git a/third_party/WebKit/Source/platform/WebThreadSupportingGC.h b/third_party/WebKit/Source/platform/WebThreadSupportingGC.h
index fe2f9c7..c39ce3d 100644
--- a/third_party/WebKit/Source/platform/WebThreadSupportingGC.h
+++ b/third_party/WebKit/Source/platform/WebThreadSupportingGC.h
@@ -29,11 +29,8 @@
   WTF_MAKE_NONCOPYABLE(WebThreadSupportingGC);
 
  public:
-  static std::unique_ptr<WebThreadSupportingGC> create(const char* name,
-                                                       BlinkGC::ThreadHeapMode);
-  static std::unique_ptr<WebThreadSupportingGC> createForThread(
-      WebThread*,
-      BlinkGC::ThreadHeapMode);
+  static std::unique_ptr<WebThreadSupportingGC> create(const char* name);
+  static std::unique_ptr<WebThreadSupportingGC> createForThread(WebThread*);
   ~WebThreadSupportingGC();
 
   void postTask(const WebTraceLocation& location,
@@ -79,7 +76,7 @@
   }
 
  private:
-  WebThreadSupportingGC(const char* name, WebThread*, BlinkGC::ThreadHeapMode);
+  WebThreadSupportingGC(const char* name, WebThread*);
 
   std::unique_ptr<GCTaskRunner> m_gcTaskRunner;
 
@@ -88,7 +85,6 @@
   // existing thread via createForThread().
   WebThread* m_thread = nullptr;
   std::unique_ptr<WebThread> m_owningThread;
-  const BlinkGC::ThreadHeapMode m_threadHeapMode;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/BlinkGC.h b/third_party/WebKit/Source/platform/heap/BlinkGC.h
index d05033f..0800e22 100644
--- a/third_party/WebKit/Source/platform/heap/BlinkGC.h
+++ b/third_party/WebKit/Source/platform/heap/BlinkGC.h
@@ -105,11 +105,6 @@
     V8MinorGC,
     V8MajorGC,
   };
-
-  enum ThreadHeapMode {
-    MainThreadHeapMode,
-    PerThreadHeapMode,
-  };
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/heap/Heap.cpp b/third_party/WebKit/Source/platform/heap/Heap.cpp
index 046c80f9..f176390 100644
--- a/third_party/WebKit/Source/platform/heap/Heap.cpp
+++ b/third_party/WebKit/Source/platform/heap/Heap.cpp
@@ -256,12 +256,6 @@
     m_threads.remove(thread);
     isLastThread = m_threads.isEmpty();
   }
-  // The last thread begin detached should be the owning thread, which would
-  // be the main thread for the mainThreadHeap and a per thread heap enabled
-  // thread otherwise.
-  if (isLastThread)
-    DCHECK(thread->threadHeapMode() == BlinkGC::PerThreadHeapMode ||
-           thread->isMainThread());
   if (thread->isMainThread())
     DCHECK_EQ(heapStats().allocatedSpace(), 0u);
   if (isLastThread)
diff --git a/third_party/WebKit/Source/platform/heap/HeapTest.cpp b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
index 76c61b8..efd6f66b 100644
--- a/third_party/WebKit/Source/platform/heap/HeapTest.cpp
+++ b/third_party/WebKit/Source/platform/heap/HeapTest.cpp
@@ -561,7 +561,7 @@
   }
 
   void runThread() override {
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
+    ThreadState::attachCurrentThread();
 
     // Add a cross-thread persistent from this thread; the test object
     // verifies that it will have been cleared out after the threads
@@ -616,7 +616,7 @@
 
  private:
   void runThread() override {
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
+    ThreadState::attachCurrentThread();
 
     int gcCount = 0;
     while (!done()) {
@@ -706,7 +706,7 @@
   };
 
   void runThread() override {
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
+    ThreadState::attachCurrentThread();
 
     PersistentChain::create(100);
 
@@ -4780,67 +4780,6 @@
   EXPECT_EQ(2, MixinA::s_traceCount);
 }
 
-class GCParkingThreadTester {
- public:
-  static void test() {
-    std::unique_ptr<WebThread> sleepingThread =
-        WTF::wrapUnique(Platform::current()->createThread("SleepingThread"));
-    sleepingThread->getWebTaskRunner()->postTask(
-        BLINK_FROM_HERE, crossThreadBind(sleeperMainFunc));
-
-    // Wait for the sleeper to run.
-    while (!s_sleeperRunning) {
-      testing::yieldCurrentThread();
-    }
-
-    {
-      // Expect the first attempt to park the sleeping thread to fail
-      TestGCScope scope(BlinkGC::NoHeapPointersOnStack);
-      EXPECT_FALSE(scope.allThreadsParked());
-    }
-
-    s_sleeperDone = true;
-
-    // Wait for the sleeper to finish.
-    while (s_sleeperRunning) {
-      // We enter the safepoint here since the sleeper thread will detach
-      // causing it to GC.
-      ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack);
-      testing::yieldCurrentThread();
-    }
-
-    {
-      // Since the sleeper thread has detached this is the only thread.
-      TestGCScope scope(BlinkGC::NoHeapPointersOnStack);
-      EXPECT_TRUE(scope.allThreadsParked());
-    }
-  }
-
- private:
-  static void sleeperMainFunc() {
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
-    s_sleeperRunning = true;
-
-    // Simulate a long running op that is not entering a safepoint.
-    while (!s_sleeperDone) {
-      testing::yieldCurrentThread();
-    }
-
-    ThreadState::detachCurrentThread();
-    s_sleeperRunning = false;
-  }
-
-  static volatile bool s_sleeperRunning;
-  static volatile bool s_sleeperDone;
-};
-
-volatile bool GCParkingThreadTester::s_sleeperRunning = false;
-volatile bool GCParkingThreadTester::s_sleeperDone = false;
-
-TEST(HeapTest, GCParkingTimeout) {
-  GCParkingThreadTester::test();
-}
-
 TEST(HeapTest, NeedsAdjustAndMark) {
   // class Mixin : public GarbageCollectedMixin {};
   static_assert(NeedsAdjustAndMark<Mixin>::value,
@@ -5469,107 +5408,6 @@
   workerThreadCondition().signal();
 }
 
-class DeadBitTester {
- public:
-  static void test() {
-    IntWrapper::s_destructorCalls = 0;
-
-    MutexLocker locker(mainThreadMutex());
-    std::unique_ptr<WebThread> workerThread = WTF::wrapUnique(
-        Platform::current()->createThread("Test Worker Thread"));
-    workerThread->getWebTaskRunner()->postTask(
-        BLINK_FROM_HERE, crossThreadBind(workerThreadMain));
-
-    // Wait for the worker thread to have done its initialization,
-    // IE. the worker allocates an object and then throw aways any
-    // pointers to it.
-    parkMainThread();
-
-    // Now do a GC. This will not find the worker threads object since it
-    // is not referred from any of the threads. Even a conservative
-    // GC will not find it.
-    // Also at this point the worker is waiting for the main thread
-    // to be parked and will not do any sweep of its heap.
-    preciselyCollectGarbage();
-
-    // Since the worker thread is not sweeping the worker object should
-    // not have been finalized.
-    EXPECT_EQ(0, IntWrapper::s_destructorCalls);
-
-    // Put the worker thread's object address on the stack and do a
-    // conservative GC. This should find the worker object, but since
-    // it was dead in the previous GC it should not be traced in this
-    // GC.
-    uintptr_t stackPtrValue = s_workerObjectPointer;
-    s_workerObjectPointer = 0;
-    DCHECK(stackPtrValue);
-    conservativelyCollectGarbage();
-
-    // Since the worker thread is not sweeping the worker object should
-    // not have been finalized.
-    EXPECT_EQ(0, IntWrapper::s_destructorCalls);
-
-    // Wake up the worker thread so it can continue with its sweeping.
-    // This should finalized the worker object which we test below.
-    // The worker thread will go back to sleep once sweeping to ensure
-    // we don't have thread local GCs until after validating the destructor
-    // was called.
-    wakeWorkerThread();
-
-    // Wait for the worker thread to sweep its heaps before checking.
-    parkMainThread();
-    EXPECT_EQ(1, IntWrapper::s_destructorCalls);
-
-    // Wake up the worker to allow it thread to continue with thread
-    // shutdown.
-    wakeWorkerThread();
-  }
-
- private:
-  static void workerThreadMain() {
-    MutexLocker locker(workerThreadMutex());
-
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
-
-    {
-      // Create a worker object that is not kept alive except the
-      // main thread will keep it as an integer value on its stack.
-      IntWrapper* workerObject = IntWrapper::create(42);
-      s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject);
-    }
-
-    // Signal the main thread that the worker is done with its allocation.
-    wakeMainThread();
-
-    {
-      // Wait for the main thread to do two GCs without sweeping this thread
-      // heap. The worker waits within a safepoint, but there is no sweeping
-      // until leaving the safepoint scope.
-      SafePointScope scope(BlinkGC::NoHeapPointersOnStack);
-      parkWorkerThread();
-    }
-
-    // Wake up the main thread when done sweeping.
-    wakeMainThread();
-
-    // Wait with detach until the main thread says so. This is not strictly
-    // necessary, but it means the worker thread will not do its thread local
-    // GCs just yet, making it easier to reason about that no new GC has
-    // occurred and the above sweep was the one finalizing the worker object.
-    parkWorkerThread();
-
-    ThreadState::detachCurrentThread();
-  }
-
-  static volatile uintptr_t s_workerObjectPointer;
-};
-
-volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0;
-
-TEST(HeapTest, ObjectDeadBit) {
-  DeadBitTester::test();
-}
-
 class ThreadedStrongificationTester {
  public:
   static void test() {
@@ -5648,7 +5486,7 @@
   static void workerThreadMain() {
     MutexLocker locker(workerThreadMutex());
 
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
+    ThreadState::attachCurrentThread();
 
     {
       Persistent<WeakCollectionType> collection = allocateCollection();
@@ -5763,82 +5601,6 @@
 
 int DestructorLockingObject::s_destructorCalls = 0;
 
-class RecursiveLockingTester {
- public:
-  static void test() {
-    DestructorLockingObject::s_destructorCalls = 0;
-
-    MutexLocker locker(mainThreadMutex());
-    std::unique_ptr<WebThread> workerThread = WTF::wrapUnique(
-        Platform::current()->createThread("Test Worker Thread"));
-    workerThread->getWebTaskRunner()->postTask(
-        BLINK_FROM_HERE, crossThreadBind(workerThreadMain));
-
-    // Park the main thread until the worker thread has initialized.
-    parkMainThread();
-
-    {
-      SafePointAwareMutexLocker recursiveLocker(recursiveMutex());
-
-      // Let the worker try to acquire the above mutex. It won't get it
-      // until the main thread has done its GC.
-      wakeWorkerThread();
-
-      preciselyCollectGarbage();
-
-      // The worker thread should not have swept yet since it is waiting
-      // to get the global mutex.
-      EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls);
-    }
-    // At this point the main thread releases the global lock and the worker
-    // can acquire it and do its sweep of its arenas. Just wait for the worker
-    // to complete its sweep and check the result.
-    parkMainThread();
-    EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls);
-  }
-
- private:
-  static void workerThreadMain() {
-    MutexLocker locker(workerThreadMutex());
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
-
-    DestructorLockingObject* dlo = DestructorLockingObject::create();
-    DCHECK(dlo);
-
-    // Wake up the main thread which is waiting for the worker to do its
-    // allocation.
-    wakeMainThread();
-
-    // Wait for the main thread to get the global lock to ensure it has
-    // it before the worker tries to acquire it. We want the worker to
-    // block in the SafePointAwareMutexLocker until the main thread
-    // has done a GC. The GC will not mark the "dlo" object since the worker
-    // is entering the safepoint with NoHeapPointersOnStack. When the worker
-    // subsequently gets the global lock and leaves the safepoint it will
-    // sweep its heap and finalize "dlo". The destructor of "dlo" will try
-    // to acquire the same global lock that the thread just got and deadlock
-    // unless the global lock is recursive.
-    parkWorkerThread();
-    SafePointAwareMutexLocker recursiveLocker(recursiveMutex(),
-                                              BlinkGC::NoHeapPointersOnStack);
-
-    // We won't get here unless the lock is recursive since the sweep done
-    // in the constructor of SafePointAwareMutexLocker after
-    // getting the lock will not complete given the "dlo" destructor is
-    // waiting to get the same lock.
-    // Tell the main thread the worker has done its sweep.
-    wakeMainThread();
-
-    ThreadState::detachCurrentThread();
-  }
-
-  static volatile IntWrapper* s_workerObjectPointer;
-};
-
-TEST(HeapTest, RecursiveMutex) {
-  RecursiveLockingTester::test();
-}
-
 template <typename T>
 class TraceIfNeededTester
     : public GarbageCollectedFinalized<TraceIfNeededTester<T>> {
@@ -6501,7 +6263,7 @@
     DestructorLockingObject** object) {
   // Step 2: Create an object and store the pointer.
   MutexLocker locker(workerThreadMutex());
-  ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
+  ThreadState::attachCurrentThread();
   *object = DestructorLockingObject::create();
   wakeMainThread();
   parkWorkerThread();
@@ -6631,7 +6393,7 @@
   void runWhileAttached();
 
   void runThread() override {
-    ThreadState::attachCurrentThread(BlinkGC::MainThreadHeapMode);
+    ThreadState::attachCurrentThread();
     EXPECT_EQ(42, threadSpecificIntWrapper().value());
     runWhileAttached();
     ThreadState::detachCurrentThread();
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.cpp b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
index fa04eda6..e9bef27a 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.cpp
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.cpp
@@ -139,7 +139,7 @@
   bool m_shouldResumeThreads;
 };
 
-ThreadState::ThreadState(BlinkGC::ThreadHeapMode threadHeapMode)
+ThreadState::ThreadState()
     : m_thread(currentThread()),
       m_persistentRegion(WTF::makeUnique<PersistentRegion>()),
 #if OS(WIN) && COMPILER(MSVC)
@@ -159,7 +159,6 @@
       m_accumulatedSweepingTime(0),
       m_vectorBackingArenaIndex(BlinkGC::Vector1ArenaIndex),
       m_currentArenaAges(0),
-      m_threadHeapMode(threadHeapMode),
       m_isTerminating(false),
       m_gcMixinMarker(nullptr),
       m_shouldFlushHeapDoesNotContainCache(false),
@@ -181,25 +180,17 @@
   ASSERT(!**s_threadSpecific);
   **s_threadSpecific = this;
 
-  switch (m_threadHeapMode) {
-    case BlinkGC::MainThreadHeapMode:
-      if (isMainThread()) {
-        s_mainThreadStackStart =
-            reinterpret_cast<uintptr_t>(m_startOfStack) - sizeof(void*);
-        size_t underestimatedStackSize =
-            StackFrameDepth::getUnderestimatedStackSize();
-        if (underestimatedStackSize > sizeof(void*))
-          s_mainThreadUnderestimatedStackSize =
-              underestimatedStackSize - sizeof(void*);
-        m_heap = new ThreadHeap();
-      } else {
-        m_heap = &ThreadState::mainThreadState()->heap();
-      }
-      break;
-    case BlinkGC::PerThreadHeapMode:
-      m_heap = new ThreadHeap();
-      break;
+  if (isMainThread()) {
+    s_mainThreadStackStart =
+        reinterpret_cast<uintptr_t>(m_startOfStack) - sizeof(void*);
+    size_t underestimatedStackSize =
+        StackFrameDepth::getUnderestimatedStackSize();
+    if (underestimatedStackSize > sizeof(void*)) {
+      s_mainThreadUnderestimatedStackSize =
+          underestimatedStackSize - sizeof(void*);
+    }
   }
+  m_heap = new ThreadHeap();
   ASSERT(m_heap);
   m_heap->attach(this);
 
@@ -265,12 +256,12 @@
 void ThreadState::attachMainThread() {
   RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete);
   s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>();
-  new (s_mainThreadStateStorage) ThreadState(BlinkGC::MainThreadHeapMode);
+  new (s_mainThreadStateStorage) ThreadState();
 }
 
-void ThreadState::attachCurrentThread(BlinkGC::ThreadHeapMode threadHeapMode) {
+void ThreadState::attachCurrentThread() {
   RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete);
-  new ThreadState(threadHeapMode);
+  new ThreadState();
 }
 
 void ThreadState::cleanupPages() {
diff --git a/third_party/WebKit/Source/platform/heap/ThreadState.h b/third_party/WebKit/Source/platform/heap/ThreadState.h
index aafbf30..faffd0e 100644
--- a/third_party/WebKit/Source/platform/heap/ThreadState.h
+++ b/third_party/WebKit/Source/platform/heap/ThreadState.h
@@ -167,8 +167,6 @@
   void lockThreadAttachMutex();
   void unlockThreadAttachMutex();
 
-  BlinkGC::ThreadHeapMode threadHeapMode() const { return m_threadHeapMode; }
-
   bool isTerminating() { return m_isTerminating; }
 
   static void attachMainThread();
@@ -178,7 +176,7 @@
   // Associate ThreadState object with the current thread. After this
   // call thread can start using the garbage collected heap infrastructure.
   // It also has to periodically check for safepoints.
-  static void attachCurrentThread(BlinkGC::ThreadHeapMode);
+  static void attachCurrentThread();
 
   // Disassociate attached ThreadState from the current thread. The thread
   // can no longer use the garbage collected heap after this call.
@@ -588,7 +586,7 @@
   friend class PrefinalizerRegistration;
   enum SnapshotType { HeapSnapshot, FreelistSnapshot };
 
-  explicit ThreadState(BlinkGC::ThreadHeapMode);
+  ThreadState();
   ~ThreadState();
 
   NO_SANITIZE_ADDRESS void copyStackUntilSafePointScope();
@@ -704,7 +702,6 @@
   size_t m_arenaAges[BlinkGC::NumberOfArenas];
   size_t m_currentArenaAges;
 
-  const BlinkGC::ThreadHeapMode m_threadHeapMode;
   bool m_isTerminating;
   GarbageCollectedMixinConstructorMarker* m_gcMixinMarker;
 
diff --git a/third_party/WebKit/Source/wtf/ThreadSpecific.h b/third_party/WebKit/Source/wtf/ThreadSpecific.h
index 82f2144..5d7f6d2 100644
--- a/third_party/WebKit/Source/wtf/ThreadSpecific.h
+++ b/third_party/WebKit/Source/wtf/ThreadSpecific.h
@@ -224,7 +224,9 @@
 
 template <typename T>
 inline void ThreadSpecific<T>::destroy(void* ptr) {
-  if (isShutdown())
+  // Never call destructors on the main thread.
+  // This is fine because Blink no longer has a graceful shutdown sequence.
+  if (isMainThread())
     return;
 
   Data* data = static_cast<Data*>(ptr);
diff --git a/third_party/WebKit/public/platform/modules/presentation/presentation.mojom b/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
index 847ed6cb..96aea0c7 100644
--- a/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
+++ b/third_party/WebKit/public/platform/modules/presentation/presentation.mojom
@@ -53,10 +53,23 @@
   array<uint8>? data;
 };
 
+interface PresentationConnection {
+   // TODO(zhaobin): migrate SendConnectionMessage from PresentationService =>
+   // PresentationConnection.Send(). http://crbug.com/658474
+
+   // Called when a message is sent by the target connection.
+   OnMessage(ConnectionMessage message) => (bool success);
+
+   // Called when target connection notifies connection state change.
+   DidChangeState(PresentationConnectionState state);
+};
+
 interface PresentationService {
   // Sets the PresentationServiceClient.
   SetClient(PresentationServiceClient client);
 
+  ///////////// Functions here are for the controller part of the API. /////////
+
   // Called when the frame sets or changes the default presentation URLs.
   // When the default presentation is started on this frame,
   // PresentationServiceClient::OnDefaultSessionStarted will be invoked.
@@ -91,6 +104,16 @@
   JoinSession(array<url.mojom.Url> presentation_urls, string? presentation_id)
       => (PresentationSessionInfo? sessionInfo, PresentationError? error);
 
+  // Called in StartSession's callback function for offscreen presentation only.
+  // It passes in controlling frame's PresentationConnection and
+  // PresentationConnectionRequest to PresentationService.
+  SetPresentationConnection(
+      PresentationSessionInfo sessionInfo,
+      PresentationConnection controller_connection_ptr,
+      PresentationConnection& receiver_connection_request);
+
+  //////////////////////////////////////////////////////////////////////////////
+
   // Called when send() is called by the frame. The true in the
   // result callback notifies that the service is ready for next message.
   // The false in the result callback notifies the renderer to stop sending
@@ -113,6 +136,9 @@
 };
 
 interface PresentationServiceClient {
+
+  ////////////Functions here are called only on the controlling page.///////////
+
   // Called when the client tries to listen for screen availability changes for
   // presentation of |url| but it is not supported by the device or underlying
   // platform. This can also be called if the device is currently in a mode
@@ -125,6 +151,11 @@
   // the current known state. It will then be called to notify of state updates.
   OnScreenAvailabilityUpdated(url.mojom.Url url, bool available);
 
+  // See PresentationService::SetDefaultPresentationURL.
+  OnDefaultSessionStarted(PresentationSessionInfo sessionInfo);
+
+  //////////////////////////////////////////////////////////////////////////////
+
   // Called when the state of PresentationConnection |connection| started on
   // this frame has changed to |newState|.
   OnConnectionStateChanged(PresentationSessionInfo connection,
@@ -140,9 +171,10 @@
   OnConnectionMessagesReceived(PresentationSessionInfo sessionInfo,
                             array<ConnectionMessage> messages);
 
-  // See PresentationService::SetDefaultPresentationURL.
-  OnDefaultSessionStarted(PresentationSessionInfo sessionInfo);
-
-  // See PresentationService::OnReceiverConnectionAvailable.
-  OnReceiverConnectionAvailable(PresentationSessionInfo sessionInfo);
+  // Called on a presentation receiver when presentation connection is available
+  // from the controlling page.
+  OnReceiverConnectionAvailable(
+      PresentationSessionInfo sessionInfo,
+      PresentationConnection controller_connection_ptr,
+      PresentationConnection& receiver_connection_request);
 };
diff --git a/ui/file_manager/gallery/css/gallery.css b/ui/file_manager/gallery/css/gallery.css
index 803add4f..70bec09a 100644
--- a/ui/file_manager/gallery/css/gallery.css
+++ b/ui/file_manager/gallery/css/gallery.css
@@ -1270,6 +1270,7 @@
 .slideshow-toolbar > div {
   background-position: center;
   background-repeat: no-repeat;
+  cursor: pointer;
   height: 48px;
   opacity: 0.8;
   pointer-events: auto;
diff --git a/ui/keyboard/BUILD.gn b/ui/keyboard/BUILD.gn
index 2674b16..3226e6fa 100644
--- a/ui/keyboard/BUILD.gn
+++ b/ui/keyboard/BUILD.gn
@@ -38,7 +38,7 @@
     "//ui/base",
     "//ui/base/ime",
     "//ui/compositor",
-    "//ui/display/types:types",
+    "//ui/display:display",
     "//ui/events",
     "//ui/events:dom_keycode_converter",
     "//ui/events:events_base",
diff --git a/ui/keyboard/DEPS b/ui/keyboard/DEPS
index 8e48a4a..bfeb73b 100644
--- a/ui/keyboard/DEPS
+++ b/ui/keyboard/DEPS
@@ -6,7 +6,7 @@
   "+ui/aura",
   "+ui/base",
   "+ui/compositor",
-  "+ui/display/types",
+  "+ui/display",
   "+ui/events",
   "+ui/gfx",
   "+ui/gl/test/gl_surface_test_support.h",  # To initialize GL for tests.
diff --git a/ui/keyboard/keyboard_layout_manager.cc b/ui/keyboard/keyboard_layout_manager.cc
index e29b9f0..613800f 100644
--- a/ui/keyboard/keyboard_layout_manager.cc
+++ b/ui/keyboard/keyboard_layout_manager.cc
@@ -5,6 +5,8 @@
 #include "ui/keyboard/keyboard_layout_manager.h"
 
 #include "ui/compositor/layer_animator.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_util.h"
 
@@ -81,7 +83,17 @@
     // The window height is set to 0 initially or before switch to an IME in a
     // different extension. Virtual keyboard window may wait for this bounds
     // change to correctly animate in.
-    controller_->ShowKeyboard(controller_->keyboard_locked());
+    if (controller_->keyboard_locked()) {
+      // Do not move the keyboard to another display after switch to an IME in a
+      // different extension.
+      const int64_t display_id =
+          display::Screen::GetScreen()
+              ->GetDisplayNearestWindow(controller_->GetContainerWindow())
+              .id();
+      controller_->ShowKeyboardInDisplay(display_id);
+    } else {
+      controller_->ShowKeyboard(false /* lock */);
+    }
   } else {
     if (controller_->keyboard_mode() == FULL_WIDTH) {
       // We need to send out this notification only if keyboard is visible since