diff --git a/AUTHORS b/AUTHORS
index bf23440..2ff9a60 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -376,6 +376,7 @@
 Jeremy Noring <jnoring@hirevue.com>
 Jeremy Spiegel <jeremysspiegel@gmail.com>
 Jeroen Van den Berghe <vandenberghe.jeroen@gmail.com>
+Jerry Lin <wahahab11@gmail.com>
 Jesper Storm Bache <jsbache@gmail.com>
 Jesse Miller <jesse@jmiller.biz>
 Jesus Sanchez-Palencia <jesus.sanchez-palencia.fernandez.fil@intel.com>
diff --git a/DEPS b/DEPS
index 436b542..53db2a1e 100644
--- a/DEPS
+++ b/DEPS
@@ -105,11 +105,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '846bb413e161cb556f1afdbf07f3e637bff44432',
+  'skia_revision': '4359d529121fc1f39f882693d641c0133d138d41',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '4e454ce4b9534e4ada120486a56b099c46c72b6a',
+  'v8_revision': '9edff1c22685d21a282af9951040b0fee3caca73',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -117,7 +117,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '4004ae0e033a0169de3cb53c0a036833ad47178a',
+  'angle_revision': 'a914f7ff310df18ce64185bee69bdf9275b4463f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -518,7 +518,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9cccc5ce4fb9d6c2df820b14d5fc8350a98cd5b9',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2ac4352aea1751d8e928d3e4db519ba9a73a22a9',
       'condition': 'checkout_linux',
   },
 
@@ -1010,7 +1010,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5e83981c2c44f24109b96b555d6865d481e0c609',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '66cadcc6b924f027afb60a9b5932d4af3dc6a1d5',
+    Var('webrtc_git') + '/src.git' + '@' + '056a68da896d9a578b9ea83e56d261648ea0adc6',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1044,7 +1044,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@208cf41c691bb5f5851630c661426bc5a880ba1a',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7c2b573628be45199398f14d247482e2333db198',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 1de811d..36bc2e61 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -249,6 +249,10 @@
   host->AddFilter(new AwPrintingMessageFilter(host->GetID()));
 }
 
+bool AwContentBrowserClient::ShouldUseMobileFlingCurve() const {
+  return true;
+}
+
 bool AwContentBrowserClient::IsHandledURL(const GURL& url) {
   if (!url.is_valid()) {
     // We handle error cases.
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index e669168..54446a7 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -53,6 +53,7 @@
   void RenderProcessWillLaunch(
       content::RenderProcessHost* host,
       service_manager::mojom::ServiceRequest* service_request) override;
+  bool ShouldUseMobileFlingCurve() const override;
   bool IsHandledURL(const GURL& url) override;
   bool ForceSniffingFileUrlsForHtml() override;
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java
index 437cd0b..6aa1165 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillManager.java
@@ -48,6 +48,7 @@
         }
     }
 
+    private static boolean sIsLoggable;
     private AutofillManager mAutofillManager;
     private boolean mIsAutofillInputUIShowing;
     private AutofillInputUIMonitor mMonitor;
@@ -56,10 +57,14 @@
     private ArrayList<WeakReference<InputUIObserver>> mInputUIObservers;
 
     public AwAutofillManager(Context context) {
-        log("constructor");
+        updateLogStat();
+        if (isLoggable()) log("constructor");
         mAutofillManager = context.getSystemService(AutofillManager.class);
         mDisabled = mAutofillManager == null || !mAutofillManager.isEnabled();
-        if (mDisabled) return;
+        if (mDisabled) {
+            if (isLoggable()) log("disabled");
+            return;
+        }
 
         mMonitor = new AutofillInputUIMonitor(this);
         mAutofillManager.registerCallback(mMonitor);
@@ -67,19 +72,19 @@
 
     public void notifyVirtualValueChanged(View parent, int childId, AutofillValue value) {
         if (mDisabled || checkAndWarnIfDestroyed()) return;
-        log("notifyVirtualValueChanged");
+        if (isLoggable()) log("notifyVirtualValueChanged");
         mAutofillManager.notifyValueChanged(parent, childId, value);
     }
 
     public void commit(int submissionSource) {
         if (mDisabled || checkAndWarnIfDestroyed()) return;
-        log("commit source:" + submissionSource);
+        if (isLoggable()) log("commit source:" + submissionSource);
         mAutofillManager.commit();
     }
 
     public void cancel() {
         if (mDisabled || checkAndWarnIfDestroyed()) return;
-        log("cancel");
+        if (isLoggable()) log("cancel");
         mAutofillManager.cancel();
     }
 
@@ -92,31 +97,31 @@
             return;
         }
         if (checkAndWarnIfDestroyed()) return;
-        log("notifyVirtualViewEntered");
+        if (isLoggable()) log("notifyVirtualViewEntered");
         mAutofillManager.notifyViewEntered(parent, childId, absBounds);
     }
 
     public void notifyVirtualViewExited(View parent, int childId) {
         if (mDisabled || checkAndWarnIfDestroyed()) return;
-        log("notifyVirtualViewExited");
+        if (isLoggable()) log("notifyVirtualViewExited");
         mAutofillManager.notifyViewExited(parent, childId);
     }
 
     public void requestAutofill(View parent, int virtualId, Rect absBounds) {
         if (mDisabled || checkAndWarnIfDestroyed()) return;
-        log("requestAutofill");
+        if (isLoggable()) log("requestAutofill");
         mAutofillManager.requestAutofill(parent, virtualId, absBounds);
     }
 
     public boolean isAutofillInputUIShowing() {
         if (mDisabled || checkAndWarnIfDestroyed()) return false;
-        log("isAutofillInputUIShowing: " + mIsAutofillInputUIShowing);
+        if (isLoggable()) log("isAutofillInputUIShowing: " + mIsAutofillInputUIShowing);
         return mIsAutofillInputUIShowing;
     }
 
     public void destroy() {
         if (mDisabled || checkAndWarnIfDestroyed()) return;
-        log("destroy");
+        if (isLoggable()) log("destroy");
         mAutofillManager.unregisterCallback(mMonitor);
         mAutofillManager = null;
         mDestroyed = true;
@@ -164,9 +169,25 @@
         }
     }
 
+    public void notifyNewSessionStarted() {
+        updateLogStat();
+        if (isLoggable()) log("Session starts");
+    }
+
+    /**
+     * Always check isLoggable() before call this method.
+     */
     public static void log(String log) {
-        // Use 'setprop log.tag.AwAutofillManager DEBUG' to enable the log at runtime.
         // Log.i() instead of Log.d() is used here because log.d() is stripped out in release build.
-        if (Log.isLoggable(TAG, Log.DEBUG)) Log.i(TAG, log);
+        Log.i(TAG, log);
+    }
+
+    public static boolean isLoggable() {
+        return sIsLoggable;
+    }
+
+    private static void updateLogStat() {
+        // Use 'setprop log.tag.AwAutofillManager DEBUG' to enable the log at runtime.
+        sIsLoggable = Log.isLoggable(TAG, Log.DEBUG);
     }
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
index f33570a..50cce9d 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwAutofillProvider.java
@@ -255,8 +255,10 @@
         // return.
         if (mRequest == null) return;
         mRequest.fillViewStructure(structure);
-        AwAutofillManager.log(
-                "onProvideAutoFillVirtualStructure fields:" + structure.getChildCount());
+        if (AwAutofillManager.isLoggable()) {
+            AwAutofillManager.log(
+                    "onProvideAutoFillVirtualStructure fields:" + structure.getChildCount());
+        }
         mAutofillUMA.onVirtualStructureProvided();
     }
 
@@ -264,7 +266,9 @@
     public void autofill(final SparseArray<AutofillValue> values) {
         if (mNativeAutofillProvider != 0 && mRequest != null && mRequest.autofill((values))) {
             autofill(mNativeAutofillProvider, mRequest.mFormData);
-            AwAutofillManager.log("autofill values:" + values.size());
+            if (AwAutofillManager.isLoggable()) {
+                AwAutofillManager.log("autofill values:" + values.size());
+            }
             mAutofillUMA.onAutofill();
         }
     }
@@ -293,6 +297,7 @@
         if (!BuildInfo.isAtLeastP()) {
             mAutofillManager.cancel();
         }
+        mAutofillManager.notifyNewSessionStarted();
         Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height));
         mRequest = new AutofillRequest(formData, new FocusField((short) focus, absBound));
         int virtualId = mRequest.getVirtualId((short) focus);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index f180d86c..a86077c 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -174,8 +174,7 @@
      * Interface that consumers of {@link AwContents} must implement to allow the proper
      * dispatching of view methods through the containing view.
      */
-    public interface InternalAccessDelegate extends ContentViewCore.InternalAccessDelegate {
-
+    public interface InternalAccessDelegate extends ViewEventSink.InternalAccessDelegate {
         /**
          * @see View#overScrollBy(int, int, int, int, int, int, int, int, boolean);
          */
@@ -996,7 +995,7 @@
 
     private void setInternalAccessAdapter(InternalAccessDelegate internalAccessAdapter) {
         mInternalAccessAdapter = internalAccessAdapter;
-        mContentViewCore.setContainerViewInternals(mInternalAccessAdapter);
+        mViewEventSink.setAccessDelegate(mInternalAccessAdapter);
     }
 
     private void setContainerView(ViewGroup newContainerView, AwGLFunctor currentFunctor) {
diff --git a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
index db5b8e1..6df78d6f 100644
--- a/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
+++ b/ash/components/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -16,6 +16,7 @@
 #include "ui/events/devices/input_device_manager.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/dom_codes.h"
 #include "ui/events/keycodes/dom/dom_key.h"
 #include "ui/events/keycodes/dom/keycode_converter.h"
 #include "ui/events/keycodes/keyboard_code_conversion.h"
@@ -27,20 +28,6 @@
 
 namespace {
 
-// Get all DomCodes to construct the reverse mapping from DomCode to VKEY
-// and DomKey. We want to map a VKEY value to a text label, i.e. VKEY -> DomKey.
-// But VKEY and DomKey are both outputs of layout, so we only have
-// DomCode -> (VKEY, DomKey) by KeyboardLayoutEngine::Lookup(). We need to
-// iterate over the full list of DomCodes in order to look up a corresponding
-// DomKey for a KeyboardCode we want to get the string representation for.
-// keycode_converter.cc does not expose this list, so we need to generate it
-// here.
-#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) usb
-#define USB_KEYMAP_DECLARATION constexpr uint32_t kDomCodes[] =
-#include "ui/events/keycodes/dom/keycode_converter_data.inc"
-#undef USB_KEYMAP
-#undef USB_KEYMAP_DECLARATION
-
 // Gets the keyboard codes for modifiers.
 ui::KeyboardCode GetKeyCodeForModifier(ui::EventFlags modifier) {
   switch (modifier) {
@@ -145,8 +132,7 @@
 
   ui::DomKey dom_key;
   ui::KeyboardCode key_code_to_compare = ui::VKEY_UNKNOWN;
-  for (const auto& code : kDomCodes) {
-    const ui::DomCode dom_code = static_cast<ui::DomCode>(code);
+  for (const auto& dom_code : ui::dom_codes) {
     if (!ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()->Lookup(
             dom_code, /*flags=*/ui::EF_NONE, &dom_key, &key_code_to_compare)) {
       continue;
diff --git a/ash/public/interfaces/wallpaper.mojom b/ash/public/interfaces/wallpaper.mojom
index 5c268b6..3df0b0a 100644
--- a/ash/public/interfaces/wallpaper.mojom
+++ b/ash/public/interfaces/wallpaper.mojom
@@ -252,10 +252,11 @@
   // returns false.
   IsActiveUserWallpaperControlledByPolicy() => (bool controlled);
 
-  // Returns the location of the active user's wallpaper (either a url or a file
-  // path, corresponding to |WallpaperInfo.location|). Returns an empty string
-  // if there's no active user.
-  GetActiveUserWallpaperLocation() => (string loaction);
+  // Returns the location and the layout of the active user's wallpaper. The
+  // location is either a url or a file path, corresponding to
+  // |WallpaperInfo.location|. Returns an empty string and an invalid layout if
+  // there's no active user.
+  GetActiveUserWallpaperInfo() => (string location, WallpaperLayout layout);
 
   // Returns true if the wallpaper setting (used to open the wallpaper picker)
   // should be visible.
diff --git a/ash/system/audio/audio_detailed_view.cc b/ash/system/audio/audio_detailed_view.cc
index 5a15b85..63ee464 100644
--- a/ash/system/audio/audio_detailed_view.cc
+++ b/ash/system/audio/audio_detailed_view.cc
@@ -139,8 +139,7 @@
   }
 
   if (has_output_devices) {
-    scroll_content()->AddChildView(
-        TrayPopupUtils::CreateListSubHeaderSeparator());
+    scroll_content()->AddChildView(CreateListSubHeaderSeparator());
   }
 
   // Add audio input devices.
diff --git a/ash/system/brightness/unified_brightness_view.cc b/ash/system/brightness/unified_brightness_view.cc
index 2536b0c..dce5534e 100644
--- a/ash/system/brightness/unified_brightness_view.cc
+++ b/ash/system/brightness/unified_brightness_view.cc
@@ -18,6 +18,8 @@
                         kSystemMenuBrightnessIcon,
                         IDS_ASH_STATUS_TRAY_BRIGHTNESS),
       model_(model) {
+  button()->SetEnabled(false);
+
   model_->AddObserver(this);
   OnDisplayBrightnessChanged(false /* by_user */);
 }
diff --git a/ash/system/ime_menu/ime_menu_tray.cc b/ash/system/ime_menu/ime_menu_tray.cc
index 4f3569c..5412fd1 100644
--- a/ash/system/ime_menu/ime_menu_tray.cc
+++ b/ash/system/ime_menu/ime_menu_tray.cc
@@ -271,6 +271,9 @@
   bool IsOverflowIndicatorEnabled() const override { return true; }
   TriView* CreateTitleRow(int string_id) override { return nullptr; }
   views::View* CreateTitleSeparator() override { return nullptr; }
+  void ShowStickyHeaderSeparator(views::View* view,
+                                 bool show_separator) override {}
+  views::Separator* CreateListSubHeaderSeparator() override { return nullptr; }
   HoverHighlightView* CreateScrollListItem(
       ViewClickListener* listener,
       const gfx::VectorIcon& icon,
diff --git a/ash/system/message_center/arc/arc_notification_content_view.cc b/ash/system/message_center/arc/arc_notification_content_view.cc
index f1eea87c..5c73259 100644
--- a/ash/system/message_center/arc/arc_notification_content_view.cc
+++ b/ash/system/message_center/arc/arc_notification_content_view.cc
@@ -89,21 +89,6 @@
       return;
     }
 
-    // TODO(sarakato): Use a better tigger (eg. focusing EditText on
-    // notification) than clicking (b/78604162).
-    if (event->type() == ui::ET_MOUSE_PRESSED ||
-        event->type() == ui::ET_GESTURE_TAP) {
-      // Remove the focus from the currently focused view-control in the message
-      // center before activating the window of ARC notification, so that
-      // unexpected key handling doesn't happen (b/74415372).
-      // Focusing notification surface window doesn't steal the focus from
-      // the focucued view control in the message center, so that input events
-      // handles on both side wrongly without this.
-      owner_->GetFocusManager()->ClearFocus();
-
-      owner_->Activate();
-    }
-
     views::Widget* widget = owner_->GetWidget();
     if (!widget)
       return;
@@ -615,7 +600,7 @@
   notification_view->OnContentFocused();
 
   if (surface_ && surface_->GetAXTreeId() != -1)
-    Activate();
+    ActivateWidget(true);
 }
 
 void ArcNotificationContentView::OnBlur() {
@@ -631,18 +616,34 @@
   notification_view->OnContentBlurred();
 }
 
-void ArcNotificationContentView::Activate() {
+void ArcNotificationContentView::OnRemoteInputActivationChanged(
+    bool activated) {
+  // Remove the focus from the currently focused view-control in the message
+  // center before activating the window of ARC notification, so that unexpected
+  // key handling doesn't happen (b/74415372).
+  // Focusing notification surface window doesn't steal the focus from the
+  // focused view control in the message center, so that input events handles
+  // on both side wrongly without this.
+  GetFocusManager()->ClearFocus();
+
+  ActivateWidget(activated);
+}
+
+void ArcNotificationContentView::ActivateWidget(bool activate) {
   if (!GetWidget())
     return;
 
   // Make the widget active.
-  if (!GetWidget()->IsActive()) {
-    GetWidget()->widget_delegate()->set_can_activate(true);
-    GetWidget()->Activate();
-  }
+  if (activate) {
+    if (!GetWidget()->IsActive()) {
+      GetWidget()->widget_delegate()->set_can_activate(true);
+      GetWidget()->Activate();
+    }
 
-  // Focus the surface window.
-  surface_->FocusSurfaceWindow();
+    surface_->FocusSurfaceWindow();
+  } else {
+    GetWidget()->widget_delegate()->set_can_activate(false);
+  }
 }
 
 views::FocusTraversable* ArcNotificationContentView::GetFocusTraversable() {
@@ -676,7 +677,7 @@
     // not activated by default. We need to activate the widget. If other view
     // in message center has focus, it can consume key event. We need to request
     // focus to move it to this content view.
-    Activate();
+    ActivateWidget(true);
     RequestFocus();
   }
 }
diff --git a/ash/system/message_center/arc/arc_notification_content_view.h b/ash/system/message_center/arc/arc_notification_content_view.h
index ac141cca..f6a6b15 100644
--- a/ash/system/message_center/arc/arc_notification_content_view.h
+++ b/ash/system/message_center/arc/arc_notification_content_view.h
@@ -58,10 +58,13 @@
   void OnSlideChanged();
   void OnContainerAnimationStarted();
   void OnContainerAnimationEnded();
+  void ActivateWidget(bool activate);
 
  private:
   friend class ArcNotificationViewTest;
   friend class ArcNotificationContentViewTest;
+  FRIEND_TEST_ALL_PREFIXES(ArcNotificationContentViewTest,
+                           ActivateWhenRemoteInputOpens);
 
   class EventForwarder;
   class MouseEnterExitHandler;
@@ -75,7 +78,6 @@
   void UpdatePreferredSize();
   void UpdateSnapshot();
   void AttachSurface();
-  void Activate();
   void SetExpanded(bool expanded);
   bool IsExpanded() const;
   void SetManuallyExpandedOrCollapsed(bool value);
@@ -106,6 +108,7 @@
 
   // ArcNotificationItem::Observer
   void OnItemDestroying() override;
+  void OnRemoteInputActivationChanged(bool activated) override;
 
   // ArcNotificationSurfaceManager::Observer:
   void OnNotificationSurfaceAdded(ArcNotificationSurface* surface) override;
diff --git a/ash/system/message_center/arc/arc_notification_content_view_unittest.cc b/ash/system/message_center/arc/arc_notification_content_view_unittest.cc
index 5a1e1041..c4b8297 100644
--- a/ash/system/message_center/arc/arc_notification_content_view_unittest.cc
+++ b/ash/system/message_center/arc/arc_notification_content_view_unittest.cc
@@ -238,8 +238,9 @@
   ArcNotificationContentView* GetArcNotificationContentView() const {
     return notification_view_->content_view_;
   }
+
   void ActivateArcNotification() {
-    GetArcNotificationContentView()->Activate();
+    GetArcNotificationContentView()->ActivateWidget(true);
   }
 
  private:
@@ -474,7 +475,7 @@
   CloseNotificationView();
 }
 
-TEST_F(ArcNotificationContentViewTest, ActivateOnClick) {
+TEST_F(ArcNotificationContentViewTest, NotActivateOnClick) {
   std::string key("notification id");
   auto notification_item = std::make_unique<MockArcNotificationItem>(key);
   auto notification = CreateNotification(notification_item.get());
@@ -486,7 +487,24 @@
   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
                                      kNotificationSurfaceBounds.CenterPoint());
   generator.PressLeftButton();
+  EXPECT_EQ(nullptr, GetFocusedWindow());
+
+  CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, ActivateWhenRemoteInputOpens) {
+  std::string key("notification id");
+  auto notification_item = std::make_unique<MockArcNotificationItem>(key);
+  auto notification = CreateNotification(notification_item.get());
+
+  PrepareSurface(key);
+  CreateAndShowNotificationView(notification);
+
+  EXPECT_EQ(nullptr, GetFocusedWindow());
+  GetArcNotificationContentView()->OnRemoteInputActivationChanged(true);
   EXPECT_EQ(surface()->window(), GetFocusedWindow());
+  GetArcNotificationContentView()->OnRemoteInputActivationChanged(false);
+  EXPECT_NE(surface()->window(), GetFocusedWindow());
 
   CloseNotificationView();
 }
diff --git a/ash/system/message_center/arc/arc_notification_item.h b/ash/system/message_center/arc/arc_notification_item.h
index c9d23e11..c9f7c86b 100644
--- a/ash/system/message_center/arc/arc_notification_item.h
+++ b/ash/system/message_center/arc/arc_notification_item.h
@@ -18,6 +18,10 @@
     // Invoked when the notification data for this item has changed.
     virtual void OnItemDestroying() = 0;
 
+    // Invoked when the remote input textbox on notification is activated or
+    // deactivated.
+    virtual void OnRemoteInputActivationChanged(bool activated) {}
+
    protected:
     virtual ~Observer() = default;
   };
@@ -49,6 +53,10 @@
   // called from ArcNotificationContentView.
   virtual void ToggleExpansion() = 0;
 
+  // Called from ArcNotificationManager when the remote input textbox on
+  // notification is activated or deactivated.
+  virtual void OnRemoteInputActivationChanged(bool activate) = 0;
+
   // Adds an observer.
   virtual void AddObserver(Observer* observer) = 0;
   // Removes the observer.
diff --git a/ash/system/message_center/arc/arc_notification_item_impl.cc b/ash/system/message_center/arc/arc_notification_item_impl.cc
index 84d1bbc..0af3982 100644
--- a/ash/system/message_center/arc/arc_notification_item_impl.cc
+++ b/ash/system/message_center/arc/arc_notification_item_impl.cc
@@ -8,7 +8,9 @@
 #include <vector>
 
 #include "ash/system/message_center/arc/arc_notification_constants.h"
+#include "ash/system/message_center/arc/arc_notification_content_view.h"
 #include "ash/system/message_center/arc/arc_notification_delegate.h"
+#include "ash/system/message_center/arc/arc_notification_view.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/gfx/geometry/size.h"
@@ -193,6 +195,11 @@
   manager_->SendNotificationToggleExpansionOnChrome(notification_key_);
 }
 
+void ArcNotificationItemImpl::OnRemoteInputActivationChanged(bool activated) {
+  for (auto& observer : observers_)
+    observer.OnRemoteInputActivationChanged(activated);
+}
+
 void ArcNotificationItemImpl::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/ash/system/message_center/arc/arc_notification_item_impl.h b/ash/system/message_center/arc/arc_notification_item_impl.h
index 961e570..2db9207 100644
--- a/ash/system/message_center/arc/arc_notification_item_impl.h
+++ b/ash/system/message_center/arc/arc_notification_item_impl.h
@@ -39,6 +39,7 @@
   void OpenSettings() override;
   void OpenSnooze() override;
   void ToggleExpansion() override;
+  void OnRemoteInputActivationChanged(bool activated) override;
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
   void IncrementWindowRefCount() override;
diff --git a/ash/system/message_center/arc/arc_notification_manager.cc b/ash/system/message_center/arc/arc_notification_manager.cc
index b365468..5f0ad55 100644
--- a/ash/system/message_center/arc/arc_notification_manager.cc
+++ b/ash/system/message_center/arc/arc_notification_manager.cc
@@ -166,6 +166,32 @@
   if (it == items_.end())
     return;
 
+  bool is_remote_view_focused =
+      (data->remote_input_state ==
+       arc::mojom::ArcNotificationRemoteInputState::OPENED);
+  if (is_remote_view_focused && (previously_focused_notification_key_ != key)) {
+    if (!previously_focused_notification_key_.empty()) {
+      auto prev_it = items_.find(previously_focused_notification_key_);
+      // The case that another remote input is focused. Notify the previously-
+      // focused notification (if any).
+      if (prev_it != items_.end())
+        prev_it->second->OnRemoteInputActivationChanged(false);
+    }
+
+    // Notify the newly-focused notification.
+    previously_focused_notification_key_ = key;
+    it->second->OnRemoteInputActivationChanged(true);
+  } else if (!is_remote_view_focused &&
+             (previously_focused_notification_key_ == key)) {
+    // The case that the previously-focused notification gets unfocused. Notify
+    // the previously-focused notification if the notification still exists.
+    auto it = items_.find(previously_focused_notification_key_);
+    if (it != items_.end())
+      it->second->OnRemoteInputActivationChanged(false);
+
+    previously_focused_notification_key_.clear();
+  }
+
   delegate_->GetAppIdByPackageName(
       data->package_name.value_or(std::string()),
       base::BindOnce(&ArcNotificationManager::OnGotAppId,
diff --git a/ash/system/message_center/arc/arc_notification_manager.h b/ash/system/message_center/arc/arc_notification_manager.h
index 8300df5..1246e47 100644
--- a/ash/system/message_center/arc/arc_notification_manager.h
+++ b/ash/system/message_center/arc/arc_notification_manager.h
@@ -84,6 +84,9 @@
 
   bool ready_ = false;
 
+  // If any remote input is focused, its key is stored. Otherwise, empty.
+  std::string previously_focused_notification_key_;
+
   std::unique_ptr<InstanceOwner> instance_owner_;
 
   base::WeakPtrFactory<ArcNotificationManager> weak_ptr_factory_{this};
diff --git a/ash/system/message_center/arc/mock_arc_notification_item.h b/ash/system/message_center/arc/mock_arc_notification_item.h
index 11b5ee9..88f81e32 100644
--- a/ash/system/message_center/arc/mock_arc_notification_item.h
+++ b/ash/system/message_center/arc/mock_arc_notification_item.h
@@ -43,6 +43,8 @@
   void OpenSnooze() override {}
   void IncrementWindowRefCount() override {}
   void DecrementWindowRefCount() override {}
+  void OnRemoteInputActivationChanged(bool activate) override {}
+
   arc::mojom::ArcNotificationType GetNotificationType() const override;
   arc::mojom::ArcNotificationExpandState GetExpandState() const override;
   arc::mojom::ArcNotificationShownContents GetShownContents() const override;
diff --git a/ash/system/network/network_list.cc b/ash/system/network/network_list.cc
index 0ed366f..fd5f298 100644
--- a/ash/system/network/network_list.cc
+++ b/ash/system/network/network_list.cc
@@ -925,7 +925,7 @@
   // visible when the header row is not at the top of the list.
   if (child_index > 0) {
     if (!*separator_view)
-      *separator_view = TrayPopupUtils::CreateListSubHeaderSeparator();
+      *separator_view = CreateListSubHeaderSeparator();
     PlaceViewAtIndex(*separator_view, child_index++);
   } else {
     if (*separator_view)
diff --git a/ash/system/network/vpn_list_view.cc b/ash/system/network/vpn_list_view.cc
index d4b2e74..4ce990b 100644
--- a/ash/system/network/vpn_list_view.cc
+++ b/ash/system/network/vpn_list_view.cc
@@ -324,8 +324,7 @@
     const chromeos::NetworkStateHandler::NetworkStateList& networks) {
   // Add a visual separator, unless this is the topmost entry in the list.
   if (!list_empty_) {
-    scroll_content()->AddChildView(
-        TrayPopupUtils::CreateListSubHeaderSeparator());
+    scroll_content()->AddChildView(CreateListSubHeaderSeparator());
   }
   std::string vpn_name =
       vpn_provider.provider_type == VPNProvider::BUILT_IN_VPN
diff --git a/ash/system/tray/detailed_view_delegate.h b/ash/system/tray/detailed_view_delegate.h
index dc3b1c4..0dc900b 100644
--- a/ash/system/tray/detailed_view_delegate.h
+++ b/ash/system/tray/detailed_view_delegate.h
@@ -19,6 +19,7 @@
 namespace views {
 class Button;
 class ButtonListener;
+class Separator;
 class View;
 }  // namespace views
 
@@ -57,6 +58,15 @@
   // takes ownership of the returned view.
   virtual views::View* CreateTitleSeparator() = 0;
 
+  // Configure a |view| to have a visible separator below.
+  virtual void ShowStickyHeaderSeparator(views::View* view,
+                                         bool show_separator) = 0;
+
+  // Create a horizontal separator line to be drawn between rows in a detailed
+  // view above the sub-header rows. Caller takes ownership of the returned
+  // view.
+  virtual views::Separator* CreateListSubHeaderSeparator() = 0;
+
   // Return a targetable row containing |icon| and |text|. Caller takes
   // ownership of the returned view.
   virtual HoverHighlightView* CreateScrollListItem(
diff --git a/ash/system/tray/system_tray_item_detailed_view_delegate.cc b/ash/system/tray/system_tray_item_detailed_view_delegate.cc
index a1ed7e8..1041ab1 100644
--- a/ash/system/tray/system_tray_item_detailed_view_delegate.cc
+++ b/ash/system/tray/system_tray_item_detailed_view_delegate.cc
@@ -86,6 +86,17 @@
   return separator;
 }
 
+void SystemTrayItemDetailedViewDelegate::ShowStickyHeaderSeparator(
+    views::View* view,
+    bool show_separator) {
+  TrayPopupUtils::ShowStickyHeaderSeparator(view, show_separator);
+}
+
+views::Separator*
+SystemTrayItemDetailedViewDelegate::CreateListSubHeaderSeparator() {
+  return TrayPopupUtils::CreateListSubHeaderSeparator();
+}
+
 HoverHighlightView* SystemTrayItemDetailedViewDelegate::CreateScrollListItem(
     ViewClickListener* listener,
     const gfx::VectorIcon& icon,
diff --git a/ash/system/tray/system_tray_item_detailed_view_delegate.h b/ash/system/tray/system_tray_item_detailed_view_delegate.h
index ef7053b..cf63cfc 100644
--- a/ash/system/tray/system_tray_item_detailed_view_delegate.h
+++ b/ash/system/tray/system_tray_item_detailed_view_delegate.h
@@ -28,6 +28,9 @@
   bool IsOverflowIndicatorEnabled() const override;
   TriView* CreateTitleRow(int string_id) override;
   views::View* CreateTitleSeparator() override;
+  void ShowStickyHeaderSeparator(views::View* view,
+                                 bool show_separator) override;
+  views::Separator* CreateListSubHeaderSeparator() override;
   HoverHighlightView* CreateScrollListItem(ViewClickListener* listener,
                                            const gfx::VectorIcon& icon,
                                            const base::string16& text) override;
diff --git a/ash/system/tray/tray_detailed_view.cc b/ash/system/tray/tray_detailed_view.cc
index 0ce272e2..02d41736 100644
--- a/ash/system/tray/tray_detailed_view.cc
+++ b/ash/system/tray/tray_detailed_view.cc
@@ -54,7 +54,8 @@
 // row use set_id(VIEW_ID_STICKY_HEADER).
 class ScrollContentsView : public views::View {
  public:
-  ScrollContentsView() {
+  explicit ScrollContentsView(DetailedViewDelegate* delegate)
+      : delegate_(delegate) {
     box_layout_ = SetLayoutManager(
         std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
   }
@@ -212,8 +213,7 @@
       }
       if (header.draw_separator_below != draw_separator_below) {
         header.draw_separator_below = draw_separator_below;
-        TrayPopupUtils::ShowStickyHeaderSeparator(header_view,
-                                                  draw_separator_below);
+        delegate_->ShowStickyHeaderSeparator(header_view, draw_separator_below);
       }
       if (header.natural_offset < scroll_offset)
         break;
@@ -253,6 +253,8 @@
     canvas->DrawRect(shadowed_area, flags);
   }
 
+  DetailedViewDelegate* const delegate_;
+
   views::BoxLayout* box_layout_ = nullptr;
 
   // Header child views that stick to the top of visible viewport when scrolled.
@@ -313,7 +315,7 @@
 
 void TrayDetailedView::CreateScrollableList() {
   DCHECK(!scroller_);
-  scroll_content_ = new ScrollContentsView();
+  scroll_content_ = new ScrollContentsView(delegate_);
   scroller_ = new views::ScrollView;
   scroller_->set_draw_overflow_indicator(
       delegate_->IsOverflowIndicatorEnabled());
@@ -428,6 +430,10 @@
   return delegate_->CreateHelpButton(this);
 }
 
+views::Separator* TrayDetailedView::CreateListSubHeaderSeparator() {
+  return delegate_->CreateListSubHeaderSeparator();
+}
+
 void TrayDetailedView::HandleViewClicked(views::View* view) {
   NOTREACHED();
 }
diff --git a/ash/system/tray/tray_detailed_view.h b/ash/system/tray/tray_detailed_view.h
index bf664f5..f0ec573b 100644
--- a/ash/system/tray/tray_detailed_view.h
+++ b/ash/system/tray/tray_detailed_view.h
@@ -23,6 +23,7 @@
 class Button;
 class ProgressBar;
 class ScrollView;
+class Separator;
 }  // namespace views
 
 namespace ash {
@@ -108,6 +109,11 @@
   views::Button* CreateSettingsButton(int setting_accessible_name_id);
   views::Button* CreateHelpButton();
 
+  // Create a horizontal separator line to be drawn between rows in a detailed
+  // view above the sub-header rows. Caller takes ownership of the returned
+  // view.
+  views::Separator* CreateListSubHeaderSeparator();
+
   // Closes the bubble that contains the detailed view.
   void CloseBubble();
 
diff --git a/ash/system/tray_accessibility.cc b/ash/system/tray_accessibility.cc
index e3a932ce..a278934 100644
--- a/ash/system/tray_accessibility.cc
+++ b/ash/system/tray_accessibility.cc
@@ -276,8 +276,7 @@
           IDS_ASH_STATUS_TRAY_ACCESSIBILITY_VIRTUAL_KEYBOARD),
       virtual_keyboard_enabled_);
 
-  scroll_content()->AddChildView(
-      TrayPopupUtils::CreateListSubHeaderSeparator());
+  scroll_content()->AddChildView(CreateListSubHeaderSeparator());
 
   AddScrollListSubHeader(IDS_ASH_STATUS_TRAY_ACCESSIBILITY_ADDITIONAL_SETTINGS);
 
diff --git a/ash/system/unified/top_shortcut_button.cc b/ash/system/unified/top_shortcut_button.cc
index feab131..7ec10dd1 100644
--- a/ash/system/unified/top_shortcut_button.cc
+++ b/ash/system/unified/top_shortcut_button.cc
@@ -19,13 +19,17 @@
 TopShortcutButton::TopShortcutButton(views::ButtonListener* listener,
                                      const gfx::VectorIcon& icon,
                                      int accessible_name_id)
-    : views::ImageButton(listener) {
-  SetPreferredSize(gfx::Size(kTrayItemSize, kTrayItemSize));
-
+    : TopShortcutButton(listener, accessible_name_id) {
   SetImage(views::Button::STATE_NORMAL,
            gfx::CreateVectorIcon(icon, kUnifiedMenuIconColor));
   SetImage(views::Button::STATE_DISABLED,
            gfx::CreateVectorIcon(icon, kUnifiedMenuIconColorDisabled));
+}
+
+TopShortcutButton::TopShortcutButton(views::ButtonListener* listener,
+                                     int accessible_name_id)
+    : views::ImageButton(listener) {
+  SetPreferredSize(gfx::Size(kTrayItemSize, kTrayItemSize));
 
   SetImageAlignment(ALIGN_CENTER, ALIGN_MIDDLE);
   SetTooltipText(l10n_util::GetStringUTF16(accessible_name_id));
diff --git a/ash/system/unified/top_shortcut_button.h b/ash/system/unified/top_shortcut_button.h
index aac6e6c..b0fce14 100644
--- a/ash/system/unified/top_shortcut_button.h
+++ b/ash/system/unified/top_shortcut_button.h
@@ -18,6 +18,7 @@
   TopShortcutButton(views::ButtonListener* listener,
                     const gfx::VectorIcon& icon,
                     int accessible_name_id);
+  TopShortcutButton(views::ButtonListener* listener, int accessible_name_id);
   ~TopShortcutButton() override;
 
   // views::ImageButton:
diff --git a/ash/system/unified/unified_detailed_view_delegate.cc b/ash/system/unified/unified_detailed_view_delegate.cc
index 07495ef..9f546ad 100644
--- a/ash/system/unified/unified_detailed_view_delegate.cc
+++ b/ash/system/unified/unified_detailed_view_delegate.cc
@@ -146,6 +146,30 @@
   return separator;
 }
 
+void UnifiedDetailedViewDelegate::ShowStickyHeaderSeparator(
+    views::View* view,
+    bool show_separator) {
+  if (show_separator) {
+    view->SetBorder(views::CreatePaddedBorder(
+        views::CreateSolidSidedBorder(0, 0, kSeparatorWidth, 0,
+                                      kUnifiedMenuSeparatorColor),
+        gfx::Insets(kMenuSeparatorVerticalPadding, 0,
+                    kMenuSeparatorVerticalPadding - kSeparatorWidth, 0)));
+  } else {
+    view->SetBorder(views::CreateEmptyBorder(
+        gfx::Insets(kMenuSeparatorVerticalPadding, 0)));
+  }
+  view->SchedulePaint();
+}
+
+views::Separator* UnifiedDetailedViewDelegate::CreateListSubHeaderSeparator() {
+  views::Separator* separator = new views::Separator();
+  separator->SetColor(kUnifiedMenuSeparatorColor);
+  separator->SetBorder(views::CreateEmptyBorder(
+      kMenuSeparatorVerticalPadding - views::Separator::kThickness, 0, 0, 0));
+  return separator;
+}
+
 HoverHighlightView* UnifiedDetailedViewDelegate::CreateScrollListItem(
     ViewClickListener* listener,
     const gfx::VectorIcon& icon,
diff --git a/ash/system/unified/unified_detailed_view_delegate.h b/ash/system/unified/unified_detailed_view_delegate.h
index d8ef69f..dd7f89d 100644
--- a/ash/system/unified/unified_detailed_view_delegate.h
+++ b/ash/system/unified/unified_detailed_view_delegate.h
@@ -26,6 +26,9 @@
   bool IsOverflowIndicatorEnabled() const override;
   TriView* CreateTitleRow(int string_id) override;
   views::View* CreateTitleSeparator() override;
+  void ShowStickyHeaderSeparator(views::View* view,
+                                 bool show_separator) override;
+  views::Separator* CreateListSubHeaderSeparator() override;
   HoverHighlightView* CreateScrollListItem(ViewClickListener* listener,
                                            const gfx::VectorIcon& icon,
                                            const base::string16& text) override;
diff --git a/ash/system/unified/unified_slider_view.cc b/ash/system/unified/unified_slider_view.cc
index 1754062..61346c0 100644
--- a/ash/system/unified/unified_slider_view.cc
+++ b/ash/system/unified/unified_slider_view.cc
@@ -47,7 +47,9 @@
 UnifiedSliderButton::UnifiedSliderButton(views::ButtonListener* listener,
                                          const gfx::VectorIcon& icon,
                                          int accessible_name_id)
-    : TopShortcutButton(listener, icon, accessible_name_id) {}
+    : TopShortcutButton(listener, accessible_name_id) {
+  SetVectorIcon(icon);
+}
 
 UnifiedSliderButton::~UnifiedSliderButton() = default;
 
diff --git a/ash/system/unified/unified_system_info_view.cc b/ash/system/unified/unified_system_info_view.cc
index cf8d155..11ab5c5 100644
--- a/ash/system/unified/unified_system_info_view.cc
+++ b/ash/system/unified/unified_system_info_view.cc
@@ -20,6 +20,7 @@
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/tray/tray_popup_utils.h"
+#include "ash/system/unified/unified_system_tray_controller.h"
 #include "base/i18n/time_formatting.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -49,26 +50,33 @@
 
 // A view that shows current date in short format e.g. "Mon, Mar 12". It updates
 // by observing ClockObserver.
-class DateView : public views::View, public ClockObserver {
+class DateView : public views::Button,
+                 public views::ButtonListener,
+                 public ClockObserver {
  public:
-  DateView();
+  explicit DateView(UnifiedSystemTrayController* controller);
   ~DateView() override;
 
  private:
   void Update();
 
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
   // ClockObserver:
   void OnDateFormatChanged() override;
   void OnSystemClockTimeUpdated() override;
   void OnSystemClockCanSetTimeChanged(bool can_set_time) override;
   void Refresh() override;
 
+  UnifiedSystemTrayController* const controller_;
   views::Label* label_;
 
   DISALLOW_COPY_AND_ASSIGN(DateView);
 };
 
-DateView::DateView() : label_(new views::Label) {
+DateView::DateView(UnifiedSystemTrayController* controller)
+    : Button(this), controller_(controller), label_(new views::Label) {
   SetLayoutManager(std::make_unique<views::FillLayout>());
   AddChildView(label_);
 
@@ -78,16 +86,23 @@
   Update();
 
   Shell::Get()->system_tray_model()->clock()->AddObserver(this);
+  TrayPopupUtils::ConfigureTrayPopupButton(this);
 }
 
 DateView::~DateView() {
   Shell::Get()->system_tray_model()->clock()->RemoveObserver(this);
 }
 
+void DateView::ButtonPressed(views::Button* sender, const ui::Event& event) {
+  controller_->HandleOpenDateTimeSettingsAction();
+}
+
 void DateView::Update() {
   base::Time now = base::Time::Now();
   label_->SetText(l10n_util::GetStringFUTF16(
       IDS_ASH_STATUS_TRAY_DATE, FormatDayOfWeek(now), FormatDate(now)));
+  SetAccessibleName(TimeFormatFriendlyDateAndTime(now));
+  NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true);
 }
 
 void DateView::OnDateFormatChanged() {}
@@ -304,14 +319,15 @@
 
 }  // namespace
 
-UnifiedSystemInfoView::UnifiedSystemInfoView()
+UnifiedSystemInfoView::UnifiedSystemInfoView(
+    UnifiedSystemTrayController* controller)
     : enterprise_managed_(new EnterpriseManagedView()),
       supervised_(new SupervisedUserView()) {
   auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::kHorizontal, kUnifiedMenuItemPadding,
       kUnifiedSystemInfoSpacing));
 
-  AddChildView(new DateView());
+  AddChildView(new DateView(controller));
 
   if (PowerStatus::Get()->IsBatteryPresent()) {
     auto* separator = new views::Separator();
diff --git a/ash/system/unified/unified_system_info_view.h b/ash/system/unified/unified_system_info_view.h
index 13cd5d9..920b60d7 100644
--- a/ash/system/unified/unified_system_info_view.h
+++ b/ash/system/unified/unified_system_info_view.h
@@ -6,6 +6,7 @@
 #define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_INFO_VIEW_H_
 
 #include "ash/ash_export.h"
+#include "ash/system/unified/unified_system_tray_controller.h"
 #include "ui/views/view.h"
 
 namespace ash {
@@ -15,7 +16,7 @@
 // is enterprise managed or not.
 class ASH_EXPORT UnifiedSystemInfoView : public views::View {
  public:
-  UnifiedSystemInfoView();
+  explicit UnifiedSystemInfoView(UnifiedSystemTrayController* controller);
   ~UnifiedSystemInfoView() override;
 
   // views::View:
diff --git a/ash/system/unified/unified_system_info_view_unittest.cc b/ash/system/unified/unified_system_info_view_unittest.cc
index 927f81d..d85097d 100644
--- a/ash/system/unified/unified_system_info_view_unittest.cc
+++ b/ash/system/unified/unified_system_info_view_unittest.cc
@@ -9,6 +9,8 @@
 #include "ash/shell.h"
 #include "ash/system/model/enterprise_domain_model.h"
 #include "ash/system/model/system_tray_model.h"
+#include "ash/system/unified/unified_system_tray_controller.h"
+#include "ash/system/unified/unified_system_tray_model.h"
 #include "ash/test/ash_test_base.h"
 
 namespace ash {
@@ -20,11 +22,15 @@
 
   void SetUp() override {
     AshTestBase::SetUp();
-    info_view_ = std::make_unique<UnifiedSystemInfoView>();
+    model_ = std::make_unique<UnifiedSystemTrayModel>();
+    controller_ = std::make_unique<UnifiedSystemTrayController>(model_.get());
+    info_view_ = std::make_unique<UnifiedSystemInfoView>(controller_.get());
   }
 
   void TearDown() override {
     info_view_.reset();
+    controller_.reset();
+    model_.reset();
     AshTestBase::TearDown();
   }
 
@@ -32,6 +38,8 @@
   UnifiedSystemInfoView* info_view() { return info_view_.get(); }
 
  private:
+  std::unique_ptr<UnifiedSystemTrayModel> model_;
+  std::unique_ptr<UnifiedSystemTrayController> controller_;
   std::unique_ptr<UnifiedSystemInfoView> info_view_;
 
   DISALLOW_COPY_AND_ASSIGN(UnifiedSystemInfoViewTest);
@@ -68,13 +76,17 @@
 using UnifiedSystemInfoViewNoSessionTest = NoSessionAshTestBase;
 
 TEST_F(UnifiedSystemInfoViewNoSessionTest, SupervisedVisible) {
-  std::unique_ptr<UnifiedSystemInfoView> info_view_;
+  std::unique_ptr<UnifiedSystemTrayModel> model_ =
+      std::make_unique<UnifiedSystemTrayModel>();
+  std::unique_ptr<UnifiedSystemTrayController> controller_ =
+      std::make_unique<UnifiedSystemTrayController>(model_.get());
 
   SessionController* session = Shell::Get()->session_controller();
   ASSERT_FALSE(session->IsActiveUserSessionStarted());
 
   // Before login the supervised user view is invisible.
-  info_view_ = std::make_unique<UnifiedSystemInfoView>();
+  std::unique_ptr<UnifiedSystemInfoView> info_view_;
+  info_view_ = std::make_unique<UnifiedSystemInfoView>(controller_.get());
   EXPECT_FALSE(info_view_->supervised_->visible());
   info_view_.reset();
 
@@ -88,7 +100,7 @@
   session->UpdateUserSession(std::move(user_session));
 
   // Now the supervised user view is visible.
-  info_view_ = std::make_unique<UnifiedSystemInfoView>();
+  info_view_ = std::make_unique<UnifiedSystemInfoView>(controller_.get());
   ASSERT_TRUE(info_view_->supervised_->visible());
 }
 
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc
index cd2d9b8..080d536 100644
--- a/ash/system/unified/unified_system_tray_controller.cc
+++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -18,6 +18,8 @@
 #include "ash/system/cast/unified_cast_detailed_view_controller.h"
 #include "ash/system/ime/ime_feature_pod_controller.h"
 #include "ash/system/ime/unified_ime_detailed_view_controller.h"
+#include "ash/system/model/clock_model.h"
+#include "ash/system/model/system_tray_model.h"
 #include "ash/system/network/network_feature_pod_controller.h"
 #include "ash/system/network/unified_network_detailed_view_controller.h"
 #include "ash/system/network/unified_vpn_detailed_view_controller.h"
@@ -129,6 +131,15 @@
       ShutdownReason::TRAY_SHUT_DOWN_BUTTON);
 }
 
+void UnifiedSystemTrayController::HandleOpenDateTimeSettingsAction() {
+  if (Shell::Get()->system_tray_model()->clock()->can_set_time()) {
+    Shell::Get()->system_tray_model()->clock()->ShowSetTimeDialog();
+  } else {
+    Shell::Get()->system_tray_model()->clock()->ShowDateSettings();
+  }
+  CloseBubble();
+}
+
 void UnifiedSystemTrayController::ToggleExpanded() {
   UMA_HISTOGRAM_ENUMERATION("ChromeOS.SystemTray.ToggleExpanded",
                             TOGGLE_EXPANDED_TYPE_BY_BUTTON,
diff --git a/ash/system/unified/unified_system_tray_controller.h b/ash/system/unified/unified_system_tray_controller.h
index 6d4b1533..8674e252 100644
--- a/ash/system/unified/unified_system_tray_controller.h
+++ b/ash/system/unified/unified_system_tray_controller.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "ash/ash_export.h"
+#include "ash/system/unified/unified_system_tray_model.h"
 #include "base/macros.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/geometry/point.h"
@@ -47,6 +48,8 @@
   void HandleSettingsAction();
   // Shutdown the computer. Called from the view.
   void HandlePowerAction();
+  // Show date and time settings. Called from the view.
+  void HandleOpenDateTimeSettingsAction();
   // Toggle expanded state of UnifiedSystemTrayView. Called from the view.
   void ToggleExpanded();
   // Clear all notifications. It triggers animation, and does not remove
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc
index e1adbb7..87eca1c 100644
--- a/ash/system/unified/unified_system_tray_view.cc
+++ b/ash/system/unified/unified_system_tray_view.cc
@@ -127,7 +127,7 @@
       top_shortcuts_view_(new TopShortcutsView(controller_)),
       feature_pods_container_(new FeaturePodsContainerView(initially_expanded)),
       sliders_container_(new UnifiedSlidersContainerView(initially_expanded)),
-      system_info_view_(new UnifiedSystemInfoView()),
+      system_info_view_(new UnifiedSystemInfoView(controller_)),
       system_tray_container_(new SystemTrayContainer()),
       detailed_view_container_(new DetailedViewContainer()),
       interacted_by_tap_recorder_(
diff --git a/ash/wallpaper/wallpaper_controller.cc b/ash/wallpaper/wallpaper_controller.cc
index 60242fd5..d89839e 100644
--- a/ash/wallpaper/wallpaper_controller.cc
+++ b/ash/wallpaper/wallpaper_controller.cc
@@ -1248,6 +1248,10 @@
 }
 
 void WallpaperController::ConfirmPreviewWallpaper() {
+  if (!confirm_preview_wallpaper_callback_) {
+    DCHECK(!reload_preview_wallpaper_callback_);
+    return;
+  }
   std::move(confirm_preview_wallpaper_callback_).Run();
   reload_preview_wallpaper_callback_.Reset();
   for (auto& observer : observers_)
@@ -1473,9 +1477,14 @@
   std::move(callback).Run(IsActiveUserWallpaperControlledByPolicyImpl());
 }
 
-void WallpaperController::GetActiveUserWallpaperLocation(
-    GetActiveUserWallpaperLocationCallback callback) {
-  std::move(callback).Run(GetActiveUserWallpaperLocationImpl());
+void WallpaperController::GetActiveUserWallpaperInfo(
+    GetActiveUserWallpaperInfoCallback callback) {
+  WallpaperInfo info;
+  if (!GetActiveUserWallpaperInfoImpl(&info)) {
+    std::move(callback).Run(std::string(), ash::NUM_WALLPAPER_LAYOUT);
+    return;
+  }
+  std::move(callback).Run(info.location, info.layout);
 }
 
 void WallpaperController::ShouldShowWallpaperSetting(
@@ -2039,19 +2048,20 @@
                             active_user_session->user_info->is_ephemeral);
 }
 
-std::string WallpaperController::GetActiveUserWallpaperLocationImpl() const {
+bool WallpaperController::GetActiveUserWallpaperInfoImpl(
+    WallpaperInfo* info_out) const {
   // The currently active user has index 0.
   const mojom::UserSession* const active_user_session =
       Shell::Get()->session_controller()->GetUserSession(/*user index=*/0);
   if (!active_user_session)
-    return std::string();
+    return false;
 
-  WallpaperInfo info;
-  if (!GetUserWallpaperInfo(active_user_session->user_info->account_id, &info,
+  if (!GetUserWallpaperInfo(active_user_session->user_info->account_id,
+                            info_out,
                             active_user_session->user_info->is_ephemeral)) {
-    return std::string();
+    return false;
   }
-  return info.location;
+  return true;
 }
 
 bool WallpaperController::ShouldShowWallpaperSettingImpl() const {
diff --git a/ash/wallpaper/wallpaper_controller.h b/ash/wallpaper/wallpaper_controller.h
index dcdc646..f7c5849 100644
--- a/ash/wallpaper/wallpaper_controller.h
+++ b/ash/wallpaper/wallpaper_controller.h
@@ -345,8 +345,8 @@
   void IsWallpaperBlurred(IsWallpaperBlurredCallback callback) override;
   void IsActiveUserWallpaperControlledByPolicy(
       IsActiveUserWallpaperControlledByPolicyCallback callback) override;
-  void GetActiveUserWallpaperLocation(
-      GetActiveUserWallpaperLocationCallback callback) override;
+  void GetActiveUserWallpaperInfo(
+      GetActiveUserWallpaperInfoCallback callback) override;
   void ShouldShowWallpaperSetting(
       ShouldShowWallpaperSettingCallback callback) override;
 
@@ -546,8 +546,8 @@
   // Implementation of |IsActiveUserWallpaperControlledByPolicy|.
   bool IsActiveUserWallpaperControlledByPolicyImpl() const;
 
-  // Implementation of |GetActiveUserWallpaperLocation|.
-  std::string GetActiveUserWallpaperLocationImpl() const;
+  // Implementation of |GetActiveUserWallpaperInfo|.
+  bool GetActiveUserWallpaperInfoImpl(WallpaperInfo* info_out) const;
 
   // Implementation of |ShouldShowWallpaperSetting|.
   bool ShouldShowWallpaperSettingImpl() const;
diff --git a/base/win/async_operation.h b/base/win/async_operation.h
index 2c41ddf..97f7aab6 100644
--- a/base/win/async_operation.h
+++ b/base/win/async_operation.h
@@ -108,57 +108,46 @@
 template <typename T>
 using InterfaceT = std::remove_pointer_t<AbiT<T>>;
 
-// Implementation of shared functionality.
+// Compile time switch to decide what container to use for the async results for
+// |T|. Depends on whether the underlying Abi type is a pointer to IUnknown or
+// not. It queries the internals of Windows::Foundation to obtain this
+// information.
+template <typename T>
+using ResultT =
+    std::conditional_t<std::is_convertible<AbiT<T>, IUnknown*>::value,
+                       Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiT<T>>>,
+                       AbiT<T>>;
+
+template <typename T>
+using StorageT =
+    std::conditional_t<std::is_convertible<AbiT<T>, IUnknown*>::value,
+                       Microsoft::WRL::ComPtr<std::remove_pointer_t<AbiT<T>>>,
+                       base::Optional<AbiT<T>>>;
+
+template <typename T>
+HRESULT CopyStorage(const Microsoft::WRL::ComPtr<T>& storage, T** results) {
+  return storage.CopyTo(results);
+}
+
+template <typename T>
+HRESULT CopyStorage(const base::Optional<T>& storage, T* results) {
+  *results = *storage;
+  return S_OK;
+}
+
+}  // namespace internal
+
 template <class T>
-class AsyncOperationBase
+class AsyncOperation
     : public Microsoft::WRL::RuntimeClass<
           Microsoft::WRL::RuntimeClassFlags<
               Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
           ABI::Windows::Foundation::IAsyncOperation<T>> {
  public:
+  using StorageT = internal::StorageT<T>;
+  using ResultT = internal::ResultT<T>;
   using Handler = ABI::Windows::Foundation::IAsyncOperationCompletedHandler<T>;
-
-  AsyncOperationBase() = default;
-  ~AsyncOperationBase() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
-
-  // ABI::Windows::Foundation::IAsyncOperation:
-  IFACEMETHODIMP put_Completed(Handler* handler) override {
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-    handler_ = handler;
-    return S_OK;
-  }
-
-  IFACEMETHODIMP get_Completed(Handler** handler) override {
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-    return handler_.CopyTo(handler);
-  }
-
- protected:
-  void InvokeCompletedHandler() {
-    handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
-  }
-
-  THREAD_CHECKER(thread_checker_);
-
- private:
-  Microsoft::WRL::ComPtr<Handler> handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(AsyncOperationBase);
-};
-
-}  // namespace internal
-
-template <typename T, typename Enable = void>
-class AsyncOperation;
-
-template <typename T>
-class AsyncOperation<
-    T,
-    std::enable_if_t<std::is_base_of<IUnknown, internal::InterfaceT<T>>::value>>
-    : public internal::AsyncOperationBase<T> {
- public:
-  using InterfacePointer = Microsoft::WRL::ComPtr<internal::InterfaceT<T>>;
-  using ResultCallback = base::OnceCallback<void(InterfacePointer)>;
+  using ResultCallback = base::OnceCallback<void(ResultT)>;
 
   AsyncOperation() : weak_factory_(this) {
     // Note: This can't be done in the constructor initializer list. This is
@@ -168,74 +157,49 @@
         base::BindOnce(&AsyncOperation::OnResult, weak_factory_.GetWeakPtr());
   }
 
-  ResultCallback callback() {
-    // Note: `this->` here and below is necessary due to the
-    // -Wmicrosoft-template compiler warning.
-    DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
-    DCHECK(!callback_.is_null());
-    return std::move(callback_);
-  }
+  ~AsyncOperation() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
 
   // ABI::Windows::Foundation::IAsyncOperation:
-  IFACEMETHODIMP GetResults(internal::AbiT<T>* results) override {
-    DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
-    return ptr_ ? ptr_.CopyTo(results) : E_PENDING;
-  }
-
- private:
-  void OnResult(InterfacePointer ptr) {
-    DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
-    DCHECK(!ptr_);
-    ptr_ = std::move(ptr);
-    this->InvokeCompletedHandler();
-  }
-
-  ResultCallback callback_;
-  InterfacePointer ptr_;
-  base::WeakPtrFactory<AsyncOperation> weak_factory_;
-};
-
-template <typename T>
-class AsyncOperation<
-    T,
-    std::enable_if_t<
-        !std::is_base_of<IUnknown, internal::InterfaceT<T>>::value>>
-    : public internal::AsyncOperationBase<T> {
- public:
-  using ResultCallback = base::OnceCallback<void(T)>;
-
-  AsyncOperation() : weak_factory_(this) {
-    callback_ =
-        base::BindOnce(&AsyncOperation::OnResult, weak_factory_.GetWeakPtr());
-  }
-
-  ResultCallback callback() {
-    DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
-    DCHECK(!callback_.is_null());
-    return std::move(callback_);
-  }
-
-  // ABI::Windows::Foundation::IAsyncOperation:
-  IFACEMETHODIMP GetResults(internal::AbiT<T>* results) override {
-    DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
-    if (!value_)
-      return E_PENDING;
-
-    *results = *value_;
+  IFACEMETHODIMP put_Completed(Handler* handler) override {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+    handler_ = handler;
     return S_OK;
   }
+  IFACEMETHODIMP get_Completed(Handler** handler) override {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+    return handler_.CopyTo(handler);
+  }
+  IFACEMETHODIMP GetResults(internal::AbiT<T>* results) override {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+    return storage_ ? internal::CopyStorage(storage_, results) : E_PENDING;
+  }
+
+  ResultCallback callback() {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+    DCHECK(!callback_.is_null());
+    return std::move(callback_);
+  }
 
  private:
-  void OnResult(T result) {
-    DCHECK_CALLED_ON_VALID_THREAD(this->thread_checker_);
-    DCHECK(!value_);
-    value_.emplace(std::move(result));
-    this->InvokeCompletedHandler();
+  void InvokeCompletedHandler() {
+    handler_->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
+  }
+
+  void OnResult(ResultT result) {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+    DCHECK(!storage_);
+    storage_ = std::move(result);
+    InvokeCompletedHandler();
   }
 
   ResultCallback callback_;
-  base::Optional<T> value_;
+  Microsoft::WRL::ComPtr<Handler> handler_;
+  StorageT storage_;
+
+  THREAD_CHECKER(thread_checker_);
   base::WeakPtrFactory<AsyncOperation> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(AsyncOperation);
 };
 
 }  // namespace win
diff --git a/chrome/VERSION b/chrome/VERSION
index 56d2b9ba..8eaccb08 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=69
 MINOR=0
-BUILD=3466
+BUILD=3467
 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java
index 0dcf820f..cad17f4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManager.java
@@ -181,6 +181,13 @@
                 OfflineContentAggregatorNotificationBridgeUiFactory.instance();
                 propagateInteraction(intent);
             }
+
+            @Override
+            public boolean startServiceManagerOnly() {
+                // TODO(qinmin): change this to return true once ServiceManager can be started
+                // without launching full browser.
+                return false;
+            }
         };
 
         try {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java b/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java
index d13a270e..db09d03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/BrowserParts.java
@@ -78,4 +78,12 @@
      * @return Whether GPU process needs to be started during the startup.
      */
     boolean shouldStartGpuProcess();
+
+    /**
+     * @return Whether only ServiceManager should be launched during the startup, without running
+     *         remaining parts of the Chrome.
+     */
+    default boolean startServiceManagerOnly() {
+        return false;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
index eaf5d46..47cfcae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
@@ -328,8 +328,8 @@
             // We want to start this queue once the C++ startup tasks have run; allow the
             // C++ startup to run asynchonously, and set it up to start the Java queue once
             // it has finished.
-            startChromeBrowserProcessesAsync(
-                    delegate.shouldStartGpuProcess(),
+            startChromeBrowserProcessesAsync(delegate.shouldStartGpuProcess(),
+                    delegate.startServiceManagerOnly(),
                     new BrowserStartupController.StartupCallback() {
                         @Override
                         public void onFailure() {
@@ -347,12 +347,13 @@
         }
     }
 
-    private void startChromeBrowserProcessesAsync(
-            boolean startGpuProcess,
-            BrowserStartupController.StartupCallback callback) throws ProcessInitException {
+    private void startChromeBrowserProcessesAsync(boolean startGpuProcess,
+            boolean startServiceManagerOnly, BrowserStartupController.StartupCallback callback)
+            throws ProcessInitException {
         try {
             TraceEvent.begin("ChromeBrowserInitializer.startChromeBrowserProcessesAsync");
-            getBrowserStartupController().startBrowserProcessesAsync(startGpuProcess, callback);
+            getBrowserStartupController().startBrowserProcessesAsync(
+                    startGpuProcess, startServiceManagerOnly, callback);
         } finally {
             TraceEvent.end("ChromeBrowserInitializer.startChromeBrowserProcessesAsync");
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
index e72096c..d7f75bb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -415,7 +415,7 @@
         try {
             String path = UiUtils.getDirectoryForImageCapture(ContextUtils.getApplicationContext())
                     + File.separator + SHARE_IMAGES_DIRECTORY_NAME;
-            contents.getContentBitmapAsync(
+            contents.writeContentBitmapToDiskAsync(
                     width, height, path, new ExternallyVisibleUriCallback(callback));
         } catch (IOException e) {
             Log.e(TAG, "Error getting content bitmap: ", e);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java
index 7927aa4..d771030e 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java
@@ -67,7 +67,8 @@
 
         @Override
         public void startBrowserProcessesAsync(boolean startGpuProcess,
-                final StartupCallback callback) throws ProcessInitException {}
+                boolean startServiceManagerOnly, final StartupCallback callback)
+                throws ProcessInitException {}
 
         @Override
         public void startBrowserProcessesSync(boolean singleProcess) throws ProcessInitException {}
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index ad685d6..07c2468 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -917,6 +917,9 @@
   <message name="IDS_FILE_BROWSER_DROP_TARGET_ACCESS_RESTRICTED" desc="Tooltip label displayed besides mouse pointer when dragging files or folders over a removable device whose write access is restricted by administration policy.">
     Access restricted
   </message>
+  <message name="IDS_FILE_BROWSER_DROP_TARGET_FOLDER_NO_MOVE_PERMISSION" desc="Tooltip label displayed besides mouse pointer while dragging files or folders over a Team Drive or folder in Drive that does not have write access.">
+    You don't have permission to move files into '<ph name="FOLDER_NAME">$1<ex>Trip Photos</ex></ph>'.
+  </message>
   <message name="IDS_FILE_BROWSER_DROP_TARGET_OPENING_LINUX_FILES" desc="Tooltip label displayed besides mouse pointer when dragging files or folders over Linux Files root before the container has been started and mounted.">
     Opening Linux Files...
   </message>
@@ -4880,6 +4883,9 @@
   <message name="IDS_CROSTINI_INSTALLER_START_CONTAINER_MESSAGE" desc="Text shown in the Crostini installer dialog when the container inside the VM is starting">
     Starting container inside VM.
   </message>
+  <message name="IDS_CROSTINI_INSTALLER_OFFLINE_ERROR" desc="Text shown in the Crostini installer dialog when there is no internet connection">
+    ERROR: Your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> must be connected to the Internet to install the <ph name="APP_NAME">$2<ex>Terminal</ex></ph>.
+  </message>
   <message name="IDS_CROSTINI_INSTALLER_LOAD_TERMINA_ERROR" desc="Text shown in the Crostini installer dialog when the VM component fails to load">
     ERROR: Failed to load VM component.
   </message>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 89954f2..98d6107 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2964,6 +2964,12 @@
   <message name="IDS_SETTINGS_SITE_SETTINGS_SITE_CLEAR_STORAGE_CONFIRMATION" desc="Text for the dialog that warns about clearing storage used by a site (excluding cookies).">
     All data stored by <ph name="SITE">$1<ex>www.example.com</ex></ph> will be deleted, except for cookies.
   </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_RESET_DIALOG_TITLE" desc="Title of the dialog that warns about resetting all permissions for a group of sites.">
+    Reset site permissions?
+  </message>
+  <message name="IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_RESET_CONFIRMATION" desc="Text for the dialog that warns about resetting all permissions for a group of sites.">
+    Sites under <ph name="SITE_GROUP_NAME">$1<ex>google.co.uk</ex></ph> will also be reset.
+  </message>
   <message name="IDS_SETTINGS_SITE_SETTINGS_COOKIE_REMOVE_MULTIPLE" desc="Text for the dialog that warns about deleting all site data.">
     This will delete any data stored on your device for all the sites shown. Do you want to continue?
   </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 544e0d3..ef9f5e7c5 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1802,6 +1802,7 @@
     "//crypto",
     "//crypto:platform",
     "//device/base",
+    "//device/fido",
     "//device/usb/mojo",
     "//device/usb/public/mojom",
     "//device/vr/buildflags",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 58cece50..1107a0f 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3898,6 +3898,11 @@
      FEATURE_VALUE_TYPE(ash::features::kTapVisualizerApp)},
 #endif
 
+    {"enable-websocket-auth-connection-reuse",
+     flag_descriptions::kWebSocketHandshakeReuseConnectionName,
+     flag_descriptions::kWebSocketHandshakeReuseConnectionDescription, kOsAll,
+     FEATURE_VALUE_TYPE(net::WebSocketBasicHandshakeStream::
+                            kWebSocketHandshakeReuseConnection)},
     {"unsafely-treat-insecure-origin-as-secure",
      flag_descriptions::kTreatInsecureOriginAsSecureName,
      flag_descriptions::kTreatInsecureOriginAsSecureDescription, kOsAll,
@@ -3953,6 +3958,11 @@
      flag_descriptions::kEnableCSSFragmentIdentifiersDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kCSSFragmentIdentifiers)},
 
+    {"enable-ephemeral-flash-permission",
+     flag_descriptions::kEnableEphemeralFlashPermissionName,
+     flag_descriptions::kEnableEphemeralFlashPermissionDescription, kOsDesktop,
+     SINGLE_VALUE_TYPE(switches::kEnableEphemeralFlashPermission)},
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/vr/vr_shell_gl.cc b/chrome/browser/android/vr/vr_shell_gl.cc
index 11863d0..50696bf 100644
--- a/chrome/browser/android/vr/vr_shell_gl.cc
+++ b/chrome/browser/android/vr/vr_shell_gl.cc
@@ -1877,6 +1877,18 @@
   TransformToGvrMat(head_pose, &mat);
   bool is_webvr_frame = frame_index >= 0;
   {
+    std::unique_ptr<ScopedGpuTrace> browser_gpu_trace;
+    if (gl::GLFence::IsGpuFenceSupported() && !is_webvr_frame) {
+      // This fence instance is created for the tracing side effect. Insert it
+      // before GVR submit. Then replace the previous instance below after GVR
+      // submit completes, at which point the previous fence (if any) should be
+      // complete. Doing this in two steps avoids a race condition - a fence
+      // that was inserted after Submit may not be complete yet when the next
+      // Submit finishes.
+      browser_gpu_trace = std::make_unique<ScopedGpuTrace>(
+          "gpu", "VrShellGl::PostSubmitDrawOnGpu");
+    }
+
     TRACE_EVENT0("gpu", "VrShellGl::SubmitToGvr");
     base::TimeTicks submit_start = base::TimeTicks::Now();
     acquired_frame_.Submit(viewport_list_, mat);
@@ -1884,13 +1896,11 @@
     webvr_submit_time_.AddSample(submit_done - submit_start);
     CHECK(!acquired_frame_);
 
-    if (gl::GLFence::IsGpuFenceSupported() && !is_webvr_frame) {
-      // This instance is created for the tracing side effect. Create a new
-      // instance here to replace previous instace will record trace for
-      // previous instance and start a new trace for the new instance.
+    if (browser_gpu_trace) {
+      // Replacing the previous instance will record the trace result for
+      // the previous instance.
       DCHECK(!gpu_trace_ || gpu_trace_->fence()->HasCompleted());
-      gpu_trace_ = std::make_unique<ScopedGpuTrace>(
-          "gpu", "VrShellGl::PostSubmitDrawOnGpu");
+      gpu_trace_ = std::move(browser_gpu_trace);
     }
   }
 
diff --git a/chrome/browser/apps/app_shim/DEPS b/chrome/browser/apps/app_shim/DEPS
deleted file mode 100644
index 61ef5fec..0000000
--- a/chrome/browser/apps/app_shim/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+mojo/edk/embedder",
-]
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc
index 929085d1..921a92a 100644
--- a/chrome/browser/autofill/form_structure_browsertest.cc
+++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -200,7 +200,7 @@
   AutofillManager* autofill_manager = autofill_driver->autofill_manager();
   ASSERT_NE(nullptr, autofill_manager);
   const std::vector<std::unique_ptr<FormStructure>>& forms =
-      autofill_manager->form_structures_;
+      autofill_manager->form_structures();
   *output = FormStructuresToString(forms);
 }
 
diff --git a/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc b/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
index 765a7d4..c308fae 100644
--- a/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
+++ b/chrome/browser/browsing_data/counters/sync_aware_counter_browsertest.cc
@@ -130,15 +130,16 @@
   EXPECT_FALSE(IsSyncEnabled());
 
   // If autofill sync is not affected, the counter is not restarted.
-  syncer::ModelTypeSet only_history(syncer::HISTORY_DELETE_DIRECTIVES);
+  syncer::ModelTypeSet only_history(syncer::TYPED_URLS);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->ChangePreferredDataTypes(only_history);
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false, only_history);
   sync_blocker.reset();
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
 
   // We start syncing autofill again. This restarts the counter.
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->ChangePreferredDataTypes(syncer::ModelTypeSet::All());
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false,
+                                     syncer::UserSelectableTypes());
   sync_blocker.reset();
   WaitForCounting();
   EXPECT_TRUE(IsSyncEnabled());
@@ -191,16 +192,17 @@
   EXPECT_FALSE(IsSyncEnabled());
 
   // If password sync is not affected, the counter is not restarted.
-  syncer::ModelTypeSet only_history(syncer::HISTORY_DELETE_DIRECTIVES);
-  sync_service->ChangePreferredDataTypes(only_history);
+  syncer::ModelTypeSet only_history(syncer::TYPED_URLS);
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false, only_history);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->ChangePreferredDataTypes(only_history);
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false, only_history);
   sync_blocker.reset();
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
 
   // We start syncing passwords again. This restarts the counter.
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->ChangePreferredDataTypes(syncer::ModelTypeSet::All());
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false,
+                                     syncer::UserSelectableTypes());
   sync_blocker.reset();
   WaitForCounting();
   EXPECT_TRUE(IsSyncEnabled());
@@ -249,7 +251,7 @@
   // We stop syncing history deletion in particular. This restarts the counter.
   syncer::ModelTypeSet everything_except_history =
       syncer::UserSelectableTypes();
-  everything_except_history.Remove(syncer::HISTORY_DELETE_DIRECTIVES);
+  everything_except_history.Remove(syncer::TYPED_URLS);
   auto sync_blocker = sync_service->GetSetupInProgressHandle();
   sync_service->OnUserChoseDatatypes(/*sync_everything=*/false,
                                      everything_except_history);
@@ -259,9 +261,9 @@
 
   // If the history deletion sync is not affected, the counter is not restarted.
   syncer::ModelTypeSet only_passwords(syncer::PASSWORDS);
-  sync_service->ChangePreferredDataTypes(only_passwords);
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false, only_passwords);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->ChangePreferredDataTypes(only_passwords);
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false, only_passwords);
   sync_blocker.reset();
   EXPECT_FALSE(counter.HasTrackedTasks());
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
@@ -270,14 +272,16 @@
   syncer::ModelTypeSet autofill_and_passwords(syncer::AUTOFILL,
                                               syncer::PASSWORDS);
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->ChangePreferredDataTypes(autofill_and_passwords);
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false,
+                                     autofill_and_passwords);
   sync_blocker.reset();
   EXPECT_FALSE(counter.HasTrackedTasks());
   EXPECT_FALSE(CountingFinishedSinceLastAsked());
 
   // We start syncing history deletion again. This restarts the counter.
   sync_blocker = sync_service->GetSetupInProgressHandle();
-  sync_service->ChangePreferredDataTypes(syncer::ModelTypeSet::All());
+  sync_service->OnUserChoseDatatypes(/*sync_everything=*/false,
+                                     syncer::UserSelectableTypes());
   sync_blocker.reset();
   WaitForCounting();
   EXPECT_TRUE(IsSyncEnabled());
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index e7269c7..c92cf0b 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -316,6 +316,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
 #include "chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h"
+#include "chrome/browser/ui/ash/tablet_mode_client.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chromeos/chromeos_constants.h"
 #include "chromeos/chromeos_features.h"
@@ -1327,6 +1328,17 @@
 #endif
 }
 
+bool ChromeContentBrowserClient::ShouldUseMobileFlingCurve() const {
+#if defined(OS_ANDROID)
+  return true;
+#elif defined(OS_CHROMEOS)
+  return TabletModeClient::Get() &&
+         TabletModeClient::Get()->tablet_mode_enabled();
+#else
+  return false;
+#endif  // defined(OS_ANDROID)
+}
+
 bool ChromeContentBrowserClient::ShouldUseProcessPerSite(
     content::BrowserContext* browser_context, const GURL& effective_url) {
   // Non-extension, non-Instant URLs should generally use
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 52799c8..db48375 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -108,6 +108,7 @@
   bool AllowGpuLaunchRetryOnIOThread() override;
   GURL GetEffectiveURL(content::BrowserContext* browser_context,
                        const GURL& url) override;
+  bool ShouldUseMobileFlingCurve() const override;
   bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
                                const GURL& effective_url) override;
   bool ShouldUseSpareRenderProcessHost(content::BrowserContext* browser_context,
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
index 2dc6667..a46d0f8 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.cc
@@ -7,7 +7,12 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_bridge_impl.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "components/arc/arc_features.h"
+#include "components/crx_file/id_util.h"
+#include "components/prefs/pref_service.h"
 #include "ui/base/ime/chromeos/extension_ime_util.h"
 
 namespace arc {
@@ -20,6 +25,11 @@
 constexpr char kChromeOSIMEIdInArcContainer[] =
     "org.chromium.arc.ime/.ArcInputMethodService";
 
+// The name of the proxy IME extension that is used when registering ARC IMEs to
+// InputMethodManager.
+constexpr char kArcIMEProxyExtensionName[] =
+    "org.chromium.arc.inputmethod.proxy";
+
 // Singleton factory for ArcInputMethodManagerService
 class ArcInputMethodManagerServiceFactory
     : public internal::ArcBrowserContextKeyedServiceFactoryBase<
@@ -59,15 +69,25 @@
 ArcInputMethodManagerService::ArcInputMethodManagerService(
     content::BrowserContext* context,
     ArcBridgeService* bridge_service)
-    : imm_bridge_(
+    : profile_(Profile::FromBrowserContext(context)),
+      imm_bridge_(
           std::make_unique<ArcInputMethodManagerBridgeImpl>(this,
-                                                            bridge_service)) {
+                                                            bridge_service)),
+      proxy_ime_extension_id_(
+          crx_file::id_util::GenerateId(kArcIMEProxyExtensionName)),
+      proxy_ime_engine_(std::make_unique<chromeos::InputMethodEngine>()) {
   auto* imm = chromeos::input_method::InputMethodManager::Get();
   imm->AddObserver(this);
   imm->AddImeMenuObserver(this);
 }
 
 ArcInputMethodManagerService::~ArcInputMethodManagerService() {
+  // Remove any Arc IME entry from preferences before shutting down.
+  // IME states (installed/enabled/disabled) are stored in Android's settings,
+  // that will be restored after Arc container starts next time.
+  RemoveArcIMEFromPrefs();
+  profile_->GetPrefs()->CommitPendingWrite();
+
   auto* imm = chromeos::input_method::InputMethodManager::Get();
   imm->RemoveImeMenuObserver(this);
   imm->RemoveObserver(this);
@@ -86,8 +106,28 @@
 
 void ArcInputMethodManagerService::OnImeInfoChanged(
     std::vector<mojom::ImeInfoPtr> ime_info_array) {
-  // Please see https://crbug.com/845079.
-  NOTIMPLEMENTED();
+  using namespace chromeos::input_method;
+
+  if (!base::FeatureList::IsEnabled(kEnableInputMethodFeature))
+    return;
+
+  scoped_refptr<InputMethodManager::State> state =
+      InputMethodManager::Get()->GetActiveIMEState();
+  // Remove the old registered entry.
+  state->RemoveInputMethodExtension(proxy_ime_extension_id_);
+
+  // Convert ime_info_array to InputMethodDescriptors.
+  InputMethodDescriptors descriptors;
+  for (const auto& ime_info : ime_info_array)
+    descriptors.push_back(BuildInputMethodDescriptor(ime_info.get()));
+  if (descriptors.empty()) {
+    // If no ARC IME is installed, remove ARC IME entry from preferences.
+    RemoveArcIMEFromPrefs();
+    return;
+  }
+  // Add the proxy IME entry to InputMethodManager if any ARC IME is installed.
+  state->AddInputMethodExtension(proxy_ime_extension_id_, descriptors,
+                                 proxy_ime_engine_.get());
 }
 
 void ArcInputMethodManagerService::ImeMenuListChanged() {
@@ -122,7 +162,8 @@
     chromeos::input_method::InputMethodManager* manager,
     Profile* profile,
     bool /* show_message */) {
-  auto state = manager->GetActiveIMEState();
+  scoped_refptr<chromeos::input_method::InputMethodManager::State> state =
+      manager->GetActiveIMEState();
   if (!state)
     return;
   SwitchImeTo(state->GetCurrentInputMethod().id());
@@ -165,4 +206,53 @@
                         ime_id, component_id));
 }
 
+chromeos::input_method::InputMethodDescriptor
+ArcInputMethodManagerService::BuildInputMethodDescriptor(
+    const mojom::ImeInfo* info) {
+  // TODO(yhanada): Set the special layout/language value for ARC IMEs after
+  // making settings and IME menu tray support it.
+  std::vector<std::string> layouts{"us"};
+  std::vector<std::string> languages{"en-US"};
+  const std::string display_name = info->display_name;
+
+  const std::string& input_method_id =
+      chromeos::extension_ime_util::GetArcInputMethodID(proxy_ime_extension_id_,
+                                                        info->ime_id);
+  // TODO(yhanada): Set the indicator string after the UI spec is finalized.
+  return chromeos::input_method::InputMethodDescriptor(
+      input_method_id, display_name, std::string() /* indicator */, layouts,
+      languages, false /* is_login_keyboard */, GURL(info->settings_url),
+      GURL() /* input_view_url */);
+}
+
+void ArcInputMethodManagerService::RemoveArcIMEFromPrefs() {
+  RemoveArcIMEFromPref(prefs::kLanguageEnabledExtensionImes);
+  RemoveArcIMEFromPref(prefs::kLanguagePreloadEngines);
+
+  PrefService* prefs = profile_->GetPrefs();
+  if (chromeos::extension_ime_util::IsArcIME(
+          prefs->GetString(prefs::kLanguageCurrentInputMethod))) {
+    prefs->SetString(prefs::kLanguageCurrentInputMethod, std::string());
+  }
+  if (chromeos::extension_ime_util::IsArcIME(
+          prefs->GetString(prefs::kLanguagePreviousInputMethod))) {
+    prefs->SetString(prefs::kLanguagePreviousInputMethod, std::string());
+  }
+}
+
+void ArcInputMethodManagerService::RemoveArcIMEFromPref(const char* pref_name) {
+  const std::string ime_ids = profile_->GetPrefs()->GetString(pref_name);
+  std::vector<std::string> ime_id_list = base::SplitString(
+      ime_ids, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+  auto iter = std::remove_if(
+      ime_id_list.begin(), ime_id_list.end(), [](const std::string& id) {
+        return chromeos::extension_ime_util::IsArcIME(id);
+      });
+  ime_id_list.erase(iter, ime_id_list.end());
+
+  profile_->GetPrefs()->SetString(pref_name,
+                                  base::JoinString(ime_id_list, ","));
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.h b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.h
index 0dd7c5f..678401d 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.h
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_bridge.h"
+#include "chrome/browser/chromeos/input_method/input_method_engine.h"
 #include "components/arc/common/input_method_manager.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
@@ -64,10 +65,26 @@
  private:
   void EnableIme(const std::string& ime_id, bool enable);
   void SwitchImeTo(const std::string& ime_id);
+  chromeos::input_method::InputMethodDescriptor BuildInputMethodDescriptor(
+      const mojom::ImeInfo* info);
+
+  // Removes ARC IME from IME related prefs that are current active IME pref,
+  // previous active IME pref, enabled IME list pref and preloading IME list
+  // pref.
+  void RemoveArcIMEFromPrefs();
+  void RemoveArcIMEFromPref(const char* pref_name);
+
+  Profile* const profile_;
 
   std::unique_ptr<ArcInputMethodManagerBridge> imm_bridge_;
   std::set<std::string> active_arc_ime_ids_;
 
+  // ArcInputMethodManager installs a proxy IME to redirect IME related events
+  // from/to ARC IMEs in the container. The below two variables are for the
+  // proxy IME.
+  const std::string proxy_ime_extension_id_;
+  std::unique_ptr<chromeos::InputMethodEngine> proxy_ime_engine_;
+
   DISALLOW_COPY_AND_ASSIGN(ArcInputMethodManagerService);
 };
 
diff --git a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
index 24af091ac..742a70a 100644
--- a/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/input_method_manager/arc_input_method_manager_service_unittest.cc
@@ -11,6 +11,8 @@
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
 #include "components/arc/arc_features.h"
 #include "components/arc/arc_service_manager.h"
 #include "components/arc/test/test_browser_context.h"
@@ -31,7 +33,8 @@
   // The fake im::InputMethodManager::State implementation for testing.
   class TestState : public im::MockInputMethodManager::State {
    public:
-    TestState() : active_input_method_ids_() {}
+    TestState()
+        : added_input_method_extensions_(), active_input_method_ids_() {}
 
     const std::vector<std::string>& GetActiveInputMethodIds() const override {
       return active_input_method_ids_;
@@ -45,6 +48,18 @@
       return descriptor;
     }
 
+    void AddInputMethodExtension(
+        const std::string& extension_id,
+        const im::InputMethodDescriptors& descriptors,
+        ui::IMEEngineHandlerInterface* instance) override {
+      added_input_method_extensions_.push_back(
+          std::make_tuple(extension_id, descriptors));
+    }
+
+    void RemoveInputMethodExtension(const std::string& extension_id) override {
+      removed_input_method_extensions_.push_back(extension_id);
+    }
+
     void AddActiveInputMethodId(const std::string& ime_id) {
       if (!std::count(active_input_method_ids_.begin(),
                       active_input_method_ids_.end(), ime_id)) {
@@ -62,6 +77,10 @@
       active_ime_id_ = ime_id;
     }
 
+    std::vector<std::tuple<std::string, im::InputMethodDescriptors>>
+        added_input_method_extensions_;
+    std::vector<std::string> removed_input_method_extensions_;
+
    protected:
     friend base::RefCounted<InputMethodManager::State>;
     ~TestState() override = default;
@@ -116,7 +135,7 @@
  protected:
   ArcInputMethodManagerServiceTest()
       : arc_service_manager_(std::make_unique<ArcServiceManager>()) {}
-  ~ArcInputMethodManagerServiceTest() override {}
+  ~ArcInputMethodManagerServiceTest() override = default;
 
   ArcInputMethodManagerService* service() { return service_; }
 
@@ -124,16 +143,15 @@
 
   TestInputMethodManager* imm() { return input_method_manager_; }
 
+  TestingProfile* profile() { return profile_.get(); }
+
   void SetUp() override {
     input_method_manager_ = new TestInputMethodManager();
     chromeos::input_method::InputMethodManager::Initialize(
         input_method_manager_);
-
-    context_ = std::make_unique<TestBrowserContext>();
-
+    profile_ = std::make_unique<TestingProfile>();
     service_ = ArcInputMethodManagerService::GetForBrowserContextForTesting(
-        context_.get());
-
+        profile_.get());
     test_bridge_ = new TestInputMethodManagerBridge();
     service_->SetInputMethodManagerBridgeForTesting(
         base::WrapUnique(test_bridge_));
@@ -142,16 +160,14 @@
   void TearDown() override {
     test_bridge_ = nullptr;
     service_->Shutdown();
-
-    context_.reset(nullptr);
-
+    profile_.reset(nullptr);
     chromeos::input_method::InputMethodManager::Shutdown();
   }
 
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   std::unique_ptr<ArcServiceManager> arc_service_manager_;
-  std::unique_ptr<TestBrowserContext> context_;
+  std::unique_ptr<TestingProfile> profile_;
   TestInputMethodManager* input_method_manager_ = nullptr;
   TestInputMethodManagerBridge* test_bridge_ = nullptr;  // Owned by |service_|
 
@@ -257,4 +273,88 @@
   EXPECT_EQ("ime.id.in.arc.container", bridge()->switch_ime_to_calls_[2]);
 }
 
+TEST_F(ArcInputMethodManagerServiceTest, OnImeInfoChanged) {
+  using namespace chromeos::extension_ime_util;
+
+  base::test::ScopedFeatureList feature;
+  feature.InitAndEnableFeature(kEnableInputMethodFeature);
+
+  // Preparing 2 ImeInfo.
+  const std::string android_ime_id1 = "test.arc.ime";
+  const std::string display_name1 = "DisplayName";
+  const std::string settings_url1 = "url_to_settings";
+  mojom::ImeInfoPtr info1 = mojom::ImeInfo::New();
+  info1->ime_id = android_ime_id1;
+  info1->display_name = display_name1;
+  info1->enabled = false;
+  info1->settings_url = settings_url1;
+
+  const std::string android_ime_id2 = "test.arc.ime2";
+  const std::string display_name2 = "DisplayName2";
+  const std::string settings_url2 = "url_to_settings2";
+  mojom::ImeInfoPtr info2 = mojom::ImeInfo::New();
+  info2->ime_id = android_ime_id2;
+  info2->display_name = display_name2;
+  info2->enabled = true;
+  info2->settings_url = settings_url2;
+
+  std::vector<
+      std::tuple<std::string, chromeos::input_method::InputMethodDescriptors>>&
+      added_extensions = imm()->state()->added_input_method_extensions_;
+  ASSERT_EQ(0u, added_extensions.size());
+
+  {
+    // Passing empty info_array shouldn't call AddInputMethodExtension.
+    std::vector<mojom::ImeInfoPtr> info_array{};
+    service()->OnImeInfoChanged(std::move(info_array));
+    EXPECT_TRUE(added_extensions.empty());
+  }
+
+  {
+    // Adding one ARC IME.
+    std::vector<mojom::ImeInfoPtr> info_array;
+    info_array.push_back(info1.Clone());
+    service()->OnImeInfoChanged(std::move(info_array));
+    ASSERT_EQ(1u, added_extensions.size());
+    ASSERT_EQ(1u, std::get<1>(added_extensions[0]).size());
+    EXPECT_EQ(android_ime_id1, GetComponentIDByInputMethodID(
+                                   std::get<1>(added_extensions[0])[0].id()));
+    EXPECT_EQ(display_name1, std::get<1>(added_extensions[0])[0].name());
+
+    // Emulate enabling ARC IME from chrome://settings.
+    const std::string& arc_ime_id = std::get<1>(added_extensions[0])[0].id();
+    profile()->GetPrefs()->SetString(prefs::kLanguageEnabledExtensionImes,
+                                     arc_ime_id);
+    EXPECT_EQ(arc_ime_id, profile()->GetPrefs()->GetString(
+                              prefs::kLanguageEnabledExtensionImes));
+
+    // Removing the ARC IME should clear the pref
+    std::vector<mojom::ImeInfoPtr> empty_info_array;
+    service()->OnImeInfoChanged(std::move(empty_info_array));
+    EXPECT_TRUE(profile()
+                    ->GetPrefs()
+                    ->GetString(prefs::kLanguageEnabledExtensionImes)
+                    .empty());
+    added_extensions.clear();
+  }
+
+  {
+    // Adding two ARC IMEs.
+    std::vector<mojom::ImeInfoPtr> info_array;
+    info_array.push_back(info1.Clone());
+    info_array.push_back(info2.Clone());
+    service()->OnImeInfoChanged(std::move(info_array));
+    // The ARC IMEs should be registered as two IMEs in one extension.
+    ASSERT_EQ(1u, added_extensions.size());
+    ASSERT_EQ(2u, std::get<1>(added_extensions[0]).size());
+    EXPECT_EQ(android_ime_id1, GetComponentIDByInputMethodID(
+                                   std::get<1>(added_extensions[0])[0].id()));
+    EXPECT_EQ(display_name1, std::get<1>(added_extensions[0])[0].name());
+    EXPECT_EQ(android_ime_id2, GetComponentIDByInputMethodID(
+                                   std::get<1>(added_extensions[0])[1].id()));
+    EXPECT_EQ(display_name2, std::get<1>(added_extensions[0])[1].name());
+    added_extensions.clear();
+  }
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/extensions/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc b/chrome/browser/chromeos/extensions/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc
index 742d3217..f666ce6 100644
--- a/chrome/browser/chromeos/extensions/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc
+++ b/chrome/browser/chromeos/extensions/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc
@@ -183,7 +183,7 @@
       collections_info_list;
 
   backdrop::GetCollectionsResponse collections_response;
-  if (!collections_response.ParseFromString(response)) {
+  if (response.empty() || !collections_response.ParseFromString(response)) {
     LOG(ERROR) << "Deserializing Backdrop wallpaper proto for collection info "
                   "failed.";
     backdrop_fetcher_.reset();
@@ -259,7 +259,7 @@
   std::vector<extensions::api::wallpaper_private::ImageInfo> images_info_list;
 
   backdrop::GetImagesInCollectionResponse images_response;
-  if (!images_response.ParseFromString(response)) {
+  if (response.empty() || !images_response.ParseFromString(response)) {
     LOG(ERROR) << "Deserializing Backdrop wallpaper proto for collection "
                << collection_id_ << " failed";
     backdrop_fetcher_.reset();
@@ -338,7 +338,8 @@
   extensions::api::wallpaper_private::ImageInfo image_info;
 
   backdrop::GetImageFromCollectionResponse surprise_me_image_response;
-  if (!surprise_me_image_response.ParseFromString(response)) {
+  if (response.empty() ||
+      !surprise_me_image_response.ParseFromString(response)) {
     LOG(ERROR) << "Deserializing surprise me wallpaper proto for collection "
                << collection_id_ << " failed";
     backdrop_fetcher_.reset();
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
index e78c40d9..deb2929 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc
@@ -504,6 +504,8 @@
              IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_WARNING);
   SET_STRING("DRAGGING_MULTIPLE_ITEMS",
              IDS_FILE_BROWSER_DRAGGING_MULTIPLE_ITEMS);
+  SET_STRING("DROP_TARGET_FOLDER_NO_MOVE_PERMISSION",
+             IDS_FILE_BROWSER_DROP_TARGET_FOLDER_NO_MOVE_PERMISSION);
   SET_STRING("ERROR_CREATING_FOLDER", IDS_FILE_BROWSER_ERROR_CREATING_FOLDER);
   SET_STRING("ERROR_HIDDEN_NAME", IDS_FILE_BROWSER_ERROR_HIDDEN_NAME);
   SET_STRING("ERROR_INVALID_CHARACTER",
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
index ff5e779..852c2b4a 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.cc
@@ -57,6 +57,11 @@
   return ash::WALLPAPER_LAYOUT_CENTER;
 }
 
+std::string GetLayoutString(const ash::WallpaperLayout& layout) {
+  return kWallpaperLayoutArrays[layout >= ash::NUM_WALLPAPER_LAYOUT ? 0
+                                                                    : layout];
+}
+
 void RecordCustomWallpaperLayout(const ash::WallpaperLayout& layout) {
   UMA_HISTOGRAM_ENUMERATION("Ash.Wallpaper.CustomLayout", layout,
                             ash::NUM_WALLPAPER_LAYOUT);
diff --git a/chrome/browser/chromeos/extensions/wallpaper_function_base.h b/chrome/browser/chromeos/extensions/wallpaper_function_base.h
index f3bf52b9..54b8c6a 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_function_base.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_function_base.h
@@ -23,6 +23,8 @@
 
 ash::WallpaperLayout GetLayoutEnum(const std::string& layout);
 
+std::string GetLayoutString(const ash::WallpaperLayout& layout);
+
 // This is used to record the wallpaper layout when the user sets a custom
 // wallpaper or changes the existing custom wallpaper's layout.
 void RecordCustomWallpaperLayout(const ash::WallpaperLayout& layout);
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
index b7f0d1f..7c1e726 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc
@@ -266,17 +266,19 @@
                                               ? GetBackdropWallpaperSuffix()
                                               : kHighResolutionSuffix);
 
-  WallpaperControllerClient::Get()->GetActiveUserWallpaperLocation(
-      base::BindOnce(
-          &WallpaperPrivateGetStringsFunction::OnWallpaperLocationReturned,
-          this, std::move(dict)));
+  WallpaperControllerClient::Get()->GetActiveUserWallpaperInfo(base::BindOnce(
+      &WallpaperPrivateGetStringsFunction::OnWallpaperInfoReturned, this,
+      std::move(dict)));
   return RespondLater();
 }
 
-void WallpaperPrivateGetStringsFunction::OnWallpaperLocationReturned(
+void WallpaperPrivateGetStringsFunction::OnWallpaperInfoReturned(
     std::unique_ptr<base::DictionaryValue> dict,
-    const std::string& location) {
+    const std::string& location,
+    ash::WallpaperLayout layout) {
   dict->SetString("currentWallpaper", location);
+  dict->SetString("currentWallpaperLayout",
+                  wallpaper_api_util::GetLayoutString(layout));
   Respond(OneArgument(std::move(dict)));
 }
 
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.h b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
index 0d0c0213..2c9969a 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api.h
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.h
@@ -33,9 +33,10 @@
   ResponseAction Run() override;
 
  private:
-  // Responds with the dictionary after getting the wallpaper location.
-  void OnWallpaperLocationReturned(std::unique_ptr<base::DictionaryValue> dict,
-                                   const std::string& location);
+  // Responds with the dictionary after getting the wallpaper info.
+  void OnWallpaperInfoReturned(std::unique_ptr<base::DictionaryValue> dict,
+                               const std::string& location,
+                               ash::WallpaperLayout layout);
 };
 
 // Check if sync themes setting is enabled.
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 0cb1ea2..ff05505 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -219,14 +219,26 @@
 WRAPPED_INSTANTIATE_TEST_CASE_P(
     ContextMenu, /* context_menu.js */
     FilesAppBrowserTest,
-    ::testing::Values(TestCase("checkDeleteEnabledForReadWriteFile"),
-                      TestCase("checkDeleteDisabledForReadOnlyDocument"),
-                      TestCase("checkDeleteDisabledForReadOnlyFile"),
-                      TestCase("checkDeleteDisabledForReadOnlyFolder"),
-                      TestCase("checkRenameEnabledForReadWriteFile"),
-                      TestCase("checkRenameDisabledForReadOnlyDocument"),
-                      TestCase("checkRenameDisabledForReadOnlyFile"),
-                      TestCase("checkRenameDisabledForReadOnlyFolder")));
+    ::testing::Values(
+        TestCase("checkDeleteEnabledForReadWriteFile"),
+        TestCase("checkDeleteDisabledForReadOnlyDocument"),
+        TestCase("checkDeleteDisabledForReadOnlyFile"),
+        TestCase("checkDeleteDisabledForReadOnlyFolder"),
+        TestCase("checkRenameEnabledForReadWriteFile"),
+        TestCase("checkRenameDisabledForReadOnlyDocument"),
+        TestCase("checkRenameDisabledForReadOnlyFile"),
+        TestCase("checkRenameDisabledForReadOnlyFolder"),
+        TestCase("checkCopyEnabledForReadWriteFile"),
+        TestCase("checkCopyEnabledForReadOnlyDocument"),
+        TestCase("checkCopyDisabledForStrictReadOnlyDocument"),
+        TestCase("checkCopyEnabledForReadOnlyFile"),
+        TestCase("checkCopyEnabledForReadOnlyFolder"),
+        TestCase("checkCutEnabledForReadWriteFile"),
+        TestCase("checkCutDisabledForReadOnlyDocument"),
+        TestCase("checkCutDisabledForReadOnlyFile"),
+        TestCase("checkCutDisabledForReadOnlyFolder"),
+        TestCase("checkPasteIntoFolderEnabledForReadWriteFolder"),
+        TestCase("checkPasteIntoFolderDisabledForReadOnlyFolder")));
 
 WRAPPED_INSTANTIATE_TEST_CASE_P(
     Delete, /* delete.js */
diff --git a/chrome/browser/chromeos/oauth2_token_service_delegate.cc b/chrome/browser/chromeos/oauth2_token_service_delegate.cc
index e45de2b..6bc35a6 100644
--- a/chrome/browser/chromeos/oauth2_token_service_delegate.cc
+++ b/chrome/browser/chromeos/oauth2_token_service_delegate.cc
@@ -9,7 +9,6 @@
 
 #include "base/bind.h"
 #include "base/logging.h"
-#include "chrome/browser/browser_process.h"
 #include "chromeos/account_manager/account_manager.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 
@@ -140,13 +139,7 @@
 
 net::URLRequestContextGetter*
 ChromeOSOAuth2TokenServiceDelegate::GetRequestContext() const {
-  // LSTs on Chrome are not channel/token bound for now and hence we can use
-  // the system request context.
-  // Note that we cannot use the Profile's request context since
-  // |AccountManager| acts outside the scope of Profiles.
-  // TODO(sinhak): Create a new |URLRequestContext| for |AccountManager| which
-  // conforms to token binding when those details are finalized.
-  return g_browser_process->system_request_context();
+  return account_manager_->GetUrlRequestContext();
 }
 
 OAuth2TokenServiceDelegate::LoadCredentialsState
diff --git a/chrome/browser/devtools/devtools_eye_dropper.cc b/chrome/browser/devtools/devtools_eye_dropper.cc
index fe1ce9f..b82f19a 100644
--- a/chrome/browser/devtools/devtools_eye_dropper.cc
+++ b/chrome/browser/devtools/devtools_eye_dropper.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/devtools/devtools_eye_dropper.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "build/build_config.h"
 #include "cc/paint/skia_paint_canvas.h"
@@ -345,6 +347,4 @@
   UpdateCursor();
 }
 
-void DevToolsEyeDropper::OnTargetLost(const viz::FrameSinkId& frame_sink_id) {}
-
 void DevToolsEyeDropper::OnStopped() {}
diff --git a/chrome/browser/devtools/devtools_eye_dropper.h b/chrome/browser/devtools/devtools_eye_dropper.h
index c120c98..0dde971 100644
--- a/chrome/browser/devtools/devtools_eye_dropper.h
+++ b/chrome/browser/devtools/devtools_eye_dropper.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_DEVTOOLS_DEVTOOLS_EYE_DROPPER_H_
 #define CHROME_BROWSER_DEVTOOLS_DEVTOOLS_EYE_DROPPER_H_
 
+#include <memory>
+
 #include "base/callback.h"
 #include "base/macros.h"
 #include "components/viz/host/client_frame_sink_video_capturer.h"
@@ -52,7 +54,6 @@
       const gfx::Rect& update_rect,
       const gfx::Rect& content_rect,
       viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) override;
-  void OnTargetLost(const viz::FrameSinkId& frame_sink_id) override;
   void OnStopped() override;
 
   // This object keeps the shared memory that backs |frame_| mapped.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index bcc762c..2fa6e51 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -410,6 +410,12 @@
 const char kEnableCursorMotionBlurDescription[] =
     "Enable motion blur effect for the cursor.";
 
+const char kEnableEphemeralFlashPermissionName[] =
+    "Enable Ephemeral Flash Permissions";
+const char kEnableEphemeralFlashPermissionDescription[] =
+    "When enabled, Flash plugin permissions are reset at the end of the "
+    "browser session.";
+
 const char kEnableNoScriptPreviewsName[] = "NoScript previews";
 
 const char kEnableNoScriptPreviewsDescription[] =
@@ -1945,6 +1951,13 @@
     "When enabled, Stun messages generated by WebRTC will contain the Origin "
     "header.";
 
+const char kWebSocketHandshakeReuseConnectionName[] =
+    "Enable WebSocket connection reuse for authentication";
+const char kWebSocketHandshakeReuseConnectionDescription[] =
+    "Permits the WebSocket handshake to keep the connection open after an "
+    "authentication failure. The connection may be used for further requests "
+    "to send credentials. This is sometimes needed for Windows authentication.";
+
 const char kWebvrName[] = "WebVR";
 const char kWebvrDescription[] =
     "Enables access to experimental Virtual Reality functionality via the "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 0218c0f5..74ad0f2 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -281,6 +281,9 @@
 extern const char kEnableCursorMotionBlurName[];
 extern const char kEnableCursorMotionBlurDescription[];
 
+extern const char kEnableEphemeralFlashPermissionName[];
+extern const char kEnableEphemeralFlashPermissionDescription[];
+
 extern const char kEnableNoScriptPreviewsName[];
 extern const char kEnableNoScriptPreviewsDescription[];
 
@@ -1183,6 +1186,9 @@
 extern const char kWebrtcH264WithOpenh264FfmpegName[];
 extern const char kWebrtcH264WithOpenh264FfmpegDescription[];
 
+extern const char kWebSocketHandshakeReuseConnectionName[];
+extern const char kWebSocketHandshakeReuseConnectionDescription[];
+
 extern const char kWebvrName[];
 extern const char kWebvrDescription[];
 
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
index ed0ec9b3..e444f16 100644
--- a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
@@ -36,6 +36,7 @@
 #endif  // defined(OS_CHROMEOS)
 
 using content::WebContents;
+using content::WebContentsTester;
 
 namespace {
 
@@ -120,7 +121,8 @@
             profile_, content::SiteInstance::Create(profile_)));
     ASSERT_TRUE(contents);
 
-    contents->SetLastActiveTime(base::TimeTicks::Now());
+    WebContentsTester::For(contents.get())
+        ->SetLastActiveTime(base::TimeTicks::Now());
 
     // Get or create the transient NavigationEntry and add a title and a
     // favicon to it.
@@ -314,8 +316,8 @@
   ASSERT_TRUE(contents1);
   base::TimeTicks t1 = contents1->GetLastActiveTime();
 
-  contents0->SetLastActiveTime(t1);
-  contents1->SetLastActiveTime(t0);
+  WebContentsTester::For(contents0)->SetLastActiveTime(t1);
+  WebContentsTester::For(contents1)->SetLastActiveTime(t0);
 
   EXPECT_CALL(observer_, OnSourceMoved(list_.get(), 1, 0))
       .WillOnce(testing::DoAll(CheckListSize(list_.get(), kDefaultSourceCount),
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index cfe6b02..e79ba12 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -70,6 +70,7 @@
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
 #include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/secure_origin_whitelist.h"
@@ -509,6 +510,7 @@
   autofill::AutofillManager::RegisterProfilePrefs(registry);
   browsing_data::prefs::RegisterBrowserUserPrefs(registry);
   certificate_transparency::prefs::RegisterPrefs(registry);
+  ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(registry);
   ChromeContentBrowserClient::RegisterProfilePrefs(registry);
   ChromeSSLHostStateDelegate::RegisterProfilePrefs(registry);
   ChromeVersionService::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/profiling_host/DEPS b/chrome/browser/profiling_host/DEPS
deleted file mode 100644
index 61ef5fec..0000000
--- a/chrome/browser/profiling_host/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+mojo/edk/embedder",
-]
diff --git a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
index f3efb83..f56bd6cf 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/web_contents_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace resource_coordinator {
@@ -99,12 +100,12 @@
     contents2_ = CreateTestWebContents();
     contents3_ = CreateTestWebContents();
 
-    contents1_->SetLastActiveTime(clock_.NowTicks() -
-                                  base::TimeDelta::FromHours(1));
-    contents2_->SetLastActiveTime(clock_.NowTicks() -
-                                  base::TimeDelta::FromHours(2));
-    contents3_->SetLastActiveTime(clock_.NowTicks() -
-                                  base::TimeDelta::FromHours(3));
+    content::WebContentsTester::For(contents1_.get())
+        ->SetLastActiveTime(clock_.NowTicks() - base::TimeDelta::FromHours(1));
+    content::WebContentsTester::For(contents2_.get())
+        ->SetLastActiveTime(clock_.NowTicks() - base::TimeDelta::FromHours(2));
+    content::WebContentsTester::For(contents3_.get())
+        ->SetLastActiveTime(clock_.NowTicks() - base::TimeDelta::FromHours(3));
   }
 
   void TearDown() override {
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index 50abada..03b80d8 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -581,6 +581,7 @@
       old_contents->GetVisibility() == content::Visibility::HIDDEN;
   create_params.desired_renderer_state =
       content::WebContents::CreateParams::kNoRendererProcess;
+  create_params.last_active_time = old_contents->GetLastActiveTime();
   std::unique_ptr<content::WebContents> null_contents =
       content::WebContents::Create(create_params);
   content::WebContents* raw_null_contents = null_contents.get();
@@ -601,9 +602,6 @@
   null_contents->GetController().CopyStateFrom(old_contents->GetController(),
                                                /* needs_reload */ false);
 
-  // Persist the last active time property.
-  null_contents->SetLastActiveTime(old_contents->GetLastActiveTime());
-
   // First try to fast-kill the process, if it's just running a single tab.
   bool fast_shutdown_success =
       GetRenderProcessHost()->FastShutdownIfPossible(1u, false);
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc
index 8d76d3c..396de003 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc
@@ -301,7 +301,8 @@
                   &foreground_lifecycle_unit);
     content::WebContents* initial_web_contents =
         tab_strip_model_->GetWebContentsAt(0);
-    initial_web_contents->SetLastActiveTime(kDummyLastActiveTime);
+    content::WebContentsTester::For(initial_web_contents)
+        ->SetLastActiveTime(kDummyLastActiveTime);
 
     // Discard the tab.
     EXPECT_EQ(LifecycleUnitState::ACTIVE,
diff --git a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json
index a18e51cd..61de0db0 100644
--- a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json
+++ b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json
@@ -161,36 +161,6 @@
       "options_page": "hmm_options.html?code=xkb:us:intl_pc:nld"
     },
     {
-      "name": "__MSG_keyboard_us_international__",
-      "type": "ime",
-      "id": "xkb:us:intl:por",
-      "indicator": "INTL",
-      "description": "",
-      "language": [
-        "pt-BR"
-      ],
-      "layouts": [
-        "us(intl)"
-      ],
-      "input_view": "inputview.html#id=us-intl&language=pt-BR&passwordLayout=us-intl&name=keyboard_us_international",
-      "options_page": "hmm_options.html?code=xkb:us:intl:por"
-    },
-    {
-      "name": "__MSG_keyboard_us_international_pc__",
-      "type": "ime",
-      "id": "xkb:us:intl_pc:por",
-      "indicator": "INTL",
-      "description": "",
-      "language": [
-        "pt-BR"
-      ],
-      "layouts": [
-        "us(intl_pc)"
-      ],
-      "input_view": "inputview.html#id=us-intl&language=pt-BR&passwordLayout=us-intl&name=keyboard_us_international_pc",
-      "options_page": "hmm_options.html?code=xkb:us:intl_pc:por"
-    },
-    {
       "name": "__MSG_keyboard_us_extended__",
       "type": "ime",
       "id": "xkb:us:altgr-intl:eng",
@@ -526,6 +496,36 @@
       "options_page": "hmm_options.html?code=xkb:br::por"
     },
     {
+      "name": "__MSG_keyboard_us_international__",
+      "type": "ime",
+      "id": "xkb:us:intl:por",
+      "indicator": "INTL",
+      "description": "",
+      "language": [
+        "pt-BR"
+      ],
+      "layouts": [
+        "us(intl)"
+      ],
+      "input_view": "inputview.html#id=us-intl&language=pt-BR&passwordLayout=us-intl&name=keyboard_us_international",
+      "options_page": "hmm_options.html?code=xkb:us:intl:por"
+    },
+    {
+      "name": "__MSG_keyboard_us_international_pc__",
+      "type": "ime",
+      "id": "xkb:us:intl_pc:por",
+      "indicator": "INTL",
+      "description": "",
+      "language": [
+        "pt-BR"
+      ],
+      "layouts": [
+        "us(intl_pc)"
+      ],
+      "input_view": "inputview.html#id=us-intl&language=pt-BR&passwordLayout=us-intl&name=keyboard_us_international_pc",
+      "options_page": "hmm_options.html?code=xkb:us:intl_pc:por"
+    },
+    {
       "name": "__MSG_keyboard_bulgarian__",
       "type": "ime",
       "id": "xkb:bg::bul",
diff --git a/chrome/browser/resources/chromeos/input_method/xkb_manifest.json b/chrome/browser/resources/chromeos/input_method/xkb_manifest.json
index 4a24e1d..7f3285f7 100644
--- a/chrome/browser/resources/chromeos/input_method/xkb_manifest.json
+++ b/chrome/browser/resources/chromeos/input_method/xkb_manifest.json
@@ -102,20 +102,6 @@
       "input_view": "inputview.html?id=nl.compact.qwerty&language=nl&passwordLayout=nl.compact.qwerty&name=keyboard_netherlands"
     },
     {
-      "name": "__MSG_keyboard_us_international__",
-      "type": "ime",
-      "id": "xkb:us:intl:por",
-      "indicator": "INTL",
-      "description": "",
-      "language": [
-        "pt-BR"
-      ],
-      "layouts": [
-        "us(intl)"
-      ],
-      "input_view": "inputview.html?id=us-intl&language=pt-BR&passwordLayout=us-intl&name=keyboard_us_international"
-    },
-    {
       "name": "__MSG_keyboard_us_extended__",
       "type": "ime",
       "id": "xkb:us:altgr-intl:eng",
@@ -398,6 +384,20 @@
       "input_view": "inputview.html?id=br&language=pt-BR&passwordLayout=br&name=keyboard_brazilian"
     },
     {
+      "name": "__MSG_keyboard_us_international__",
+      "type": "ime",
+      "id": "xkb:us:intl:por",
+      "indicator": "INTL",
+      "description": "",
+      "language": [
+        "pt-BR"
+      ],
+      "layouts": [
+        "us(intl)"
+      ],
+      "input_view": "inputview.html?id=us-intl&language=pt-BR&passwordLayout=us-intl&name=keyboard_us_international"
+    },
+    {
       "name": "__MSG_keyboard_bulgarian__",
       "type": "ime",
       "id": "xkb:bg::bul",
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css b/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css
index 3cc16609..d67c5f6 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/css/wallpaper_manager.css
@@ -8,7 +8,6 @@
 
 body {
   -webkit-app-region: drag;
-  background-color: rgba(20, 20, 20, 0.93);
   color: #999;
   font-size: 80%;
   height: 100%;
@@ -16,6 +15,10 @@
   padding: 0;
 }
 
+body.v1 {
+  background-color: rgba(20, 20, 20, 0.93);
+}
+
 /* Click events are not received in draggable area. Making all clickable areas
  * not draggable to receive click events.
  * TODO(bshe): Remove this when http://crbug.com/142275 fixed. */
@@ -380,7 +383,7 @@
 #dialog-header,
 #no-images-message,
 #current-wallpaper-info-bar,
-#set-successfully-message {
+#message-container {
   display: none;
 }
 
@@ -430,6 +433,7 @@
 .v2 #categories-list {
   display: block;
   height: 100%;
+  pointer-events: none;
 }
 
 .v2 #categories-list > li {
@@ -437,6 +441,7 @@
   height: 32px;
   margin-bottom: 8px;
   margin-top: 8px;
+  pointer-events: auto;
 }
 
 .v2 #categories-list > li > div {
@@ -518,6 +523,15 @@
   width: 100%;
 }
 
+.v2 .image-picker .selected-grid-border > div {
+  border: solid 16px rgba(26, 115, 232, 0.08);
+  height: 100%;
+  left: -16px;
+  position: absolute;
+  top: -16px;
+  width: 100%;
+}
+
 .v2 #window-close-button {
   display: none;
 }
@@ -547,7 +561,7 @@
 .v2 #top-header {
   -webkit-app-region: no-drag;
   background-color: #fff;
-  border-radius: 0 0 48px 48px;
+  border-radius: 0 0 24px 24px;
   display: flex;
   height: 48px;
   position: absolute;
@@ -576,7 +590,7 @@
 }
 
 .v2 .top-header-contents #cancel-preview-wallpaper {
-  -webkit-margin-start: 32px;
+  -webkit-margin-start: 16px;
   -webkit-padding-start: 32px;
   background-image: url(../images/ui/left_arrow.svg);
   background-repeat: no-repeat;
@@ -586,10 +600,8 @@
 
 .v2 .top-header-contents #image-title {
   -webkit-padding-end: 8px;
-  -webkit-padding-start: 8px;
   color: rgb(32, 33, 36);
-  max-width: 360px;
-  overflow: hidden;
+  white-space: nowrap;
 }
 
 .v2 .top-header-contents .divider {
@@ -598,30 +610,47 @@
   margin-top: 8px;
 }
 
-.v2 .top-header-contents #collection-name {
+.v2 .top-header-contents #wallpaper-description {
   -webkit-padding-start: 8px;
   color: rgb(128, 134, 139);
+  max-width: 312px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 
-.v2.custom-wallpaper .top-header-contents #collection-name {
+.v2.custom-wallpaper .top-header-contents #wallpaper-description {
   color: rgb(32, 33, 36);
 }
 
+.v2.daily-wallpaper .top-header-contents #wallpaper-description {
+  max-width: 226px;
+}
+
 .v2 .top-header-contents .more-options {
   display: flex;
   position: absolute;
-  /* TODO(wzang): Change this to be RTL-friendly. */
-  right: 32px;
+  right: 8px;
+}
+
+html[dir='rtl'] .v2 .top-header-contents .more-options {
+  -webkit-padding-start: 96px;
+  position: unset;
 }
 
 .v2 .top-header-contents .more-options > div {
-  -webkit-padding-end: 16px;
-  -webkit-padding-start: 16px;
+  background-color: #fff;
+  border: 0.5px solid;
+  border-color: rgba(128, 134, 139, 0.6);
+  border-radius: 16px;
   color: rgb(66, 133, 244);
   display: none;
+  margin-top: -8px;
+  padding: 8px 24px;
 }
 
 .v2 .top-header-contents .more-options > div.disabled {
+  background-color: #fff;
   color: rgb(128, 134, 139);
   pointer-events: none;
 }
@@ -632,12 +661,27 @@
   width: 16px;
 }
 
+.v2 .top-header-contents .more-options .center-button,
+.v2 .top-header-contents .more-options .center-cropped-button {
+  background-color: rgb(232,240,254);
+}
+
+.v2 .top-header-contents .more-options .center-button {
+  -webkit-padding-end: 48px;
+  -webkit-padding-start: 32px;
+}
+
+.v2 .top-header-contents .more-options .center-cropped-button {
+  -webkit-margin-start: -24px;
+}
+
 .v2 .top-header-contents .center-button .icon,
 .v2 #current-wallpaper-more-options #center .icon {
   background-image: url(../images/ui/center_layout.svg);
 }
 
-.v2 .top-header-contents .center-button.disabled .icon {
+.v2 .top-header-contents .center-button.disabled .icon,
+.v2 #current-wallpaper-more-options #center.disabled .icon {
   background-image: url(../images/ui/center_layout_disabled.svg);
 }
 
@@ -646,16 +690,31 @@
   background-image: url(../images/ui/center_cropped_layout.svg);
 }
 
-.v2 .top-header-contents .center-cropped-button.disabled .icon {
+.v2 .top-header-contents .center-cropped-button.disabled .icon,
+.v2 #current-wallpaper-more-options #center-cropped.disabled .icon {
   background-image: url(../images/ui/center_cropped_layout_disabled.svg);
 }
 
+.v2 #current-wallpaper-more-options .disabled {
+  color: rgb(128, 134, 139);
+  pointer-events: none;
+}
+
 .v2 .top-header-contents #confirm-preview-wallpaper {
-  -webkit-padding-start: 96px;
+  -webkit-margin-start: 96px;
+}
+
+.v2.daily-wallpaper .top-header-contents #confirm-preview-wallpaper {
+  -webkit-margin-start: 8px;
+}
+
+.v2 .top-header-contents #refresh-wallpaper {
+  -webkit-margin-start: 16px;
 }
 
 .v2.preview-mode.custom-wallpaper .more-options .custom-option,
-.v2.preview-mode:not(.custom-wallpaper) .more-options :not(.custom-option) {
+.v2.preview-mode.daily-wallpaper .more-options .daily-option,
+.v2.preview-mode:not(.custom-wallpaper):not(.daily-option) .more-options :not(.custom-option):not(.daily-option) {
   display: flex;
 }
 
@@ -715,6 +774,10 @@
   width: 30px;
 }
 
+.v2 .image-picker-offline .daily-refresh-slider {
+  pointer-events: none;
+}
+
 .v2 .daily-refresh-slider::before {
   background-color: #fff;
   border-radius: 50%;
@@ -804,14 +867,17 @@
   flex-direction: column;
   font-size: 12px;
   position: absolute;
-  /* TODO(wzang): Change this to be RTL-friendly. */
   right: 0;
 }
 
+html[dir='rtl'] .v2 #current-wallpaper-more-options {
+  right: 420px;
+}
+
 .v2 #current-wallpaper-more-options > div {
   border: 0.5px solid;
   border-color: rgba(128, 134, 139, 0.6);
-  border-radius: 32px;
+  border-radius: 16px;
   display: flex;
   padding: 8px 4px;
 }
@@ -842,19 +908,16 @@
   background-image: url(../images/ui/current_wallpaper_explore.svg);
 }
 
-.v2 #set-successfully-message {
-  background-color: #000;
-  border-radius: 18px;
+.v2 #message-container {
+  background-color: rgba(0, 0, 0, 0.5);
+  border-radius: 16px;
   bottom: 12px;
   color: #fff;
   display: block;
   padding: 8px 28px;
   position: absolute;
   visibility: hidden;  /* Need this for correct positioning. */
-}
-
-.v2.wallpaper-set-successfully #set-successfully-message {
-  visibility: visible;
+  z-index: 4;
 }
 
 .v2 .progress-bar {
@@ -862,6 +925,18 @@
   top: unset;
 }
 
+.v2 .image-picker-offline .progress-bar {
+  display: none;
+}
+
+.v2 #spinner {
+  background: url(chrome://resources/images/throbber_medium.svg) center/32px
+      no-repeat;
+  height: 32px;
+  position: absolute;
+  width: 32px;
+}
+
 @keyframes fade-in {
   from { filter: blur(15px);
          opacity: 0;
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/constants.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/constants.js
index e804739..0493687 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/js/constants.js
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/constants.js
@@ -25,7 +25,8 @@
   AccessSyncWallpaperInfoKey: 'wallpaper-sync-info-key',
 
   /**
-   * Key to access last changed date of a surprise wallpaper in
+   * Key to access last changed date of a surprise me wallpaper (on the old
+   * picker) or a daily refresh wallpaper (on the new picker) in
    * chrome.storage.local or chrome.storage.sync.
    */
   AccessLastSurpriseWallpaperChangedDate: 'wallpaper-last-changed-date-key',
@@ -43,6 +44,18 @@
   AccessSyncSurpriseMeEnabledKey: 'sync-surprise-me-enabled-key',
 
   /**
+   * Key to access the info related to daily refresh feature (on the new
+   * wallpaper picker) in chrome.storage.local.
+   */
+  AccessLocalDailyRefreshInfoKey: 'daily-refresh-info-key',
+
+  /**
+   * Key to access the info related to daily refresh feature (on the new
+   * wallpaper picker) in chrome.storage.sync.
+   */
+  AccessSyncDailyRefreshInfoKey: 'sync-daily-refresh-info-key',
+
+  /**
    * URL to get latest wallpaper RSS feed.
    */
   WallpaperRssURL: 'https://storage.googleapis.com/' +
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/event_page.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/event_page.js
index 305c93be..476409f 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/js/event_page.js
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/event_page.js
@@ -207,45 +207,62 @@
  */
 SurpriseWallpaper.prototype.setRandomWallpaperFromServer_ = function(
     onSuccess, suffix) {
-  // The first step is to get the list of wallpaper collections (ie. categories)
-  // and randomly select one.
-  chrome.wallpaperPrivate.getCollectionsInfo(collectionsInfo => {
-    if (chrome.runtime.lastError) {
-      this.retryLater_();
-      return;
-    }
-    if (collectionsInfo.length == 0) {
-      // Although the fetch succeeds, it's theoretically possible that the
-      // collection list is empty, in this case do nothing.
+  var onDailyRefreshInfoReturned = dailyRefreshInfo => {
+    var setRandomWallpaperFromServerImpl = dailyRefreshInfo => {
+      chrome.wallpaperPrivate.getSurpriseMeImage(
+          dailyRefreshInfo.collectionId, dailyRefreshInfo.resumeToken,
+          (imageInfo, nextResumeToken) => {
+            if (chrome.runtime.lastError) {
+              this.retryLater_();
+              return;
+            }
+            dailyRefreshInfo.resumeToken = nextResumeToken;
+            WallpaperUtil.saveDailyRefreshInfo(dailyRefreshInfo);
+
+            var wallpaperUrl = imageInfo['imageUrl'] + suffix;
+            var layout = Constants.WallpaperThumbnailDefaultLayout;
+            WallpaperUtil.setOnlineWallpaperWithoutPreview(
+                wallpaperUrl, layout,
+                onSuccess.bind(null, wallpaperUrl, layout),
+                this.retryLater_.bind(this));
+          });
+    };
+
+    if (dailyRefreshInfo) {
+      if (dailyRefreshInfo.enabled) {
+        setRandomWallpaperFromServerImpl(dailyRefreshInfo);
+      } else {
+        console.error(
+            'Daily refresh is disabled when the alarm goes off. ' +
+            'This should never happen!');
+      }
       return;
     }
 
-    var randomCollectionIndex =
-        Math.floor(Math.random() * collectionsInfo.length);
-    var collectionId = collectionsInfo[randomCollectionIndex]['collectionId'];
-    // The second step is to get the list of wallpapers that belong to the
-    // particular collection, and randomly select one.
-    chrome.wallpaperPrivate.getImagesInfo(collectionId, imagesInfo => {
+    // Migration: we reach here if the old picker set an alarm and by the time
+    // the alarm goes off, the new picker is already in use. We should ensure
+    // the user transitions to the daily refresh feature.
+    chrome.wallpaperPrivate.getCollectionsInfo(collectionsInfo => {
       if (chrome.runtime.lastError) {
         this.retryLater_();
         return;
       }
-      if (imagesInfo.length == 0) {
+      if (collectionsInfo.length == 0) {
         // Although the fetch succeeds, it's theoretically possible that the
-        // image list is empty, in this case do nothing.
-        // TODO(crbug.com/800945): Consider fetching another collection.
+        // collection list is empty, in this case do nothing.
         return;
       }
-      var randomImageIndex = Math.floor(Math.random() * imagesInfo.length);
-      var wallpaperUrl = imagesInfo[randomImageIndex]['imageUrl'] + suffix;
-      // The backend service doesn't specify the desired layout. Use the default
-      // layout here.
-      var layout = Constants.WallpaperThumbnailDefaultLayout;
-      WallpaperUtil.setOnlineWallpaperWithoutPreview(
-          wallpaperUrl, layout, onSuccess.bind(null, wallpaperUrl, layout),
-          this.retryLater_.bind(this));
+      dailyRefreshInfo = {
+        enabled: true,
+        // Use the first collection (an arbitrary choice).
+        collectionId: collectionsInfo[0]['collectionId'],
+        resumeToken: null
+      };
+      setRandomWallpaperFromServerImpl(dailyRefreshInfo);
     });
-  });
+  };
+
+  WallpaperUtil.getDailyRefreshInfo(onDailyRefreshInfoReturned.bind(null));
 };
 
 /**
@@ -344,6 +361,8 @@
       w.onClosed.addListener(function() {
         wallpaperPickerWindow = null;
         chrome.wallpaperPrivate.restoreMinimizedWindows();
+        // In case the app exits unexpectedly during preview.
+        chrome.wallpaperPrivate.cancelPreviewWallpaper(() => {});
       });
       if (result) {
         // By design, the new wallpaper picker should never be shown on top of
@@ -399,6 +418,30 @@
 
 chrome.storage.onChanged.addListener(function(changes, namespace) {
   WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
+    // Daily refresh feature is on the new wallpaper picker only.
+    var updateDailyRefreshStates = key => {
+      if (!changes[key])
+        return;
+      var oldDailyRefreshInfo = JSON.parse(changes[key].oldValue);
+      var newDailyRefreshInfo = JSON.parse(changes[key].newValue);
+      // The resume token is expected to change after a new daily refresh
+      // wallpaper is set. Ignore it if it's the only change.
+      if (oldDailyRefreshInfo.enabled === newDailyRefreshInfo.enabled &&
+          oldDailyRefreshInfo.collectionId ===
+              newDailyRefreshInfo.collectionId) {
+        return;
+      }
+      // Although the old and new values may both have enabled == true, they can
+      // have different collection ids, so the old alarm should always be
+      // cleared.
+      chrome.alarms.clearAll();
+      if (newDailyRefreshInfo.enabled)
+        SurpriseWallpaper.getInstance().next();
+    };
+    updateDailyRefreshStates(
+        syncEnabled ? Constants.AccessSyncDailyRefreshInfoKey :
+                      Constants.AccessLocalDailyRefreshInfoKey);
+
     if (syncEnabled) {
       // If sync theme is enabled, use values from chrome.storage.sync to sync
       // wallpaper changes.
@@ -460,12 +503,14 @@
                     wpDocument.querySelector('.check').style.visibility =
                         'visible';
                 }
-                wpDocument.querySelector('#categories-list').disabled = enable;
                 chrome.commandLinePrivate.hasSwitch(
                     'new-wallpaper-picker', useNewWallpaperPicker => {
-                      if (!useNewWallpaperPicker)
+                      if (!useNewWallpaperPicker) {
                         wpDocument.querySelector('#wallpaper-grid').disabled =
                             enable;
+                        wpDocument.querySelector('#categories-list').disabled =
+                            enable;
+                      }
                     });
               });
         }
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/util.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/util.js
index 892cad3..6d8f001 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/js/util.js
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/util.js
@@ -500,3 +500,71 @@
   if (test)
     test.sendMessage(message);
 };
+
+/**
+ * Gets the daily refresh info from sync storage, or local storage if the former
+ * is not available.
+ * @param {function} callback A callback that takes the value of the info, or
+ *     null if the value is invalid.
+ */
+WallpaperUtil.getDailyRefreshInfo = function(callback) {
+  WallpaperUtil.enabledSyncThemesCallback(syncEnabled => {
+    var parseInfo = dailyRefreshInfoJson => {
+      if (!dailyRefreshInfoJson) {
+        callback(null);
+        return;
+      }
+
+      var dailyRefreshInfo = JSON.parse(dailyRefreshInfoJson);
+      if (!dailyRefreshInfo.hasOwnProperty('enabled') ||
+          !dailyRefreshInfo.hasOwnProperty('collectionId') ||
+          !dailyRefreshInfo.hasOwnProperty('resumeToken')) {
+        callback(null);
+        return;
+      }
+      callback(dailyRefreshInfo);
+    };
+
+    if (syncEnabled) {
+      Constants.WallpaperSyncStorage.get(
+          Constants.AccessSyncDailyRefreshInfoKey, items => {
+            var dailyRefreshInfoJson =
+                items[Constants.AccessSyncDailyRefreshInfoKey];
+            if (dailyRefreshInfoJson) {
+              parseInfo(dailyRefreshInfoJson);
+            } else {
+              Constants.WallpaperLocalStorage.get(
+                  Constants.AccessLocalDailyRefreshInfoKey, items => {
+                    dailyRefreshInfoJson =
+                        items[Constants.AccessLocalDailyRefreshInfoKey];
+                    parseInfo(dailyRefreshInfoJson);
+                    if (dailyRefreshInfoJson) {
+                      WallpaperUtil.saveToSyncStorage(
+                          Constants.AccessSyncDailyRefreshInfoKey,
+                          dailyRefreshInfoJson);
+                    }
+                  });
+            }
+          });
+    } else {
+      Constants.WallpaperLocalStorage.get(
+          Constants.AccessLocalDailyRefreshInfoKey, items => {
+            parseInfo(items[Constants.AccessLocalDailyRefreshInfoKey]);
+          });
+    }
+  });
+};
+
+/**
+ * Saves the daily refresh info to local and sync storage.
+ * @param {Object} dailyRefreshInfo The daily refresh info.
+ */
+WallpaperUtil.saveDailyRefreshInfo = function(dailyRefreshInfo) {
+  var dailyRefreshInfoJson = JSON.stringify(dailyRefreshInfo);
+  WallpaperUtil.saveToLocalStorage(
+      Constants.AccessLocalDailyRefreshInfoKey, dailyRefreshInfoJson,
+      null /*opt_callback=*/);
+  WallpaperUtil.saveToSyncStorage(
+      Constants.AccessSyncDailyRefreshInfoKey, dailyRefreshInfoJson,
+      null /*opt_callback=*/);
+};
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_images_grid.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_images_grid.js
index eb5f70b..06d0a9d 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_images_grid.js
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_images_grid.js
@@ -86,6 +86,10 @@
       }
 
       var imageEl = cr.doc.createElement('img');
+      // On the new picker, do not show the image until |cropImageToFitGrid_| is
+      // done.
+      if (loadTimeData.getBoolean('useNewWallpaperPicker'))
+        imageEl.hidden = true;
       imageEl.classList.add('thumbnail');
       cr.defineProperty(imageEl, 'offline', cr.PropertyKind.BOOL_ATTR);
       imageEl.offline = this.dataItem.availableOffline;
@@ -384,6 +388,15 @@
     },
 
     /**
+     * The id of the collection that the wallpapers belong to, assuming all the
+     * wallpapers have the same id (enfored by the source of the data model).
+     * @type {string}
+     */
+    get collectionId() {
+      return this.dataModel.item(this.dataModel.length - 1).collectionId;
+    },
+
+    /**
      * A unique ID that assigned to each set dataModel operation. Note that this
      * id wont increase if the new dataModel is null or empty.
      */
@@ -480,6 +493,7 @@
 
       image.style.height = newHeight + 'px';
       image.style.width = newWidth + 'px';
+      image.hidden = false;
     },
 
     /**
@@ -550,6 +564,10 @@
           window.clearTimeout(this.dailyRefreshTimer_);
           this.showNextImage_(0);
         }
+        if (this.useNewWallpaperPicker_ &&
+            this.classList.contains('image-picker-offline')) {
+          this.highlightOfflineWallpapers();
+        }
       }
     },
 
@@ -653,6 +671,7 @@
       if (this.useNewWallpaperPicker_) {
         var selectedGridBorder = cr.doc.createElement('div');
         selectedGridBorder.classList.add('selected-grid-border');
+        selectedGridBorder.appendChild(cr.doc.createElement('div'));
         selectedGridItem.appendChild(selectedGridBorder);
       }
       selectedGridItem.appendChild(this.checkmark_);
@@ -687,11 +706,9 @@
       if (!this.dailyRefreshItem.querySelector('.daily-refresh-banner')) {
         var dailyRefreshBanner = document.querySelector('.daily-refresh-banner')
                                      .cloneNode(true /*deep=*/);
-        dailyRefreshBanner.querySelector('.daily-refresh-slider')
-            .addEventListener(
-                'click',
-                WallpaperManager.prototype.toggleSurpriseMe.bind(
-                    wallpaperManager));
+        wallpaperManager.decorateDailyRefreshSlider(
+            this.collectionId,
+            dailyRefreshBanner.querySelector('.daily-refresh-slider'));
         this.dailyRefreshItem.appendChild(dailyRefreshBanner);
       }
 
@@ -726,6 +743,37 @@
     },
 
     /**
+     * Highlights the wallpapers that are available offline by greying out all
+     * the other wallpapers.
+     */
+    highlightOfflineWallpapers: function() {
+      if (!this.useNewWallpaperPicker_ ||
+          !this.classList.contains('image-picker-offline')) {
+        return;
+      }
+
+      chrome.wallpaperPrivate.getOfflineWallpaperList(list => {
+        var offlineWallpaperList = {};
+        for (var url of list) {
+          offlineWallpaperList[url] = true;
+        }
+
+        for (var i = 0; i < this.dataModel.length; ++i) {
+          var url = this.dataModel.item(i).baseURL;
+          if (!url)
+            continue;
+          var fileName = url.substring(url.lastIndexOf('/') + 1) +
+              loadTimeData.getString('highResolutionSuffix');
+          if (this.getListItemByIndex(i) &&
+              offlineWallpaperList.hasOwnProperty(encodeURI(fileName))) {
+            this.getListItemByIndex(i).querySelector('.thumbnail').offline =
+                true;
+          }
+        }
+      });
+    },
+
+    /**
      * Redraws the viewport.
      */
     redraw: function() {
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
index 08b2aac5..e409aa3a 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
@@ -42,8 +42,7 @@
   // After the url and relevant info of the images are fetched, the two share
   // the same path, ie. pass the info to |WallpaperThumbnailsGridItem| for
   // actual image rendering.
-  this.document_.body.classList.toggle('v2', this.useNewWallpaperPicker_);
-  this.placeWallpaperPicker_();
+  this.document_.body.classList.add(this.useNewWallpaperPicker_ ? 'v2' : 'v1');
 
   if (this.useNewWallpaperPicker_) {
     // |collectionsInfo_| represents the list of wallpaper collections. Each
@@ -56,6 +55,16 @@
     this.imagesInfoMap_ = {};
     // The total count of images whose info has been fetched.
     this.imagesInfoCount_ = 0;
+    // |dailyRefreshInfo_| stores the info related to the daily refresh feature
+    // on the new picker. Its value should be consistent with the sync/local
+    // storage.
+    this.dailyRefreshInfo_ = null;
+    // |pendingDailyRefreshInfo_| stores the up-to-date daily refresh info that
+    // hasn't been confirmed by user (e.g. when user is previewing the image).
+    // Its value will either replace |dailyRefreshInfo_| or be discarded.
+    this.pendingDailyRefreshInfo_ = null;
+    this.placeWallpaperPicker_();
+    $('spinner').hidden = false;
     this.getCollectionsInfo_();
   } else {
     this.fetchManifest_();
@@ -118,15 +127,6 @@
 }
 
 /**
- * Retruns the current selected layout.
- * @return {string} The selected layout.
- */
-function getSelectedLayout() {
-  var setWallpaperLayout = $('set-wallpaper-layout');
-  return setWallpaperLayout.options[setWallpaperLayout.selectedIndex].value;
-}
-
-/**
  * Helper function to center the element.
  * @param {Object} element The element to be centered.
  * @param {number} totalWidth The total width. An empty value disables centering
@@ -254,12 +254,15 @@
               // Use the next available unique id.
               wallpaperId: this.imagesInfoCount_,
               baseURL: imagesInfo[i]['imageUrl'],
+              highResolutionURL:
+                  imagesInfo[i]['imageUrl'] + str('highResolutionSuffix'),
               layout: Constants.WallpaperThumbnailDefaultLayout,
               source: Constants.WallpaperSourceEnum.Online,
               availableOffline: false,
               displayText: imagesInfo[i]['displayText'],
               authorWebsite: imagesInfo[i]['actionUrl'],
-              collectionName: this.collectionsInfo_[index]['collectionName']
+              collectionName: this.collectionsInfo_[index]['collectionName'],
+              collectionId: collectionId
             };
             wallpapersDataModel.push(wallpaperInfo);
             ++this.imagesInfoCount_;
@@ -317,14 +320,14 @@
 
   // Wallpaper preview must always be in full screen. Exit preview if the
   // window is not in full screen for any reason (e.g. when device locks).
-  if (!chrome.app.window.current().isFullscreen() &&
-      this.document_.body.classList.contains('preview-mode')) {
+  if (!chrome.app.window.current().isFullscreen() && this.isDuringPreview_())
     $('cancel-preview-wallpaper').click();
-  }
 
   var totalWidth = this.document_.body.offsetWidth;
-  centerElement($('set-successfully-message'), totalWidth, null);
+  var totalHeight = this.document_.body.offsetHeight;
+  centerElement($('message-container'), totalWidth, null);
   centerElement($('top-header'), totalWidth, null);
+  centerElement($('spinner'), totalWidth, totalHeight);
 
   centerElement(
       $('no-images-message'), $('no-images-message').parentNode.offsetWidth,
@@ -341,7 +344,6 @@
   }
 
   // Position the entire image grid.
-  var totalHeight = this.document_.body.offsetHeight;
   var collectionTitleWidth =
       this.document_.querySelector('.dialog-topbar').offsetWidth;
   var totalPadding = collectionTitleWidth +
@@ -363,6 +365,13 @@
  * @param {string} errroMessage The string to show in the error dialog.
  */
 WallpaperManager.prototype.showError_ = function(errorMessage) {
+  if (this.useNewWallpaperPicker_) {
+    $('message-container').textContent = errorMessage;
+    centerElement(
+        $('message-container'), this.document_.body.offsetWidth, null);
+    $('message-container').style.visibility = 'visible';
+    return;
+  }
   document.querySelector('.error-message').textContent = errorMessage;
   $('error-container').hidden = false;
 };
@@ -470,6 +479,7 @@
   this.initCategoriesList_();
   this.initThumbnailsGrid_();
   this.presetCategory_();
+  $('spinner').hidden = true;
 
   $('file-selector')
       .addEventListener('change', this.onFileSelectorChanged_.bind(this));
@@ -499,7 +509,9 @@
     }
   });
 
-  if (this.enableOnlineWallpaper_) {
+  this.initializeDailyRefreshStates_();
+
+  if (this.enableOnlineWallpaper_ && !this.useNewWallpaperPicker_) {
     this.document_.body.setAttribute('surprise-me-disabled', '');
     $('surprise-me').hidden = false;
     $('surprise-me')
@@ -541,8 +553,16 @@
             });
       }
     });
+  }
 
+  if (this.enableOnlineWallpaper_) {
     window.addEventListener('offline', () => {
+      $('wallpaper-grid').classList.add('image-picker-offline');
+      if (this.useNewWallpaperPicker_) {
+        $('wallpaper-grid').highlightOfflineWallpapers();
+        return;
+      }
+
       chrome.wallpaperPrivate.getOfflineWallpaperList(lists => {
         if (!this.downloadedListMap_)
           this.downloadedListMap_ = {};
@@ -560,9 +580,13 @@
           }
         }
       });
-      $('wallpaper-grid').classList.add('image-picker-offline');
     });
     window.addEventListener('online', () => {
+      // Fetch the collection info (if not yet) when device gets online.
+      if (this.useNewWallpaperPicker_ && !this.collectionsInfo_)
+        this.getCollectionsInfo_();
+
+      $('message-container').style.visibility = 'hidden';
       this.downloadedListMap_ = null;
       $('wallpaper-grid').classList.remove('image-picker-offline');
     });
@@ -647,6 +671,7 @@
   // |currentWallpaper| is either a url containing |highResolutionSuffix| or a
   // custom wallpaper file name.
   this.currentWallpaper_ = str('currentWallpaper');
+  this.currentWallpaperLayout_ = str('currentWallpaperLayout');
   if (this.useNewWallpaperPicker_) {
     // The default category is the last one (the custom category).
     var categoryIndex = this.categoriesList_.dataModel.length - 1;
@@ -721,6 +746,130 @@
   // The info bar only exists in new wallpaper picker.
   if (!this.useNewWallpaperPicker_)
     return;
+
+  var decorateCurrentWallpaperInfoBarImpl =
+      (isOnlineWallpaper, isFromOldPicker) => {
+        // Initialize the "more options" buttons.
+        var isOnlineWallpaper = !!currentWallpaperInfo;
+        var visibleItemList = [];
+        $('refresh').hidden = !isOnlineWallpaper || !this.dailyRefreshInfo_ ||
+            !this.dailyRefreshInfo_.enabled;
+        if (!$('refresh').hidden) {
+          $('refresh').parentNode.replaceChild(
+              $('refresh').cloneNode(true), $('refresh'));
+          visibleItemList.push($('refresh'));
+          $('refresh').addEventListener('click', () => {
+            this.pendingDailyRefreshInfo_ = this.dailyRefreshInfo_;
+            this.setDailyRefreshWallpaper_();
+          });
+        }
+
+        $('explore').hidden = !isOnlineWallpaper;
+        if (!$('explore').hidden) {
+          visibleItemList.push($('explore'));
+          $('current-wallpaper-explore-link').href =
+              currentWallpaperInfo.authorWebsite;
+        }
+
+        $('center').hidden = isOnlineWallpaper;
+        if (!$('center').hidden) {
+          $('center').parentNode.replaceChild(
+              $('center').cloneNode(true), $('center'));
+          visibleItemList.push($('center'));
+          $('center').addEventListener(
+              'click', this.setCustomWallpaperLayout_.bind(this, 'CENTER'));
+        }
+
+        $('center-cropped').hidden = isOnlineWallpaper;
+        if (!$('center-cropped').hidden) {
+          $('center-cropped')
+              .parentNode.replaceChild(
+                  $('center-cropped').cloneNode(true), $('center-cropped'));
+          visibleItemList.push($('center-cropped'));
+          $('center-cropped')
+              .addEventListener(
+                  'click',
+                  this.setCustomWallpaperLayout_.bind(this, 'CENTER_CROPPED'));
+        }
+
+        if (visibleItemList.length == 1) {
+          visibleItemList[0].style.marginTop =
+              ($('current-wallpaper-info-bar').offsetHeight -
+               visibleItemList[0].offsetHeight) /
+                  2 +
+              'px';
+        } else {
+          // There are at most two visible elements.
+          var topMargin = ($('current-wallpaper-info-bar').offsetHeight -
+                           visibleItemList[0].offsetHeight -
+                           visibleItemList[1].offsetHeight) *
+              0.4;
+          visibleItemList[0].style.marginTop = topMargin + 'px';
+          visibleItemList[1].style.marginTop = topMargin / 2 + 'px';
+
+          // Make sure that all the texts are centered.
+          for (var item of visibleItemList) {
+            var totalPadding = $('current-wallpaper-more-options').offsetWidth -
+                (item.querySelector('.icon').offsetWidth +
+                 item.querySelector('.text').offsetWidth);
+            item.querySelector('.icon').style.WebkitMarginStart =
+                totalPadding / 2 + 'px';
+          }
+        }
+
+        $('current-wallpaper-more-options')
+            .classList.toggle('online-wallpaper', isOnlineWallpaper);
+        // Clear the existing contents (needed if the wallpaper changes while
+        // the picker is open).
+        $('current-wallpaper-title').innerHTML = '';
+        $('current-wallpaper-description').innerHTML = '';
+        if (isOnlineWallpaper) {
+          // Set the image title and description.
+          $('current-wallpaper-title').textContent =
+              currentWallpaperInfo.displayText[0];
+          $('current-wallpaper-description').innerHTML = '';
+          $('current-wallpaper-description')
+              .classList.toggle(
+                  'small-font', currentWallpaperInfo.displayText.length > 2);
+          for (var i = 1; i < currentWallpaperInfo.displayText.length; ++i) {
+            $('current-wallpaper-description')
+                .appendChild(document.createTextNode(
+                    currentWallpaperInfo.displayText[i]));
+            $('current-wallpaper-description')
+                .appendChild(document.createElement('br'));
+          }
+        }
+
+        var imageElement = $('current-wallpaper-image');
+        if (isOnlineWallpaper && !isFromOldPicker) {
+          WallpaperUtil.displayThumbnail(
+              imageElement, currentWallpaperInfo.baseURL,
+              Constants.WallpaperSourceEnum.Online);
+        } else {
+          // Request the thumbnail of the current wallpaper as fallback, since
+          // the picker doesn't have access to thumbnails of other types of
+          // wallpapers.
+          var currentWallpaper = this.currentWallpaper_;
+          chrome.wallpaperPrivate.getCurrentWallpaperThumbnail(
+              imageElement.offsetHeight, imageElement.offsetWidth,
+              thumbnail => {
+                // If the current wallpaper already changed when this function
+                // returns, do nothing.
+                if (currentWallpaper != this.currentWallpaper_)
+                  return;
+                WallpaperUtil.displayImage(
+                    imageElement, thumbnail, null /*opt_callback=*/);
+                // Show a placeholder as the image title.
+                $('current-wallpaper-title').textContent =
+                    str('customCategoryLabel');
+              });
+        }
+
+        this.toggleLayoutButtonStates_(this.currentWallpaperLayout_);
+        $('current-wallpaper-info-bar').classList.add('show-info-bar');
+      };
+
+  // Try finding the current wallpaper in the online wallpaper collection.
   var currentWallpaperInfo;
   Object.values(this.imagesInfoMap_).forEach(imagesInfo => {
     for (var i = 0; i < imagesInfo.length; ++i) {
@@ -729,101 +878,39 @@
     }
   });
 
-  // Initialize the "more options" buttons.
-  var isOnlineWallpaper = !!currentWallpaperInfo;
-  var surpriseMeEnabled =
-      !this.document_.body.hasAttribute('surprise-me-disabled');
-  var visibleItemList = [];
-  $('refresh').hidden = !surpriseMeEnabled;
-  if (!$('refresh').hidden) {
-    visibleItemList.push($('refresh'));
-    // TODO(wzang): Add event listener to this button.
-  }
-  $('explore').hidden = !isOnlineWallpaper;
-  if (!$('explore').hidden) {
-    visibleItemList.push($('explore'));
-    $('current-wallpaper-explore-link').href =
-        currentWallpaperInfo.authorWebsite;
-  }
-  $('center').hidden = isOnlineWallpaper || surpriseMeEnabled;
-  if (!$('center').hidden) {
-    visibleItemList.push($('center'));
-    $('center').addEventListener(
-        'click', this.setCustomWallpaperLayout_.bind(this, 'CENTER'));
-  }
-  $('center-cropped').hidden = isOnlineWallpaper || surpriseMeEnabled;
-  if (!$('center-cropped').hidden) {
-    visibleItemList.push($('center-cropped'));
-    $('center-cropped')
-        .addEventListener(
-            'click',
-            this.setCustomWallpaperLayout_.bind(this, 'CENTER_CROPPED'));
-  }
-
-  if (visibleItemList.length == 1) {
-    visibleItemList[0].style.marginTop =
-        ($('current-wallpaper-info-bar').offsetHeight -
-         visibleItemList[0].offsetHeight) /
-            2 +
-        'px';
+  if (currentWallpaperInfo) {
+    decorateCurrentWallpaperInfoBarImpl(
+        true /*isOnlineWallpaper=*/, false /*isFromOldPicker=*/);
   } else {
-    // There are at most two visible elements.
-    var topMargin =
-        ($('current-wallpaper-info-bar').offsetHeight -
-         visibleItemList[0].offsetHeight - visibleItemList[1].offsetHeight) *
-        0.4;
-    visibleItemList[0].style.marginTop = topMargin + 'px';
-    visibleItemList[1].style.marginTop = topMargin / 2 + 'px';
+    // Migration: it's possible that the wallpaper was selected from the online
+    // collection of the old picker. Try finding its info from local storage.
+    var accessManifestKey = Constants.AccessLocalManifestKey;
+    Constants.WallpaperLocalStorage.get(accessManifestKey, items => {
+      var manifest = items[accessManifestKey];
+      if (!manifest) {
+        decorateCurrentWallpaperInfoBarImpl(
+            false /*isOnlineWallpaper=*/, false /*isFromOldPicker=*/);
+        return;
+      }
 
-    // Make sure that all the texts are centered.
-    for (var item of visibleItemList) {
-      var totalPadding = $('current-wallpaper-more-options').offsetWidth -
-          (item.querySelector('.icon').offsetWidth +
-           item.querySelector('.text').offsetWidth);
-      item.querySelector('.icon').style.WebkitMarginStart =
-          totalPadding / 2 + 'px';
-    }
+      for (var i = 0; i < manifest.wallpaper_list.length; i++) {
+        if (this.currentWallpaper_.includes(
+                manifest.wallpaper_list[i].base_url)) {
+          currentWallpaperInfo = {
+            displayText: ['', manifest.wallpaper_list[i].author],
+            authorWebsite: manifest.wallpaper_list[i].author_website,
+          };
+          console.error(manifest.wallpaper_list[i].author);
+          decorateCurrentWallpaperInfoBarImpl(
+              false /*isOnlineWallpaper=*/, true /*isFromOldPicker=*/);
+          return;
+        }
+      }
+      // If the wallpaper is still not found, treat it as a custom wallpaper.
+      decorateCurrentWallpaperInfoBarImpl(
+          false /*isOnlineWallpaper=*/, false /*isFromOldPicker=*/);
+    });
   }
-
-  $('current-wallpaper-more-options')
-      .classList.toggle('online-wallpaper', isOnlineWallpaper);
-  var imageElement = $('current-wallpaper-image');
-  if (isOnlineWallpaper) {
-    WallpaperUtil.displayThumbnail(
-        imageElement, currentWallpaperInfo.baseURL,
-        Constants.WallpaperSourceEnum.Online);
-    // Set the image title and description.
-    $('current-wallpaper-title').textContent =
-        currentWallpaperInfo.displayText[0];
-    $('current-wallpaper-description').innerHTML = '';
-    $('current-wallpaper-description')
-        .classList.toggle(
-            'small-font', currentWallpaperInfo.displayText.length > 2);
-    for (var i = 1; i < currentWallpaperInfo.displayText.length; ++i) {
-      $('current-wallpaper-description')
-          .appendChild(
-              document.createTextNode(currentWallpaperInfo.displayText[i]));
-      $('current-wallpaper-description')
-          .appendChild(document.createElement('br'));
-    }
-  } else {
-    // Request the thumbnail of the current wallpaper as fallback, since the
-    // picker doesn't have access to thumbnails of other types of wallpapers.
-    var currentWallpaper = this.currentWallpaper_;
-    chrome.wallpaperPrivate.getCurrentWallpaperThumbnail(
-        imageElement.offsetHeight, imageElement.offsetWidth, thumbnail => {
-          // If the current wallpaper already changed when this function
-          // returns, do nothing.
-          if (currentWallpaper != this.currentWallpaper_)
-            return;
-          WallpaperUtil.displayImage(
-              imageElement, thumbnail, null /*opt_callback=*/);
-          // Show a placeholder as the image title.
-          $('current-wallpaper-title').textContent = str('customCategoryLabel');
-        });
-  }
-
-  $('current-wallpaper-info-bar').classList.add('show-info-bar');
 };
 
 /**
@@ -878,6 +965,7 @@
  */
 WallpaperManager.prototype.onWallpaperChanged_ = function(
     activeItem, currentWallpaperURL) {
+  $('message-container').style.visibility = 'hidden';
   this.wallpaperGrid_.activeItem = activeItem;
   this.currentWallpaper_ = currentWallpaperURL;
   this.decorateCurrentWallpaperInfoBar_();
@@ -907,7 +995,7 @@
           selectedItem, (imageData, optThumbnailData) => {
             this.onWallpaperChanged_(selectedItem, selectedItem.baseURL);
             this.saveCustomWallpaperToSyncFS_(
-                selectedItem.baseURL, getSelectedLayout(), imageData,
+                selectedItem.baseURL, this.getSelectedLayout_(), imageData,
                 optThumbnailData, this.onFileSystemError_.bind(this));
           });
       break;
@@ -917,7 +1005,22 @@
       this.onWallpaperChanged_(selectedItem, selectedItem.baseURL);
       break;
     case Constants.WallpaperSourceEnum.Online:
-      this.setSelectedOnlineWallpaper_(selectedItem);
+      var previewMode = this.shouldPreviewWallpaper_();
+      var successCallback = () => {
+        if (previewMode) {
+          this.onPreviewModeStarted_(
+              Constants.WallpaperSourceEnum.Online,
+              this.onWallpaperChanged_.bind(
+                  this, selectedItem, selectedItem.highResolutionURL),
+              /*optCancelCallback=*/null, /*optOnRefreshClicked=*/null);
+        } else {
+          this.onWallpaperChanged_(
+              selectedItem, selectedItem.highResolutionURL);
+        }
+      };
+      this.setSelectedOnlineWallpaper_(
+          selectedItem, successCallback, /*optFailureCallback=*/null,
+          previewMode);
       break;
     case Constants.WallpaperSourceEnum.Daily:
     case Constants.WallpaperSourceEnum.ThirdParty:
@@ -995,6 +1098,7 @@
                   if (chrome.runtime.lastError) {
                     this.showError_(str('accessFileFailure'));
                   } else {
+                    this.currentlySelectedLayout_ = layout;
                     this.document_.querySelector('.center-button')
                         .classList.toggle('disabled', layout == 'CENTER');
                     this.document_.querySelector('.center-cropped-button')
@@ -1002,8 +1106,9 @@
                             'disabled', layout == 'CENTER_CROPPED');
                     this.onPreviewModeStarted_(
                         Constants.WallpaperSourceEnum.Custom,
-                        successCallback.bind(
-                            null, imageData, optThumbnailData));
+                        successCallback.bind(null, imageData, optThumbnailData),
+                        /*optCancelCallback=*/null,
+                        /*optOnRefreshClicked=*/null);
                   }
                 });
           });
@@ -1053,16 +1158,15 @@
  * Implementation of |setSelectedWallpaper_| for online wallpapers.
  * @param {Object} selectedItem The selected item in WallpaperThumbnailsGrid's
  *     data model.
+ * @param {function} successCallback The callback after the wallpaper is set
+ *     successfully.
+ * @param {function} optFailureCallback The optional callback after setting the
+ *     wallpaper fails.
+ * @param {boolean} previewMode True if the wallpaper should be previewed.
+ * @private
  */
 WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function(
-    selectedItem) {
-  if (selectedItem.source != Constants.WallpaperSourceEnum.Online) {
-    console.error(
-        '|setSelectedOnlineWallpaper_| is called but the wallpaper source is ' +
-        'not online.');
-    return;
-  }
-
+    selectedItem, successCallback, optFailureCallback, previewMode) {
   // Cancel any ongoing wallpaper request, otherwise the wallpaper being set in
   // the end may not be the one that the user selected the last, because the
   // time needed to set each wallpaper may vary (e.g. some wallpapers already
@@ -1072,23 +1176,12 @@
     this.wallpaperRequest_ = null;
   }
 
-  var wallpaperUrl = selectedItem.baseURL + str('highResolutionSuffix');
+  var wallpaperUrl = selectedItem.highResolutionURL ?
+      selectedItem.highResolutionURL :
+      selectedItem.baseURL + str('highResolutionSuffix');
   var selectedGridItem = this.wallpaperGrid_.getListItem(selectedItem);
-  var previewMode = this.shouldPreviewWallpaper_();
-
   chrome.wallpaperPrivate.setWallpaperIfExists(
       wallpaperUrl, selectedItem.layout, previewMode, exists => {
-        var successCallback = () => {
-          if (previewMode) {
-            this.onPreviewModeStarted_(
-                Constants.WallpaperSourceEnum.Online,
-                this.onWallpaperChanged_.bind(
-                    this, selectedItem, wallpaperUrl));
-          } else {
-            this.onWallpaperChanged_(selectedItem, wallpaperUrl);
-          }
-        };
-
         if (exists) {
           successCallback();
           return;
@@ -1108,7 +1201,12 @@
                     if (chrome.runtime.lastError != undefined &&
                         chrome.runtime.lastError.message !=
                             str('canceledWallpaper')) {
-                      this.showError_(chrome.runtime.lastError.message);
+                      // The user doesn't need to distinguish this error (most
+                      // likely due to a decode failure) from a download
+                      // failure.
+                      this.showError_(str('downloadFailed'));
+                      if (optFailureCallback)
+                        optFailureCallback();
                     } else {
                       successCallback();
                     }
@@ -1119,6 +1217,8 @@
           this.progressManager_.hideProgressBar(selectedGridItem);
           this.showError_(str('downloadFailed'));
           this.wallpaperRequest_ = null;
+          if (optFailureCallback)
+            optFailureCallback();
         };
         WallpaperUtil.fetchURL(
             wallpaperUrl, 'arraybuffer', onSuccess, onFailure,
@@ -1130,38 +1230,56 @@
  * Handles the UI changes when the preview mode is started.
  * @param {string} source The source of the wallpaper corresponding to
  *     |WallpaperSourceEnum|.
- * @param {function} confirmPreviewWallpaperCallback The callback after preview
+ * @param {function} optConfirmCallback The callback after preview
  *     wallpaper is set.
+ * @param {function} optCancelCallback The callback after preview
+ *     is canceled.
+ * @param {function} optOnRefreshClicked The event listener for the refresh
+ *     button. Must be non-null when the wallpaper type is daily.
  * @private
  */
 WallpaperManager.prototype.onPreviewModeStarted_ = function(
-    source, confirmPreviewWallpaperCallback) {
-  if (this.document_.body.classList.contains('preview-mode'))
+    source, optConfirmCallback, optCancelCallback, optOnRefreshClicked) {
+  if (this.isDuringPreview_())
     return;
 
   this.document_.body.classList.add('preview-animation');
+  chrome.wallpaperPrivate.minimizeInactiveWindows();
   window.setTimeout(() => {
     chrome.app.window.current().fullscreen();
     this.document_.body.classList.add('preview-mode');
     this.document_.body.classList.toggle(
         'custom-wallpaper', source == Constants.WallpaperSourceEnum.Custom);
+    this.document_.body.classList.toggle(
+        'daily-wallpaper', source == Constants.WallpaperSourceEnum.Daily);
   }, 800);
 
   var onConfirmClicked = () => {
     chrome.wallpaperPrivate.confirmPreviewWallpaper(() => {
-      confirmPreviewWallpaperCallback();
+      if (optConfirmCallback)
+        optConfirmCallback();
       this.showSuccessMessageAndQuit_();
     });
   };
   $('confirm-preview-wallpaper').addEventListener('click', onConfirmClicked);
 
+  var onRefreshClicked = () => {
+    if (optOnRefreshClicked)
+      optOnRefreshClicked();
+  };
+  $('refresh-wallpaper').addEventListener('click', onRefreshClicked);
+
   var onCancelClicked = () => {
     $('confirm-preview-wallpaper')
         .removeEventListener('click', onConfirmClicked);
+    $('refresh-wallpaper').removeEventListener('click', onRefreshClicked);
     $('cancel-preview-wallpaper').removeEventListener('click', onCancelClicked);
     chrome.wallpaperPrivate.cancelPreviewWallpaper(() => {
+      if (optCancelCallback)
+        optCancelCallback();
       // Deselect the image.
       this.wallpaperGrid_.selectedItem = null;
+      this.currentlySelectedLayout_ = null;
       this.document_.body.classList.remove('preview-mode');
       this.document_.body.classList.remove('preview-animation');
       // Exit full screen, but the window should still be maximized.
@@ -1172,6 +1290,8 @@
     });
   };
   $('cancel-preview-wallpaper').addEventListener('click', onCancelClicked);
+
+  $('message-container').style.visibility = 'hidden';
 };
 
 /*
@@ -1200,8 +1320,11 @@
  */
 WallpaperManager.prototype.showSuccessMessageAndQuit_ = function() {
   this.document_.body.classList.add('wallpaper-set-successfully');
+  $('message-container').textContent = str('setSuccessfullyMessage');
   // Success message must be shown in full screen mode.
   chrome.app.window.current().fullscreen();
+  centerElement($('message-container'), this.document_.body.offsetWidth, null);
+  $('message-container').style.visibility = 'visible';
   // Close the window after showing the success message.
   window.setTimeout(() => {
     window.close();
@@ -1273,11 +1396,22 @@
  */
 WallpaperManager.prototype.setWallpaperAttribution = function(selectedItem) {
   if (this.useNewWallpaperPicker_) {
+    $('image-title').textContent = '';
+    $('wallpaper-description').textContent = '';
     if (selectedItem) {
-      $('collection-name').textContent = selectedItem.collectionName;
       // The first element in |displayText| is used as title.
       if (selectedItem.displayText)
         $('image-title').textContent = selectedItem.displayText[0];
+
+      if (selectedItem.displayText && selectedItem.displayText.length > 1) {
+        for (var i = 1; i < selectedItem.displayText.length; ++i) {
+          $('wallpaper-description').textContent +=
+              selectedItem.displayText[i] + ' ';
+        }
+      } else if (selectedItem.collectionName) {
+        // Display the collection name as backup.
+        $('wallpaper-description').textContent = selectedItem.collectionName;
+      }
     }
     return;
   }
@@ -1370,7 +1504,7 @@
     this.showError_(str('invalidWallpaper'));
     return;
   }
-  var layout = getSelectedLayout();
+  var layout = this.getSelectedLayout_();
   var self = this;
   var errorHandler = this.onFileSystemError_.bind(this);
   var setSelectedFile = function(file, layout, fileName) {
@@ -1472,7 +1606,7 @@
  * Handles the layout setting change of custom wallpaper.
  */
 WallpaperManager.prototype.onWallpaperLayoutChanged_ = function() {
-  this.setCustomWallpaperLayout_(getSelectedLayout());
+  this.setCustomWallpaperLayout_(this.getSelectedLayout_());
 };
 
 /**
@@ -1520,24 +1654,89 @@
 };
 
 /**
- * Implementation of |onWallpaperLayoutChanged_|. A wrapper of the
- * |setCustomWallpaperLayout| api.
- * @param {string} layout The user selected wallpaper layout.
+ * Updates the layout of the currently set custom wallpaper. No-op if the
+ * current wallpaper is not a custom wallpaper.
+ * @param {string} newLayout The new wallpaper layout.
  * @private
  */
-WallpaperManager.prototype.setCustomWallpaperLayout_ = function(layout) {
-  chrome.wallpaperPrivate.setCustomWallpaperLayout(layout, () => {
-    if (chrome.runtime.lastError != undefined &&
-        chrome.runtime.lastError.message != str('canceledWallpaper')) {
-      this.showError_(chrome.runtime.lastError.message);
-      this.removeCustomWallpaper(fileName);
-      $('set-wallpaper-layout').disabled = true;
-    } else {
-      WallpaperUtil.saveToLocalStorage(this.currentWallpaper_, layout);
-      this.onWallpaperChanged_(
-          this.wallpaperGrid_.activeItem, this.currentWallpaper_);
+WallpaperManager.prototype.setCustomWallpaperLayout_ = function(newLayout) {
+  var setCustomWallpaperLayoutImpl = (layout, onSuccess) => {
+    chrome.wallpaperPrivate.setCustomWallpaperLayout(layout, () => {
+      if (chrome.runtime.lastError != undefined &&
+          chrome.runtime.lastError.message != str('canceledWallpaper')) {
+        this.showError_(chrome.runtime.lastError.message);
+        this.removeCustomWallpaper(fileName);
+        $('set-wallpaper-layout').disabled = true;
+      } else {
+        WallpaperUtil.saveToLocalStorage(this.currentWallpaper_, layout);
+        if (this.useNewWallpaperPicker_) {
+          this.toggleLayoutButtonStates_(layout);
+          WallpaperUtil.saveWallpaperInfo(
+              this.currentWallpaper_, layout,
+              Constants.WallpaperSourceEnum.Custom, '');
+        } else {
+          this.onWallpaperChanged_(
+              this.wallpaperGrid_.activeItem, this.currentWallpaper_);
+        }
+        if (onSuccess)
+          onSuccess();
+      }
+    });
+  };
+
+  if (!this.shouldPreviewWallpaper_()) {
+    setCustomWallpaperLayoutImpl(newLayout, null /*onSuccess=*/);
+    this.currentWallpaperLayout_ = newLayout;
+    return;
+  }
+
+  // TODO(crbug.com/836396): Add |previewMode| option to
+  // |setCustomWallpaperLayout| instead.
+  var forcePreviewMode = () => {
+    chrome.wallpaperPrivate.getCurrentWallpaperThumbnail(
+        this.document_.body.offsetHeight, this.document_.body.offsetWidth,
+        image => {
+          chrome.wallpaperPrivate.setCustomWallpaper(
+              image, Constants.WallpaperThumbnailDefaultLayout,
+              false /*generateThumbnail=*/, this.currentWallpaper_,
+              true /*previewMode=*/, () => {
+                chrome.wallpaperPrivate.cancelPreviewWallpaper(() => {});
+              });
+        });
+  };
+  forcePreviewMode();
+
+  var decorateLayoutButton = layout => {
+    if (layout != 'CENTER' && layout != 'CENTER_CROPPED') {
+      console.error('Wallpaper layout ' + layout + ' is not supported.');
+      return;
     }
-  });
+    var layoutButton = this.document_.querySelector(
+        layout == 'CENTER' ? '.center-button' : '.center-cropped-button');
+    var newLayoutButton = layoutButton.cloneNode(true);
+    layoutButton.parentNode.replaceChild(newLayoutButton, layoutButton);
+    newLayoutButton.addEventListener('click', () => {
+      setCustomWallpaperLayoutImpl(layout, () => {
+        this.document_.querySelector('.center-button')
+            .classList.toggle('disabled', layout == 'CENTER');
+        this.document_.querySelector('.center-cropped-button')
+            .classList.toggle('disabled', layout == 'CENTER_CROPPED');
+        this.onPreviewModeStarted_(
+            Constants.WallpaperSourceEnum.Custom, null /*optConfirmCallback=*/,
+            setCustomWallpaperLayoutImpl.bind(
+                null, this.currentWallpaperLayout_),
+            /*optOnRefreshClicked=*/null);
+      });
+    });
+  };
+
+  decorateLayoutButton('CENTER');
+  decorateLayoutButton('CENTER_CROPPED');
+  this.document_
+      .querySelector(
+          newLayout == 'CENTER' ? '.center-button' : '.center-cropped-button')
+      .click();
+  this.setWallpaperAttribution({collectionName: str('customCategoryLabel')});
 };
 
 /**
@@ -1548,17 +1747,11 @@
 WallpaperManager.prototype.onSurpriseMeStateChanged_ = function(enabled) {
   WallpaperUtil.setSurpriseMeCheckboxValue(enabled);
   $('categories-list').disabled = enabled;
+  $('wallpaper-grid').disabled = enabled;
   if (enabled)
     this.document_.body.removeAttribute('surprise-me-disabled');
   else
     this.document_.body.setAttribute('surprise-me-disabled', '');
-
-  // The surprise me state affects the UI of the current wallpaper info bar.
-  this.decorateCurrentWallpaperInfoBar_();
-  // On the old wallpaper picker, the wallpaper grid should be disabled when
-  // surprise me is enabled.
-  if (!this.useNewWallpaperPicker_)
-    $('wallpaper-grid').disabled = enabled;
 };
 
 /**
@@ -1756,6 +1949,15 @@
 };
 
 /**
+ * Returns whether preview mode is currently on.
+ * @return {boolean} Whether preview mode is currently on.
+ * @private
+ */
+WallpaperManager.prototype.isDuringPreview_ = function() {
+  return this.document_.body.classList.contains('preview-mode');
+};
+
+/**
  * Notifies the wallpaper manager that the scroll bar position changes.
  * @param {number} scrollTop The distance between the scroll bar and the top.
  */
@@ -1767,4 +1969,223 @@
   $('wallpaper-grid').classList.toggle('top-padding', needTopPadding);
 };
 
+/**
+ * Returns the currently selected layout.
+ * @return {string} The selected layout.
+ * @private
+ */
+WallpaperManager.prototype.getSelectedLayout_ = function() {
+  if (this.useNewWallpaperPicker_) {
+    return this.currentlySelectedLayout_ ?
+        this.currentlySelectedLayout_ :
+        Constants.WallpaperThumbnailDefaultLayout;
+  }
+  var setWallpaperLayout = $('set-wallpaper-layout');
+  return setWallpaperLayout.options[setWallpaperLayout.selectedIndex].value;
+};
+
+/**
+ * Toggles the disabled states of the layout buttons on the top header bar based
+ * on the currently selected layout.
+ * @param {string} layout The currently selected layout.
+ * @private
+ */
+WallpaperManager.prototype.toggleLayoutButtonStates_ = function(layout) {
+  $('center').classList.toggle('disabled', layout == 'CENTER');
+  $('center-cropped').classList.toggle('disabled', layout == 'CENTER_CROPPED');
+};
+
+/**
+ * Fetches the info related to the daily refresh feature and updates the UI for
+ * the sliders. Only used by the new wallpaper picker.
+ * @private
+ */
+WallpaperManager.prototype.initializeDailyRefreshStates_ = function() {
+  if (!this.useNewWallpaperPicker_)
+    return;
+
+  var initializeDailyRefreshStatesImpl = dailyRefreshInfo => {
+    if (dailyRefreshInfo) {
+      this.dailyRefreshInfo_ = dailyRefreshInfo;
+    } else {
+      // We reach here if it's the first time the new picker is in use, or the
+      // unlikely case that the data was corrupted (it's safe to assume daily
+      // refresh is disabled if this ever happens).
+      this.dailyRefreshInfo_ = {
+        enabled: false,
+        collectionId: null,
+        resumeToken: null
+      };
+    }
+
+    this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
+    this.decorateCurrentWallpaperInfoBar_();
+  };
+
+  WallpaperUtil.getDailyRefreshInfo(
+      initializeDailyRefreshStatesImpl.bind(null));
+};
+
+/**
+ * Updates the UI of all the daily refresh sliders based on the info.
+ * @param {Object} dailyRefreshInfo The daily refresh info.
+ * @private
+ */
+WallpaperManager.prototype.updateDailyRefreshSliderStates_ = function(
+    dailyRefreshInfo) {
+  if (!this.dailyRefreshSliderMap_ || !dailyRefreshInfo)
+    return;
+
+  Object.entries(this.dailyRefreshSliderMap_)
+      .forEach(([collectionId, dailyRefreshSlider]) => {
+        var enabled = dailyRefreshInfo.enabled &&
+            dailyRefreshInfo.collectionId === collectionId;
+        dailyRefreshSlider.classList.toggle('checked', enabled);
+      });
+};
+
+/**
+ * Decorates the UI and registers event listener for the slider.
+ * @param {string} collectionId The collection id that this slider is associated
+ *     with.
+ * @param {Object} dailyRefreshSlider The daily refresh slider.
+ */
+WallpaperManager.prototype.decorateDailyRefreshSlider = function(
+    collectionId, dailyRefreshSlider) {
+  if (!this.dailyRefreshSliderMap_)
+    this.dailyRefreshSliderMap_ = {};
+
+  this.dailyRefreshSliderMap_[collectionId] = dailyRefreshSlider;
+  this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
+  dailyRefreshSlider.addEventListener('click', () => {
+    var isSliderEnabled = dailyRefreshSlider.classList.contains('checked');
+    var isCollectionEnabled =
+        collectionId === this.dailyRefreshInfo_.collectionId;
+    if (isSliderEnabled !== isCollectionEnabled) {
+      console.error(
+          'There is a mismatch between the enabled daily refresh collection ' +
+          'and the slider state. This should never happen.');
+      return;
+    }
+    if (isSliderEnabled) {
+      // Disable daily refresh. The current value of the collection id and
+      // resume token can be discarded.
+      this.dailyRefreshInfo_ = {
+        enabled: false,
+        collectionId: null,
+        resumeToken: null
+      };
+      WallpaperUtil.saveDailyRefreshInfo(this.dailyRefreshInfo_);
+      this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
+      this.decorateCurrentWallpaperInfoBar_();
+    } else {
+      // Enable daily refresh but do not overwrite |dailyRefreshInfo_| yet
+      // (since it's still possible to revert). The resume token is left empty
+      // for now.
+      this.pendingDailyRefreshInfo_ = {
+        enabled: true,
+        collectionId: collectionId,
+        resumeToken: null
+      };
+      this.setDailyRefreshWallpaper_();
+    }
+  });
+};
+
+/**
+ * Fetches the image for daily refresh based on |pendingDailyRefreshInfo_|.
+ * Either sets it directly or enters preview mode.
+ * @private
+ */
+WallpaperManager.prototype.setDailyRefreshWallpaper_ = function() {
+  if (!this.pendingDailyRefreshInfo_)
+    return;
+  // There should be immediate UI update even though the info hasn't been saved.
+  this.updateDailyRefreshSliderStates_(this.pendingDailyRefreshInfo_);
+  if (this.isDuringPreview_())
+    $('spinner').hidden = false;
+
+  chrome.wallpaperPrivate.getSurpriseMeImage(
+      this.pendingDailyRefreshInfo_.collectionId,
+      this.pendingDailyRefreshInfo_.resumeToken,
+      (imageInfo, nextResumeToken) => {
+        var failureCallback = () => {
+          this.pendingDailyRefreshInfo_ = null;
+          // Restore the original states.
+          this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
+          $('spinner').hidden = true;
+        };
+        if (chrome.runtime.lastError) {
+          console.error(
+              'Error fetching daily refresh wallpaper for collection id: ' +
+              this.pendingDailyRefreshInfo_.collectionId);
+          failureCallback();
+          return;
+        }
+
+        this.pendingDailyRefreshInfo_.resumeToken = nextResumeToken;
+        // Find the name of the collection based on its id for display purpose.
+        var collectionName;
+        for (var i = 0; i < this.collectionsInfo_.length; ++i) {
+          if (this.collectionsInfo_[i]['collectionId'] ===
+              this.pendingDailyRefreshInfo_.collectionId) {
+            collectionName = this.collectionsInfo_[i]['collectionName'];
+          }
+        }
+        var dailyRefreshImageInfo = {
+          highResolutionURL:
+              imageInfo['imageUrl'] + str('highResolutionSuffix'),
+          layout: Constants.WallpaperThumbnailDefaultLayout,
+          source: Constants.WallpaperSourceEnum.Daily,
+          displayText: imageInfo['displayText'],
+          authorWebsite: imageInfo['actionUrl'],
+          collectionName: collectionName
+        };
+
+        var previewMode = this.shouldPreviewWallpaper_();
+        var successCallback = () => {
+          $('spinner').hidden = true;
+
+          var onWallpaperConfirmed = () => {
+            var date = new Date().toDateString();
+            WallpaperUtil.saveToLocalStorage(
+                Constants.AccessLastSurpriseWallpaperChangedDate, date, () => {
+                  WallpaperUtil.enabledSyncThemesCallback(syncEnabled => {
+                    var saveInfo = () => {
+                      this.dailyRefreshInfo_ = this.pendingDailyRefreshInfo_;
+                      WallpaperUtil.saveDailyRefreshInfo(
+                          this.dailyRefreshInfo_);
+                      this.onWallpaperChanged_(
+                          dailyRefreshImageInfo,
+                          dailyRefreshImageInfo.highResolutionURL);
+                      this.pendingDailyRefreshInfo_ = null;
+                    };
+
+                    if (syncEnabled) {
+                      WallpaperUtil.saveToSyncStorage(
+                          Constants.AccessLastSurpriseWallpaperChangedDate,
+                          date, saveInfo);
+                    } else {
+                      saveInfo();
+                    }
+                  });
+                });
+          };
+
+          if (previewMode) {
+            this.setWallpaperAttribution(dailyRefreshImageInfo);
+            this.onPreviewModeStarted_(
+                dailyRefreshImageInfo.source, onWallpaperConfirmed,
+                failureCallback, this.setDailyRefreshWallpaper_.bind(this));
+          } else {
+            onWallpaperConfirmed();
+          }
+        };
+
+        this.setSelectedOnlineWallpaper_(
+            dailyRefreshImageInfo, successCallback, failureCallback,
+            previewMode);
+      });
+};
+
 })();
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/main.html b/chrome/browser/resources/chromeos/wallpaper_manager/main.html
index 1229046..de4d65e 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/main.html
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/main.html
@@ -171,7 +171,7 @@
       <div id="cancel-preview-wallpaper" class="preview-option"></div>
       <div id="image-title"></div>
       <div class="divider"></div>
-      <div id="collection-name"></div>
+      <div id="wallpaper-description"></div>
       <div class="more-options">
         <div class="center-button custom-option">
           <div class="icon"></div>
@@ -181,13 +181,15 @@
           <div class="icon"></div>
           <div class="text" i18n-content="centerCroppedLayout"></div>
         </div>
+        <div id="refresh-wallpaper" class="daily-option"
+            i18n-content="refreshLabel"></div>
         <div id="confirm-preview-wallpaper" class="preview-option"
             i18n-content="confirmPreviewLabel"></div>
       </div>
     </div>
   </div>
-  <div id="set-successfully-message"
-      i18n-content="setSuccessfullyMessage"></div>
+  <div id="message-container"></div>
+  <div id="spinner" hidden></div>
   <div id="daily-refresh-banner-template" hidden>
     <div class="daily-refresh-banner">
       <div class="daily-refresh-label" i18n-content="surpriseMeLabel"></div>
diff --git a/chrome/browser/resources/md_bookmarks/item.html b/chrome/browser/resources/md_bookmarks/item.html
index b0cb78e..44b6bd68 100644
--- a/chrome/browser/resources/md_bookmarks/item.html
+++ b/chrome/browser/resources/md_bookmarks/item.html
@@ -56,6 +56,10 @@
       .more-vert-button {
         -webkit-margin-end: 12px;
       }
+
+      :host(:focus) {
+        z-index: 1;
+      }
     </style>
     <div id="icon"></div>
     <div id="website-title" class="elided-text" title="[[item_.title]]">
diff --git a/chrome/browser/resources/settings/a11y_page/externs.js b/chrome/browser/resources/settings/a11y_page/externs.js
index f6ef9bc6..499139f 100644
--- a/chrome/browser/resources/settings/a11y_page/externs.js
+++ b/chrome/browser/resources/settings/a11y_page/externs.js
@@ -4,8 +4,7 @@
 
 /**
  * @fileoverview Stub methods to allow the closure compiler to compile
- * successfully for external dependencies which cannot be included in
- * compiled_resources2.gyp.
+ * successfully for external dependencies.
  */
 
 /**
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index b10af44a..af03de64 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -111,8 +111,8 @@
           </settings-section>
         </template>
         <template is="dom-if"
-            if="[[shouldShowMultidevice_(showMultidevice, pageVisibility)]]"
-            restamp>
+            if="[[shouldShowMultidevice_(showMultidevice, pageVisibility,
+                hasExpandedSection_, currentRoute_)]]" restamp>
           <settings-multidevice-section-container prefs="{{prefs}}">
           </settings-multidevice-section-container>
         </template>
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.js b/chrome/browser/resources/settings/basic_page/basic_page.js
index 413754e..52becd3 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.js
+++ b/chrome/browser/resources/settings/basic_page/basic_page.js
@@ -239,7 +239,9 @@
   shouldShowMultidevice_: function() {
     const visibility = /** @type {boolean|undefined} */ (
         this.get('pageVisibility.multidevice'));
-    return this.showMultidevice && this.showPage_(visibility);
+    return this.showMultidevice && this.showPage_(visibility) &&
+        (settings.routes.MULTIDEVICE.contains(this.currentRoute_) ||
+         !this.hasExpandedSection_);
   },
 
   /**
diff --git a/chrome/browser/resources/settings/site_settings/BUILD.gn b/chrome/browser/resources/settings/site_settings/BUILD.gn
index c9332a9..b7d2dca 100644
--- a/chrome/browser/resources/settings/site_settings/BUILD.gn
+++ b/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -19,6 +19,7 @@
     ":site_data_details_subpage",
     ":site_details",
     ":site_details_permission",
+    ":site_entry",
     ":site_list",
     ":site_settings_behavior",
     ":site_settings_prefs_browser_proxy",
@@ -170,6 +171,20 @@
   ]
 }
 
+js_library("site_entry") {
+  deps = [
+    ":constants",
+    ":site_settings_behavior",
+    "..:route",
+    "//third_party/polymer/v1_0/components-chromium/iron-collapse:iron-collapse-extracted",
+    "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
+    "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render",
+    "//ui/webui/resources/js:assert",
+    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:load_time_data",
+  ]
+}
+
 js_library("site_list") {
   deps = [
     ":constants",
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.js b/chrome/browser/resources/settings/site_settings/all_sites.js
index 2a395bc..f3b611f 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.js
+++ b/chrome/browser/resources/settings/site_settings/all_sites.js
@@ -40,42 +40,11 @@
    */
   populateList_: function() {
     /** @type {!Array<settings.ContentSettingsTypes>} */
-    let contentTypes = [];
-    const types = Object.values(settings.ContentSettingsTypes);
-    for (let i = 0; i < types.length; ++i) {
-      const type = types[i];
-      // <if expr="not chromeos">
-      if (type == settings.ContentSettingsTypes.PROTECTED_CONTENT)
-        continue;
-      // </if>
-      // Some categories store their data in a custom way.
-      if (type == settings.ContentSettingsTypes.PROTOCOL_HANDLERS ||
-          type == settings.ContentSettingsTypes.ZOOM_LEVELS) {
-        continue;
-      }
-      // These categories are gated behind flags.
-      if (type == settings.ContentSettingsTypes.SENSORS &&
-          !loadTimeData.getBoolean('enableSensorsContentSetting')) {
-        continue;
-      }
-      if (type == settings.ContentSettingsTypes.ADS &&
-          !loadTimeData.getBoolean('enableSafeBrowsingSubresourceFilter')) {
-        continue;
-      }
-      if (type == settings.ContentSettingsTypes.SOUND &&
-          !loadTimeData.getBoolean('enableSoundContentSetting')) {
-        continue;
-      }
-      if (type == settings.ContentSettingsTypes.CLIPBOARD &&
-          !loadTimeData.getBoolean('enableClipboardContentSetting')) {
-        continue;
-      }
-      if (type == settings.ContentSettingsTypes.PAYMENT_HANDLER &&
-          !loadTimeData.getBoolean('enablePaymentHandlerContentSetting')) {
-        continue;
-      }
-      contentTypes.push(type);
-    }
+    const contentTypes = this.getCategoryList();
+    // Make sure to include cookies, because All Sites handles data storage +
+    // cookies as well as regular settings.ContentSettingsTypes.
+    if (!contentTypes.includes(settings.ContentSettingsTypes.COOKIES))
+      contentTypes.push(settings.ContentSettingsTypes.COOKIES);
 
     this.browserProxy_.getAllSites(contentTypes).then((response) => {
       this.siteGroupList = response;
diff --git a/chrome/browser/resources/settings/site_settings/site_details.html b/chrome/browser/resources/settings/site_settings/site_details.html
index dfbb6fff..ab798c7 100644
--- a/chrome/browser/resources/settings/site_settings/site_details.html
+++ b/chrome/browser/resources/settings/site_settings/site_details.html
@@ -116,8 +116,7 @@
       <site-details-permission
           category="{{ContentSettingsTypes.SENSORS}}"
           icon="settings:sensors" id="sensors"
-          label="$i18n{siteSettingsSensors}"
-          hidden$="[[!enableSensorsContentSetting_]]">
+          label="$i18n{siteSettingsSensors}">
       </site-details-permission>
       <site-details-permission category="{{ContentSettingsTypes.NOTIFICATIONS}}"
           icon="settings:notifications" id="notifications"
@@ -139,8 +138,7 @@
       <site-details-permission
           category="{{ContentSettingsTypes.ADS}}"
           icon="settings:ads" id="ads"
-          label="$i18n{siteSettingsAds}"
-          hidden$="[[!enableSafeBrowsingSubresourceFilter_]]">
+          label="$i18n{siteSettingsAds}">
       </site-details-permission>
       <site-details-permission
           category="{{ContentSettingsTypes.BACKGROUND_SYNC}}"
@@ -149,8 +147,7 @@
       </site-details-permission>
       <site-details-permission category="{{ContentSettingsTypes.SOUND}}"
           icon="settings:volume-up" id="sound"
-          label="$i18n{siteSettingsSound}"
-          hidden$="[[!enableSoundContentSetting_]]">
+          label="$i18n{siteSettingsSound}">
       </site-details-permission>
       <site-details-permission
           category="{{ContentSettingsTypes.AUTOMATIC_DOWNLOADS}}"
@@ -180,14 +177,12 @@
       <site-details-permission
           category="{{ContentSettingsTypes.CLIPBOARD}}"
           icon="settings:clipboard" id="clipboard"
-          label="$i18n{siteSettingsClipboard}"
-          hidden$="[[!enableClipboardContentSetting_]]">
+          label="$i18n{siteSettingsClipboard}">
       </site-details-permission>
       <site-details-permission
           category="{{ContentSettingsTypes.PAYMENT_HANDLER}}"
           icon="settings:payment-handler" id="paymentHandler"
-          label="$i18n{siteSettingsPaymentHandler}"
-          hidden$="[[!enablePaymentHandlerContentSetting_]]">
+          label="$i18n{siteSettingsPaymentHandler}">
       </site-details-permission>
     </div>
 
diff --git a/chrome/browser/resources/settings/site_settings/site_details.js b/chrome/browser/resources/settings/site_settings/site_details.js
index a264b52..155cc28 100644
--- a/chrome/browser/resources/settings/site_settings/site_details.js
+++ b/chrome/browser/resources/settings/site_settings/site_details.js
@@ -51,47 +51,6 @@
       },
     },
 
-    /** @private */
-    enableSafeBrowsingSubresourceFilter_: {
-      type: Boolean,
-      value: function() {
-        return loadTimeData.getBoolean('enableSafeBrowsingSubresourceFilter');
-      },
-    },
-
-    /** @private */
-    enableSoundContentSetting_: {
-      type: Boolean,
-      value: function() {
-        return loadTimeData.getBoolean('enableSoundContentSetting');
-      },
-    },
-
-    /** @private */
-    enableClipboardContentSetting_: {
-      type: Boolean,
-      value: function() {
-        return loadTimeData.getBoolean('enableClipboardContentSetting');
-      },
-    },
-
-    /** @private */
-    enableSensorsContentSetting_: {
-      type: Boolean,
-      readOnly: true,
-      value: function() {
-        return loadTimeData.getBoolean('enableSensorsContentSetting');
-      },
-    },
-
-    /** @private */
-    enablePaymentHandlerContentSetting_: {
-      type: Boolean,
-      value: function() {
-        return loadTimeData.getBoolean('enablePaymentHandlerContentSetting');
-      },
-    },
-
     /**
      * The type of storage for the origin.
      * @private
@@ -144,7 +103,7 @@
         if (this.enableSiteSettings_)
           this.$.usageApi.fetchUsageTotal(this.toUrl(this.origin).hostname);
 
-        this.updatePermissions_(this.getCategoryList_());
+        this.updatePermissions_(this.getCategoryList());
       }
     });
   },
@@ -162,7 +121,7 @@
         origin === undefined || origin == '') {
       return;
     }
-    if (!this.getCategoryList_().includes(category))
+    if (!this.getCategoryList().includes(category))
       return;
 
     // Site details currently doesn't support embedded origins, so ignore it and
@@ -239,20 +198,20 @@
    * Resets all permissions for the current origin.
    * @private
    */
-  onResetSettings_: function() {
+  onResetSettings_: function(e) {
     this.browserProxy.setOriginPermissions(
-        this.origin, this.getCategoryList_(), settings.ContentSetting.DEFAULT);
-    if (this.getCategoryList_().includes(settings.ContentSettingsTypes.PLUGINS))
+        this.origin, this.getCategoryList(), settings.ContentSetting.DEFAULT);
+    if (this.getCategoryList().includes(settings.ContentSettingsTypes.PLUGINS))
       this.browserProxy.clearFlashPref(this.origin);
 
-    this.$.confirmResetSettings.close();
+    this.onCloseDialog_(e);
   },
 
   /**
    * Clears all data stored, except cookies, for the current origin.
    * @private
    */
-  onClearStorage_: function() {
+  onClearStorage_: function(e) {
     // Since usage is only shown when "Site Settings" is enabled, don't clear it
     // when it's not shown.
     if (this.enableSiteSettings_ && this.storedData_ != '') {
@@ -260,7 +219,7 @@
           this.toUrl(this.origin).href, this.storageType_);
     }
 
-    this.$.confirmClearStorage.close();
+    this.onCloseDialog_(e);
   },
 
   /**
@@ -275,20 +234,6 @@
   },
 
   /**
-   * Returns list of categories for each permission displayed in <site-details>.
-   * @return {!Array<!settings.ContentSettingsTypes>}
-   * @private
-   */
-  getCategoryList_: function() {
-    const categoryList = [];
-    this.root.querySelectorAll('site-details-permission').forEach((element) => {
-      if (!element.hidden)
-        categoryList.push(element.category);
-    });
-    return categoryList;
-  },
-
-  /**
    * Checks whether the permission list is standalone or has a heading.
    * @return {string} CSS class applied when the permission list has no heading.
    * @private
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.html b/chrome/browser/resources/settings/site_settings/site_details_permission.html
index e2a3019..76881dc 100644
--- a/chrome/browser/resources/settings/site_settings/site_details_permission.html
+++ b/chrome/browser/resources/settings/site_settings/site_details_permission.html
@@ -12,7 +12,7 @@
 <dom-module id="site-details-permission">
   <template>
     <style include="settings-shared md-select"></style>
-    <div id="details">
+    <div id="details" hidden$="[[shouldHideCategory_(category)]]">
       <div id="permissionItem"
           class$="list-item [[permissionInfoStringClass_(site.source, category,
                                                          site.setting)]]">
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.js b/chrome/browser/resources/settings/site_settings/site_details_permission.js
index ce339395..b40bd94 100644
--- a/chrome/browser/resources/settings/site_settings/site_details_permission.js
+++ b/chrome/browser/resources/settings/site_settings/site_details_permission.js
@@ -36,6 +36,10 @@
         this.onDefaultSettingChanged_.bind(this));
   },
 
+  shouldHideCategory_: function(category) {
+    return !this.getCategoryList().includes(category);
+  },
+
   /**
    * Updates the drop-down value after |site| has changed.
    * @param {!RawSiteException} site The site to display.
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.html b/chrome/browser/resources/settings/site_settings/site_entry.html
index 3f9eb5d..f271018 100644
--- a/chrome/browser/resources/settings/site_settings/site_entry.html
+++ b/chrome/browser/resources/settings/site_settings/site_entry.html
@@ -7,20 +7,43 @@
 
 <dom-module id="site-entry">
   <template>
-    <style include="settings-shared"></style>
+    <style include="settings-shared">
+      .row-aligned {
+        display: flex;
+        flex-direction: row;
+      }
+    </style>
     <div id="collapseParent">
-      <div id="toggleButton" class="settings-box list-item"
-          on-click="toggleCollapsible_" actionable aria-expanded="false">
-        <div class="favicon-image"
-            style$="[[getSiteGroupIcon_(siteGroup)]]">
+      <div class="settings-box list-item">
+        <div id="toggleButton" class="start row-aligned"
+            on-click="toggleCollapsible_" actionable aria-expanded="false">
+          <div class="favicon-image"
+              style$="[[getSiteGroupIcon_(siteGroup)]]">
+          </div>
+          <div class="middle text-elide" id="displayName">
+            [[displayName_]]
+          </div>
+          <div hidden$="[[!grouped_(siteGroup)]]">
+            <paper-icon-button-light id="expandIcon" class="icon-expand-more">
+              <button aria-label$="[[displayName_]]"
+                  aria-describedby="displayName"></button>
+            </paper-icon-button-light>
+          </div>
+          <div hidden$="[[grouped_(siteGroup)]]">
+            <paper-icon-button-light class="subpage-arrow">
+              <button aria-label$="[[displayName_]]"
+                  aria-describedby="displayName"></button>
+            </paper-icon-button-light>
+          </div>
         </div>
-        <div class="middle text-elide" id="displayName">
-          [[displayName_(siteGroup)]]
+        <div class="row-aligned" hidden$="[[!grouped_(siteGroup)]]">
+          <div class="separator"></div>
+          <paper-icon-button-light class="icon-more-vert">
+            <button id="overflowMenuButton" title="$i18n{moreActions}"
+                on-click="showOverflowMenu_">
+            </button>
+          </paper-icon-button-light>
         </div>
-        <paper-icon-button-light class="subpage-arrow">
-          <button aria-label$="[[displayName_(siteGroup)]]"
-              aria-describedby="displayName"></button>
-        </paper-icon-button-light>
       </div>
 
       <iron-collapse id="collapseChild" no-animation>
@@ -31,7 +54,7 @@
               <div class="favicon-image"
                   style$="[[computeSiteIcon(item)]]">
               </div>
-              <div class="middle text-elide" data-index="[[index]]">
+              <div class="middle text-elide">
                 [[item]]
               </div>
             </div>
@@ -39,6 +62,38 @@
         </div>
       </iron-collapse>
     </div>
+
+    <!-- Overflow menu. -->
+    <cr-lazy-render id="menu">
+      <template>
+        <cr-action-menu>
+          <button slot="item" class="dropdown-item" role="menuitem"
+              on-click="onConfirmResetSettings_">
+            Reset permissions
+          </button>
+        </cr-action-menu>
+      </template>
+    </cr-lazy-render>
+
+    <!-- Confirm reset settings dialog. -->
+    <cr-dialog id="confirmResetSettings" close-text="$i18n{close}">
+      <div slot="title">
+        $i18n{siteSettingsSiteGroupResetDialogTitle}
+      </div>
+      <div slot="body">
+        [[getFormatString_(
+            '$i18nPolymer{siteSettingsSiteGroupResetConfirmation}',
+            displayName_)]]
+      </div>
+      <div slot="button-container">
+        <paper-button class="cancel-button" on-click="onCloseDialog_">
+          $i18n{cancel}
+        </paper-button>
+        <paper-button class="action-button" on-click="onResetSettings_">
+          $i18n{siteSettingsSiteResetAll}
+        </paper-button>
+      </div>
+    </cr-dialog>
   </template>
   <script src="site_entry.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.js b/chrome/browser/resources/settings/site_settings/site_entry.js
index 9ba76a6..8b2a1db7 100644
--- a/chrome/browser/resources/settings/site_settings/site_entry.js
+++ b/chrome/browser/resources/settings/site_settings/site_entry.js
@@ -17,13 +17,23 @@
      * An object representing a group of sites with the same eTLD+1.
      * @typedef {!SiteGroup}
      */
-    siteGroup: Object,
+    siteGroup: {
+      type: Object,
+      observer: 'onSiteGroupChanged_',
+    },
+
+    /**
+     * The name to display beside the icon. If grouped_() is true, it will be
+     * the eTLD+1 for all the origins, otherwise, it will match the origin more
+     * closely in an appropriate site representation.
+     */
+    displayName_: String,
   },
 
   /**
    * Whether the list of origins displayed in this site-entry is a group of
    * eTLD+1 origins or not.
-   * @param {Array<Object>} siteGroup The eTLD+1 group of origins.
+   * @param {SiteGroup} siteGroup The eTLD+1 group of origins.
    * @return {boolean}
    * @private
    */
@@ -32,25 +42,20 @@
   },
 
   /**
-   * The name to display beside the icon. If grouped_() is true, it will return
-   * the eTLD+1 for all the origins, otherwise, it will return the origin in an
-   * appropriate site representation.
-   * @param {Array<Object>} siteGroup The eTLD+1 group of origins.
-   * @return {string} The name to display.
+   * @param {SiteGroup} siteGroup The eTLD+1 group of origins.
    * @private
    */
-  displayName_: function(siteGroup) {
-    if (this.grouped_(siteGroup))
-      return siteGroup.etldPlus1;
-    // TODO(https://crbug.com/835712): Return the origin in a user-friendly site
-    // representation.
-    return siteGroup.origins[0];
+  onSiteGroupChanged_: function(siteGroup) {
+    // TODO(https://crbug.com/835712): Present the origin in a user-friendly
+    // site representation when ungrouped.
+    this.displayName_ =
+        this.grouped_(siteGroup) ? siteGroup.etldPlus1 : siteGroup.origins[0];
   },
 
   /**
    * Get an appropriate favicon that represents this group of eTLD+1 sites as a
    * whole.
-   * @param {Array<Object>} siteGroup The eTLD+1 group of origins.
+   * @param {SiteGroup} siteGroup The eTLD+1 group of origins.
    * @return {string} CSS to apply to show the appropriate favicon.
    * @private
    */
@@ -74,28 +79,95 @@
 
   /**
    * A handler for selecting a site (by clicking on the origin).
-   * @param {!{model: !{index: !number}}} event
+   * @param {!{model: !{index: !number}}} e
    * @private
    */
-  onOriginTap_: function(event) {
-    this.navigateToSiteDetails_(this.siteGroup.origins[event.model.index]);
+  onOriginTap_: function(e) {
+    this.navigateToSiteDetails_(this.siteGroup.origins[e.model.index]);
   },
 
   /**
    * Toggles open and closed the list of origins if there is more than one, and
    * directly navigates to Site Details if there is only one site.
-   * @param {!Object} event
+   * @param {!Object} e
    * @private
    */
-  toggleCollapsible_: function(event) {
+  toggleCollapsible_: function(e) {
     // Individual origins don't expand - just go straight to Site Details.
     if (!this.grouped_(this.siteGroup)) {
       this.navigateToSiteDetails_(this.siteGroup.origins[0]);
       return;
     }
 
-    let collapseChild = this.$.collapseChild;
+    let collapseChild =
+        /** @type {IronCollapseElement} */ (this.$.collapseChild);
     collapseChild.toggle();
     this.$.toggleButton.setAttribute('aria-expanded', collapseChild.opened);
+    this.$.expandIcon.toggleClass('icon-expand-more');
+    this.$.expandIcon.toggleClass('icon-expand-less');
+  },
+
+  /**
+   * Retrieves the overflow menu.
+   * @private
+   */
+  getOverflowMenu_: function() {
+    let menu = /** @type {?CrActionMenuElement} */ (this.$.menu.getIfExists());
+    if (!menu)
+      menu = /** @type {!CrActionMenuElement} */ (this.$.menu.get());
+    return menu;
+  },
+
+  /**
+   * Opens the overflow menu at event target.
+   * @param {!{target: Element}} e
+   * @private
+   */
+  showOverflowMenu_: function(e) {
+    this.getOverflowMenu_().showAt(e.target);
+  },
+
+  /** @private */
+  onCloseDialog_: function(e) {
+    e.target.closest('cr-dialog').close();
+    this.getOverflowMenu_().close();
+  },
+
+  /**
+   * Confirms the resetting of all content settings for an origin.
+   * @param {!{target: !Element}} e
+   * @private
+   */
+  onConfirmResetSettings_: function(e) {
+    e.preventDefault();
+    this.$.confirmResetSettings.showModal();
+  },
+
+  /**
+   * Resets all permissions for all origins listed in |siteGroup.origins|.
+   * @param {!Event} e
+   * @private
+   */
+  onResetSettings_: function(e) {
+    const contentSettingsTypes = this.getCategoryList();
+    for (let i = 0; i < this.siteGroup.origins.length; ++i) {
+      const origin = this.siteGroup.origins[i];
+      this.browserProxy.setOriginPermissions(
+          origin, contentSettingsTypes, settings.ContentSetting.DEFAULT);
+      if (contentSettingsTypes.includes(settings.ContentSettingsTypes.PLUGINS))
+        this.browserProxy.clearFlashPref(origin);
+    }
+    this.onCloseDialog_(e);
+  },
+
+  /**
+   * Formats the |label| string with |name|, using $<num> as markers.
+   * @param {string} label
+   * @param {string} name
+   * @return {string}
+   * @private
+   */
+  getFormatString_: function(label, name) {
+    return loadTimeData.substituteString(label, name);
   },
 });
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
index 1c244c0b..99315be 100644
--- a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
+++ b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
@@ -32,6 +32,18 @@
     category: String,
 
     /**
+     * A cached list of ContentSettingsTypes with a standard allow-block-ask
+     * pattern that are currently enabled for use. This property is the same
+     * across all elements with SiteSettingsBehavior ('static').
+     * @type {Array<settings.ContentSettingsTypes>}
+     * @private
+     */
+    contentTypes_: {
+      type: Array,
+      value: [],
+    },
+
+    /**
      * The browser proxy used to retrieve and change information about site
      * settings categories and the sites within.
      * @type {settings.SiteSettingsPrefsBrowserProxy}
@@ -98,7 +110,6 @@
    * Returns the icon to use for a given site.
    * @param {string} site The url of the site to fetch the icon for.
    * @return {string} The background-image style with the favicon.
-   * @private
    */
   computeSiteIcon: function(site) {
     site = this.removePatternWildcard(site);
@@ -170,6 +181,56 @@
     };
   },
 
+  /**
+   * Returns list of categories for each setting.ContentSettingsTypes that are
+   * currently enabled.
+   * @return {!Array<!settings.ContentSettingsTypes>}
+   */
+  getCategoryList: function() {
+    if (this.contentTypes_.length == 0) {
+      /** @type {!Array<settings.ContentSettingsTypes>} */
+      for (let typeName in settings.ContentSettingsTypes) {
+        const contentType = settings.ContentSettingsTypes[typeName];
+        // <if expr="not chromeos">
+        if (contentType == settings.ContentSettingsTypes.PROTECTED_CONTENT)
+          continue;
+        // </if>
+        // Some categories store their data in a custom way.
+        if (contentType == settings.ContentSettingsTypes.COOKIES ||
+            contentType == settings.ContentSettingsTypes.PROTOCOL_HANDLERS ||
+            contentType == settings.ContentSettingsTypes.ZOOM_LEVELS) {
+          continue;
+        }
+        this.contentTypes_.push(contentType);
+      }
+    }
+
+    const addOrRemoveSettingWithFlag = (type, flag) => {
+      if (loadTimeData.getBoolean(flag)) {
+        if (!this.contentTypes_.includes(type))
+          this.contentTypes_.push(type);
+      } else {
+        if (this.contentTypes_.includes(type))
+          this.contentTypes_.splice(this.contentTypes_.indexOf(type), 1);
+      }
+    };
+    // These categories are gated behind flags.
+    addOrRemoveSettingWithFlag(
+        settings.ContentSettingsTypes.SENSORS, 'enableSensorsContentSetting');
+    addOrRemoveSettingWithFlag(
+        settings.ContentSettingsTypes.ADS,
+        'enableSafeBrowsingSubresourceFilter');
+    addOrRemoveSettingWithFlag(
+        settings.ContentSettingsTypes.SOUND, 'enableSoundContentSetting');
+    addOrRemoveSettingWithFlag(
+        settings.ContentSettingsTypes.CLIPBOARD,
+        'enableClipboardContentSetting');
+    addOrRemoveSettingWithFlag(
+        settings.ContentSettingsTypes.PAYMENT_HANDLER,
+        'enablePaymentHandlerContentSetting');
+    return this.contentTypes_.slice(0);
+  },
+
 };
 
 /** @polymerBehavior */
diff --git a/chrome/browser/service_process/DEPS b/chrome/browser/service_process/DEPS
deleted file mode 100644
index 61ef5fec..0000000
--- a/chrome/browser/service_process/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+mojo/edk/embedder",
-]
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index fa557bbd..e9219ad 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -229,7 +229,7 @@
           browser, tab.navigations, tab_index, selected_index,
           tab.extension_app_id,
           disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB,  // selected
-          tab.pinned, true, nullptr, tab.user_agent_override,
+          tab.pinned, true, base::TimeTicks(), nullptr, tab.user_agent_override,
           true /* from_session_restore */);
       // Start loading the tab immediately.
       web_contents->GetController().LoadIfNecessary();
@@ -515,60 +515,54 @@
     DVLOG(1) << "RestoreTabsToBrowser " << window.tabs.size();
     DCHECK(!window.tabs.empty());
     base::TimeTicks now = base::TimeTicks::Now();
-    base::TimeTicks highest_time = base::TimeTicks::UnixEpoch();
-    if (initial_tab_count == 0) {
-      // The last active time of a WebContents is initially set to the
-      // creation time of the tab, which is not necessarly the same as the
-      // loading time, so we have to restore the values. Also, since TimeTicks
-      // only make sense in their current session, these values have to be
-      // sanitized first. To do so, we need to first figure out the largest
-      // time. This will then be used to set the last active time of
-      // each tab where the most recent tab will have its time set to |now|
-      // and the rest of the tabs will have theirs set earlier by the same
-      // delta as they originally had.
-      for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
-        const sessions::SessionTab& tab = *(window.tabs[i]);
-        if (tab.last_active_time > highest_time)
-          highest_time = tab.last_active_time;
-      }
+    base::TimeTicks latest_last_active_time = base::TimeTicks::UnixEpoch();
+    // The last active time of a WebContents is initially set to the
+    // creation time of the tab, which is not necessarly the same as the
+    // loading time, so we have to restore the values. Also, since TimeTicks
+    // only make sense in their current session, these values have to be
+    // sanitized first. To do so, we need to first figure out the largest
+    // time. This will then be used to set the last active time of
+    // each tab where the most recent tab will have its time set to |now|
+    // and the rest of the tabs will have theirs set earlier by the same
+    // delta as they originally had.
+    for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
+      const sessions::SessionTab& tab = *(window.tabs[i]);
+      if (tab.last_active_time > latest_last_active_time)
+        latest_last_active_time = tab.last_active_time;
+    }
 
-      for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
-        const sessions::SessionTab& tab = *(window.tabs[i]);
+    for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
+      const sessions::SessionTab& tab = *(window.tabs[i]);
 
-        // Loads are scheduled for each restored tab unless the tab is going to
-        // be selected as ShowBrowser() will load the selected tab.
-        bool is_selected_tab = (i == selected_tab_index);
-        RestoreTab(tab, browser, created_contents, i, is_selected_tab, now,
-                   highest_time);
-      }
-    } else {
+      // Loads are scheduled for each restored tab unless the tab is going to
+      // be selected as ShowBrowser() will load the selected tab.
+      bool is_selected_tab =
+          (initial_tab_count == 0) && (i == selected_tab_index);
+
+      // Sanitize the last active time.
+      base::TimeDelta delta = latest_last_active_time - tab.last_active_time;
+      base::TimeTicks last_active_time = now - delta;
+
       // If the browser already has tabs, we want to restore the new ones after
       // the existing ones. E.g. this happens in Win8 Metro where we merge
       // windows or when launching a hosted app from the app launcher.
-      int tab_index_offset = initial_tab_count;
-
-      // Always schedule loads as we will not be calling ShowBrowser().
-      bool is_selected_tab = false;
-
-      for (int i = 0; i < static_cast<int>(window.tabs.size()); ++i) {
-        const sessions::SessionTab& tab = *(window.tabs[i]);
-        RestoreTab(tab, browser, created_contents, tab_index_offset + i,
-                   is_selected_tab, now, highest_time);
-      }
+      int tab_index = i + initial_tab_count;
+      RestoreTab(tab, browser, created_contents, tab_index, is_selected_tab,
+                 last_active_time);
     }
   }
 
   // |tab_index| is ignored for pinned tabs which will always be pushed behind
   // the last existing pinned tab.
   // |tab_loader_| will schedule this tab for loading if |is_selected_tab| is
-  // false.
+  // false. |last_active_time| is the value to use to set the last time the
+  // WebContents was made active.
   void RestoreTab(const sessions::SessionTab& tab,
                   Browser* browser,
                   std::vector<RestoredTab>* created_contents,
                   const int tab_index,
                   bool is_selected_tab,
-                  base::TimeTicks now,
-                  base::TimeTicks highest_time) {
+                  base::TimeTicks last_active_time) {
     // It's possible (particularly for foreign sessions) to receive a tab
     // without valid navigations. In that case, just skip it.
     // See crbug.com/154129.
@@ -592,8 +586,8 @@
     WebContents* web_contents = chrome::AddRestoredTab(
         browser, tab.navigations, tab_index, selected_index,
         tab.extension_app_id, is_selected_tab, tab.pinned, true,
-        session_storage_namespace.get(), tab.user_agent_override,
-        true /* from_session_restore */);
+        last_active_time, session_storage_namespace.get(),
+        tab.user_agent_override, true /* from_session_restore */);
     // Regression check: if the current tab |is_selected_tab|, it should load
     // immediately, otherwise, tabs should not start loading right away. The
     // focused tab will be loaded by Browser, and TabLoader will load the rest.
@@ -603,10 +597,6 @@
     if (!web_contents)
       return;
 
-    // Sanitize the last active time.
-    base::TimeDelta delta = highest_time - tab.last_active_time;
-    web_contents->SetLastActiveTime(now - delta);
-
     RestoredTab restored_tab(web_contents, is_selected_tab,
                              tab.extension_app_id.empty(), tab.pinned);
     created_contents->push_back(restored_tab);
diff --git a/chrome/browser/sessions/session_restore_stats_collector_unittest.cc b/chrome/browser/sessions/session_restore_stats_collector_unittest.cc
index 596fae3..185acd1 100644
--- a/chrome/browser/sessions/session_restore_stats_collector_unittest.cc
+++ b/chrome/browser/sessions/session_restore_stats_collector_unittest.cc
@@ -21,6 +21,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_web_contents_factory.h"
+#include "content/public/test/web_contents_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -280,8 +281,8 @@
     contents->GetController().Restore(
         0, content::RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);
     // Create a last active time in the past.
-    contents->SetLastActiveTime(base::TimeTicks::Now() -
-                                base::TimeDelta::FromMinutes(1));
+    content::WebContentsTester::For(contents)->SetLastActiveTime(
+        base::TimeTicks::Now() - base::TimeDelta::FromMinutes(1));
     // TabLoadTracker needs the resource_coordinator WebContentsData to be
     // initialized.
     ResourceCoordinatorTabHelper::CreateForWebContents(contents);
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
index 5630b566..8564d33 100644
--- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -82,8 +82,10 @@
     if (service()->ConfigurationDone())
       return true;
     // Sync is blocked because a custom passphrase is required.
-    if (service()->passphrase_required_reason() == syncer::REASON_DECRYPTION)
+    if (service()->passphrase_required_reason_for_test() ==
+        syncer::REASON_DECRYPTION) {
       return true;
+    }
     // Sync is blocked by an auth error.
     if (HasAuthError(service()))
       return true;
@@ -346,7 +348,8 @@
 
   // Make sure that initial sync wasn't blocked by a missing passphrase.
   if (!skip_passphrase_verification &&
-      service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) {
+      service()->passphrase_required_reason_for_test() ==
+          syncer::REASON_DECRYPTION) {
     LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
                   " until SetDecryptionPassphrase is called.";
     return false;
@@ -370,7 +373,8 @@
   // If passphrase verification is not skipped, make sure that initial sync
   // wasn't blocked by a missing passphrase.
   if (!skip_passphrase_verification &&
-      service()->passphrase_required_reason() == syncer::REASON_DECRYPTION) {
+      service()->passphrase_required_reason_for_test() ==
+          syncer::REASON_DECRYPTION) {
     LOG(ERROR) << "A passphrase is required for decryption. Sync cannot proceed"
                   " until SetDecryptionPassphrase is called.";
     return false;
@@ -546,7 +550,7 @@
        << snap.model_neutral_state().num_updates_downloaded_total
        << ", passphrase_required_reason: "
        << syncer::PassphraseRequiredReasonToString(
-              service()->passphrase_required_reason())
+              service()->passphrase_required_reason_for_test())
        << ", notifications_enabled: " << status.notifications_enabled
        << ", service_is_active: " << service()->IsSyncActive();
   } else {
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.cc b/chrome/browser/ui/ash/test_wallpaper_controller.cc
index 9eedb668..d765c94 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.cc
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.cc
@@ -190,8 +190,8 @@
   NOTIMPLEMENTED();
 }
 
-void TestWallpaperController::GetActiveUserWallpaperLocation(
-    ash::mojom::WallpaperController::GetActiveUserWallpaperLocationCallback
+void TestWallpaperController::GetActiveUserWallpaperInfo(
+    ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback
         callback) {
   NOTIMPLEMENTED();
 }
diff --git a/chrome/browser/ui/ash/test_wallpaper_controller.h b/chrome/browser/ui/ash/test_wallpaper_controller.h
index 76a47d6..a1fde390 100644
--- a/chrome/browser/ui/ash/test_wallpaper_controller.h
+++ b/chrome/browser/ui/ash/test_wallpaper_controller.h
@@ -110,8 +110,8 @@
   void IsActiveUserWallpaperControlledByPolicy(
       ash::mojom::WallpaperController::
           IsActiveUserWallpaperControlledByPolicyCallback callback) override;
-  void GetActiveUserWallpaperLocation(
-      ash::mojom::WallpaperController::GetActiveUserWallpaperLocationCallback
+  void GetActiveUserWallpaperInfo(
+      ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback
           callback) override;
   void ShouldShowWallpaperSetting(
       ash::mojom::WallpaperController::ShouldShowWallpaperSettingCallback
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.cc b/chrome/browser/ui/ash/wallpaper_controller_client.cc
index f448551..33224c32 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.cc
@@ -419,10 +419,10 @@
       std::move(callback));
 }
 
-void WallpaperControllerClient::GetActiveUserWallpaperLocation(
-    ash::mojom::WallpaperController::GetActiveUserWallpaperLocationCallback
+void WallpaperControllerClient::GetActiveUserWallpaperInfo(
+    ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback
         callback) {
-  wallpaper_controller_->GetActiveUserWallpaperLocation(std::move(callback));
+  wallpaper_controller_->GetActiveUserWallpaperInfo(std::move(callback));
 }
 
 void WallpaperControllerClient::ShouldShowWallpaperSetting(
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.h b/chrome/browser/ui/ash/wallpaper_controller_client.h
index 3981fa6..d6f19fc 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.h
@@ -90,8 +90,8 @@
   void IsActiveUserWallpaperControlledByPolicy(
       ash::mojom::WallpaperController::
           IsActiveUserWallpaperControlledByPolicyCallback callback);
-  void GetActiveUserWallpaperLocation(
-      ash::mojom::WallpaperController::GetActiveUserWallpaperLocationCallback
+  void GetActiveUserWallpaperInfo(
+      ash::mojom::WallpaperController::GetActiveUserWallpaperInfoCallback
           callback);
   void ShouldShowWallpaperSetting(
       ash::mojom::WallpaperController::ShouldShowWallpaperSettingCallback
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc
index 0bca9d7..81d6154 100644
--- a/chrome/browser/ui/browser_live_tab_context.cc
+++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -90,8 +90,8 @@
 
   WebContents* web_contents = chrome::AddRestoredTab(
       browser_, navigations, tab_index, selected_navigation, extension_app_id,
-      select, pin, from_last_session, storage_namespace, user_agent_override,
-      false /* from_session_restore */);
+      select, pin, from_last_session, base::TimeTicks(), storage_namespace,
+      user_agent_override, false /* from_session_restore */);
 
 #if BUILDFLAG(ENABLE_SESSION_SERVICE)
   // The focused tab will be loaded by Browser, and TabLoader will load the
diff --git a/chrome/browser/ui/browser_tabrestore.cc b/chrome/browser/ui/browser_tabrestore.cc
index 85a3969..9c67bd9 100644
--- a/chrome/browser/ui/browser_tabrestore.cc
+++ b/chrome/browser/ui/browser_tabrestore.cc
@@ -47,6 +47,7 @@
     int selected_navigation,
     const std::string& extension_app_id,
     bool from_last_session,
+    base::TimeTicks last_active_time,
     content::SessionStorageNamespace* session_storage_namespace,
     const std::string& user_agent_override,
     bool initially_hidden,
@@ -65,6 +66,7 @@
   create_params.initially_hidden = initially_hidden;
   create_params.desired_renderer_state =
       WebContents::CreateParams::kNoRendererProcess;
+  create_params.last_active_time = last_active_time;
   WebContents* base_web_contents =
       browser->tab_strip_model()->GetActiveWebContents();
   if (base_web_contents) {
@@ -102,13 +104,14 @@
     bool select,
     bool pin,
     bool from_last_session,
+    base::TimeTicks last_active_time,
     content::SessionStorageNamespace* session_storage_namespace,
     const std::string& user_agent_override,
     bool from_session_restore) {
   std::unique_ptr<WebContents> web_contents = CreateRestoredTab(
       browser, navigations, selected_navigation, extension_app_id,
-      from_last_session, session_storage_namespace, user_agent_override,
-      !select, from_session_restore);
+      from_last_session, last_active_time, session_storage_namespace,
+      user_agent_override, !select, from_session_restore);
 
   int add_types = select ? TabStripModel::ADD_ACTIVE
                          : TabStripModel::ADD_NONE;
@@ -155,8 +158,8 @@
     bool from_session_restore) {
   std::unique_ptr<WebContents> web_contents = CreateRestoredTab(
       browser, navigations, selected_navigation, extension_app_id,
-      from_last_session, session_storage_namespace, user_agent_override, false,
-      from_session_restore);
+      from_last_session, base::TimeTicks(), session_storage_namespace,
+      user_agent_override, false, from_session_restore);
   WebContents* raw_web_contents = web_contents.get();
 
   // ReplaceWebContentsAt won't animate in the restoration, so manually do the
diff --git a/chrome/browser/ui/browser_tabrestore.h b/chrome/browser/ui/browser_tabrestore.h
index be28dcd..8311ed21 100644
--- a/chrome/browser/ui/browser_tabrestore.h
+++ b/chrome/browser/ui/browser_tabrestore.h
@@ -34,7 +34,9 @@
 // contains the string being used as the user agent for all of the tab's
 // navigations when the regular user agent is overridden. If
 // |from_session_restore| is true, the restored tab is created by session
-// restore. Returns the WebContents of the restored tab.
+// restore. |last_active_time| is the value to use to indicate the last time the
+// WebContents was made active, if this is left default initialized then the
+// creation time will be used. Returns the WebContents of the restored tab.
 content::WebContents* AddRestoredTab(
     Browser* browser,
     const std::vector<sessions::SerializedNavigationEntry>& navigations,
@@ -44,6 +46,7 @@
     bool select,
     bool pin,
     bool from_last_session,
+    base::TimeTicks last_active_time,
     content::SessionStorageNamespace* storage_namespace,
     const std::string& user_agent_override,
     bool from_session_restore);
diff --git a/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.cc b/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.cc
index 15f35f3..7fcf55ee 100644
--- a/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.cc
+++ b/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.cc
@@ -18,17 +18,18 @@
 
 namespace {
 
-MediaRouterActionController* GetActionController(WebContents* web_contents) {
+MediaRouterUIService* GetMediaRouterUIService(WebContents* web_contents) {
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
   // TODO(crbug.com/826091): Move MRUIService to c/b/ui/media_router/.
-  return MediaRouterUIService::Get(profile)->action_controller();
+  return MediaRouterUIService::Get(profile);
 }
 
 }  // namespace
 
-MediaRouterDialogControllerImplBase::~MediaRouterDialogControllerImplBase() =
-    default;
+MediaRouterDialogControllerImplBase::~MediaRouterDialogControllerImplBase() {
+  media_router_ui_service_->RemoveObserver(this);
+}
 
 void MediaRouterDialogControllerImplBase::SetMediaRouterAction(
     const base::WeakPtr<MediaRouterAction>& action) {
@@ -36,18 +37,22 @@
 }
 
 void MediaRouterDialogControllerImplBase::CreateMediaRouterDialog() {
-  // The |action_controller_| must be notified after |action_| to avoid a UI
+  if (!GetActionController())
+    return;
+
+  // The |GetActionController_| must be notified after |action_| to avoid a UI
   // bug in which the drop shadow is drawn in an incorrect position.
   if (action_)
     action_->OnDialogShown();
-  action_controller_->OnDialogShown();
+  GetActionController()->OnDialogShown();
 }
 
 void MediaRouterDialogControllerImplBase::Reset() {
   if (IsShowingMediaRouterDialog()) {
     if (action_)
       action_->OnDialogHidden();
-    action_controller_->OnDialogHidden();
+    if (GetActionController())
+      GetActionController()->OnDialogHidden();
   }
   MediaRouterDialogController::Reset();
 }
@@ -55,8 +60,9 @@
 MediaRouterDialogControllerImplBase::MediaRouterDialogControllerImplBase(
     WebContents* web_contents)
     : MediaRouterDialogController(web_contents),
-      action_controller_(GetActionController(web_contents)) {
-  DCHECK(action_controller_);
+      media_router_ui_service_(GetMediaRouterUIService(web_contents)) {
+  DCHECK(media_router_ui_service_);
+  media_router_ui_service_->AddObserver(this);
 }
 
 void MediaRouterDialogControllerImplBase::InitializeMediaRouterUI(
@@ -72,4 +78,14 @@
   }
 }
 
+void MediaRouterDialogControllerImplBase::OnServiceDisabled() {
+  CloseMediaRouterDialog();
+  Reset();
+}
+
+MediaRouterActionController*
+MediaRouterDialogControllerImplBase::GetActionController() {
+  return media_router_ui_service_->action_controller();
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h b/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h
index ee418cd..8179e5b 100644
--- a/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h
+++ b/chrome/browser/ui/media_router/media_router_dialog_controller_impl_base.h
@@ -7,9 +7,9 @@
 
 #include "base/macros.h"
 #include "chrome/browser/media/router/media_router_dialog_controller.h"
+#include "chrome/browser/ui/webui/media_router/media_router_ui_service.h"
 
 class MediaRouterAction;
-class MediaRouterActionController;
 
 namespace media_router {
 
@@ -17,7 +17,8 @@
 
 // The base class for desktop implementations of MediaRouterDialogController.
 // This class is not thread safe and must be called on the UI thread.
-class MediaRouterDialogControllerImplBase : public MediaRouterDialogController {
+class MediaRouterDialogControllerImplBase : public MediaRouterDialogController,
+                                            MediaRouterUIService::Observer {
  public:
   ~MediaRouterDialogControllerImplBase() override;
 
@@ -43,6 +44,13 @@
   void InitializeMediaRouterUI(MediaRouterUIBase* media_router_ui);
 
  private:
+  // MediaRouterUIService::Observer:
+  void OnServiceDisabled() override;
+
+  // MediaRouterActionController is responsible for showing and hiding the
+  // toolbar action. It's owned by MediaRouterUIService and it may be nullptr.
+  MediaRouterActionController* GetActionController();
+
   // |action_| refers to the MediaRouterAction on the toolbar, rather than
   // overflow menu. A MediaRouterAction is always created for the toolbar
   // first. Any subsequent creations for the overflow menu will not be set as
@@ -52,9 +60,9 @@
   // when the overflow menu is opened and destroyed when the menu is closed.
   base::WeakPtr<MediaRouterAction> action_;
 
-  // |action_controller_| is responsible for showing and hiding the toolbar
-  // action. It's owned by MediaRouterUIService, which outlives |this|.
-  MediaRouterActionController* const action_controller_;
+  // |media_router_ui_service_| Service which provides
+  // MediaRouterActionController. It outlives |this|.
+  MediaRouterUIService* const media_router_ui_service_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaRouterDialogControllerImplBase);
 };
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
index 249207e..1996756 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.cc
@@ -584,8 +584,8 @@
   if (app_window()->IsForcedFullscreen())
     return false;
 
-  // Always use immersive mode in a public session.
-  if (profiles::IsPublicSession())
+  // Always use immersive mode in a public session in fullscreen state.
+  if (profiles::IsPublicSession() && IsFullscreen())
     return true;
 
   // Always use immersive mode when fullscreen is set by the OS.
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
index 6f372de..3d34a9e6 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash.h
@@ -127,6 +127,8 @@
                            ImmersiveModeFullscreenRestoreType);
   FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshBrowserTest,
                            NoImmersiveModeWhenForcedFullscreen);
+  FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshBrowserTest,
+                           PublicSessionImmersiveMode);
   FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshInteractiveTest,
                            NoImmersiveOrBubbleOutsidePublicSessionWindow);
   FRIEND_TEST_ALL_PREFIXES(ChromeNativeAppWindowViewsAuraAshInteractiveTest,
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_browsertest.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_browsertest.cc
index 4c32545..3b4b669 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_browsertest.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_aura_ash_browsertest.cc
@@ -12,6 +12,8 @@
 #include "ui/base/ui_base_types.h"
 #include "ui/wm/core/window_util.h"
 
+#include "chromeos/login/login_state.h"
+
 class ChromeNativeAppWindowViewsAuraAshBrowserTest
     : public extensions::PlatformAppBrowserTest {
  public:
@@ -145,3 +147,24 @@
   tablet_mode_controller->FlushForTesting();
   EXPECT_FALSE(window->immersive_fullscreen_controller_->IsEnabled());
 }
+
+// Make sure a normal window is not in immersive mode, and uses
+// immersive in fullscreen.
+IN_PROC_BROWSER_TEST_F(ChromeNativeAppWindowViewsAuraAshBrowserTest,
+                       PublicSessionImmersiveMode) {
+  chromeos::LoginState::Get()->SetLoggedInState(
+      chromeos::LoginState::LOGGED_IN_ACTIVE,
+      chromeos::LoginState::LOGGED_IN_USER_PUBLIC_ACCOUNT);
+
+  extensions::AppWindow* app_window = CreateTestAppWindow("{}");
+  auto* window = static_cast<ChromeNativeAppWindowViewsAuraAsh*>(
+      GetNativeAppWindowForAppWindow(app_window));
+  ASSERT_TRUE(window != nullptr);
+  ASSERT_TRUE(window->immersive_fullscreen_controller_.get() != nullptr);
+  EXPECT_FALSE(window->immersive_fullscreen_controller_->IsEnabled());
+
+  app_window->SetFullscreen(extensions::AppWindow::FULLSCREEN_TYPE_HTML_API,
+                            true);
+
+  EXPECT_TRUE(window->immersive_fullscreen_controller_->IsEnabled());
+}
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.cc b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
index db68efa3..7b2b1054 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
@@ -22,6 +22,7 @@
 #include "components/account_id/account_id.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
+#include "net/base/network_change_notifier.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/text/bytes_formatting.h"
@@ -117,15 +118,25 @@
 
 bool CrostiniInstallerView::Accept() {
   DCHECK_EQ(state_, State::PROMPT);
+
   state_ = State::INSTALL_START;
   profile_->GetPrefs()->SetBoolean(crostini::prefs::kCrostiniEnabled, true);
   GetWidget()->UpdateWindowTitle();
 
   progress_bar_ = new views::ProgressBar();
   AddChildView(progress_bar_);
-
   StepProgress();
 
+  // HandleError needs the |progress_bar_|, so we delay our Offline check until
+  // it exists.
+  if (net::NetworkChangeNotifier::IsOffline()) {
+    const base::string16 device_type = ui::GetChromeOSDeviceName();
+    HandleError(l10n_util::GetStringFUTF16(IDS_CROSTINI_INSTALLER_OFFLINE_ERROR,
+                                           app_name_, device_type),
+                SetupResult::kErrorOffline);
+    return false;  // should not close the dialog.
+  }
+
   // Kick off the Crostini Restart sequence. We will be added as an observer.
   restart_id_ = crostini::CrostiniManager::GetInstance()->RestartCrostini(
       profile_, kCrostiniDefaultVmName, kCrostiniDefaultContainerName,
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.h b/chrome/browser/ui/views/crostini/crostini_installer_view.h
index 29280aebe..c707d9fe 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view.h
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view.h
@@ -39,6 +39,7 @@
     kErrorCreatingDiskImage = 5,
     kErrorStartingTermina = 6,
     kErrorStartingContainer = 7,
+    kErrorOffline = 8,
     kCount
   };
 
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
index 70e4ec8..a17daf3 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
@@ -8,6 +8,8 @@
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/chrome_browser_main.h"
+#include "chrome/browser/chrome_browser_main_extra_parts.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
@@ -23,9 +25,45 @@
 #include "chromeos/dbus/fake_concierge_client.h"
 #include "components/crx_file/id_util.h"
 #include "components/prefs/pref_service.h"
+#include "net/base/mock_network_change_notifier.h"
+#include "net/base/network_change_notifier_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/window/dialog_client_view.h"
 
+// ChromeBrowserMainExtraParts used to install a MockNetworkChangeNotifier.
+class ChromeBrowserMainExtraPartsNetFactoryInstaller
+    : public ChromeBrowserMainExtraParts {
+ public:
+  ChromeBrowserMainExtraPartsNetFactoryInstaller() = default;
+  ~ChromeBrowserMainExtraPartsNetFactoryInstaller() override {
+    // |network_change_notifier_| needs to be destroyed before |net_installer_|.
+    network_change_notifier_.reset();
+  }
+
+  net::test::MockNetworkChangeNotifier* network_change_notifier() {
+    return network_change_notifier_.get();
+  }
+
+  // ChromeBrowserMainExtraParts:
+  void PreEarlyInitialization() override {}
+  void PostMainMessageLoopStart() override {
+    ASSERT_TRUE(net::NetworkChangeNotifier::HasNetworkChangeNotifier());
+    net_installer_ =
+        std::make_unique<net::NetworkChangeNotifier::DisableForTest>();
+    network_change_notifier_ =
+        std::make_unique<net::test::MockNetworkChangeNotifier>();
+    network_change_notifier_->SetConnectionType(
+        net::NetworkChangeNotifier::CONNECTION_WIFI);
+  }
+
+ private:
+  std::unique_ptr<net::test::MockNetworkChangeNotifier>
+      network_change_notifier_;
+  std::unique_ptr<net::NetworkChangeNotifier::DisableForTest> net_installer_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsNetFactoryInstaller);
+};
+
 class CrostiniInstallerViewBrowserTest : public DialogBrowserTest {
  public:
   class WaitingFakeConciergeClient : public chromeos::FakeConciergeClient {
@@ -64,6 +102,15 @@
     test::GetAppListClient()->ActivateItem(kCrostiniTerminalId, 0);
   }
 
+  // BrowserTestBase:
+  void CreatedBrowserMainParts(
+      content::BrowserMainParts* browser_main_parts) override {
+    ChromeBrowserMainParts* chrome_browser_main_parts =
+        static_cast<ChromeBrowserMainParts*>(browser_main_parts);
+    extra_parts_ = new ChromeBrowserMainExtraPartsNetFactoryInstaller();
+    chrome_browser_main_parts->AddParts(extra_parts_);
+  }
+
   void SetUp() override {
     scoped_feature_list_.InitAndEnableFeature(
         features::kExperimentalCrostiniUI);
@@ -89,7 +136,9 @@
 
  protected:
   // Owned by chromeos::DBusThreadManager
-  WaitingFakeConciergeClient* waiting_fake_concierge_client_;
+  WaitingFakeConciergeClient* waiting_fake_concierge_client_ = nullptr;
+  // Owned by content::Browser
+  ChromeBrowserMainExtraPartsNetFactoryInstaller* extra_parts_ = nullptr;
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -132,6 +181,36 @@
       1);
 }
 
+IN_PROC_BROWSER_TEST_F(CrostiniInstallerViewBrowserTest, InstallFlow_Offline) {
+  base::HistogramTester histogram_tester;
+  extra_parts_->network_change_notifier()->SetConnectionType(
+      net::NetworkChangeNotifier::CONNECTION_NONE);
+
+  ShowUi("default");
+  EXPECT_NE(nullptr, ActiveView());
+  EXPECT_EQ(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
+            ActiveView()->GetDialogButtons());
+
+  EXPECT_TRUE(HasAcceptButton());
+  EXPECT_TRUE(HasCancelButton());
+
+  ActiveView()->GetDialogClientView()->AcceptWindow();
+  EXPECT_FALSE(ActiveView()->GetWidget()->IsClosed());
+  EXPECT_FALSE(HasAcceptButton());
+  EXPECT_TRUE(HasCancelButton());
+
+  ActiveView()->GetDialogClientView()->CancelWindow();
+  EXPECT_TRUE(ActiveView()->GetWidget()->IsClosed());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(nullptr, ActiveView());
+
+  histogram_tester.ExpectBucketCount(
+      "Crostini.SetupResult",
+      static_cast<base::HistogramBase::Sample>(
+          CrostiniInstallerView::SetupResult::kErrorOffline),
+      1);
+}
+
 IN_PROC_BROWSER_TEST_F(CrostiniInstallerViewBrowserTest, Cancel) {
   base::HistogramTester histogram_tester;
 
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service.cc b/chrome/browser/ui/webui/media_router/media_router_ui_service.cc
index 99597ff..ac86bed 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_service.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_service.cc
@@ -7,16 +7,27 @@
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/media_router/media_router_ui_service_factory.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "components/user_prefs/user_prefs.h"
 
 namespace media_router {
 
 MediaRouterUIService::MediaRouterUIService(Profile* profile)
-    : action_controller_(new MediaRouterActionController(profile)) {}
+    : profile_(profile),
+      profile_pref_registrar_(std::make_unique<PrefChangeRegistrar>()) {
+  profile_pref_registrar_->Init(profile->GetPrefs());
+  profile_pref_registrar_->Add(
+      ::prefs::kEnableMediaRouter,
+      base::BindRepeating(&MediaRouterUIService::ConfigureService,
+                          base::Unretained(this)));
+  ConfigureService();
+}
 
 MediaRouterUIService::~MediaRouterUIService() {}
 
 void MediaRouterUIService::Shutdown() {
-  action_controller_.reset();
+  DisableService();
 }
 
 // static
@@ -28,4 +39,27 @@
   return action_controller_.get();
 }
 
+void MediaRouterUIService::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void MediaRouterUIService::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void MediaRouterUIService::ConfigureService() {
+  if (!MediaRouterEnabled(profile_)) {
+    DisableService();
+  } else if (!action_controller_ && MediaRouterEnabled(profile_)) {
+    action_controller_ =
+        std::make_unique<MediaRouterActionController>(profile_);
+  }
+}
+
+void MediaRouterUIService::DisableService() {
+  for (auto& observer : observers_)
+    observer.OnServiceDisabled();
+  action_controller_.reset();
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service.h b/chrome/browser/ui/webui/media_router/media_router_ui_service.h
index 5a4c333..789b147 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_service.h
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_service.h
@@ -6,9 +6,11 @@
 
 #include <memory>
 
+#include "base/observer_list.h"
 #include "chrome/browser/ui/toolbar/media_router_action_controller.h"
 #include "components/keyed_service/core/keyed_service.h"
 
+class PrefChangeRegistrar;
 class Profile;
 
 namespace media_router {
@@ -17,6 +19,11 @@
 // for the Media Router toolbar action.
 class MediaRouterUIService : public KeyedService {
  public:
+  class Observer {
+   public:
+    virtual void OnServiceDisabled() = 0;
+  };
+
   explicit MediaRouterUIService(Profile* profile);
   ~MediaRouterUIService() override;
 
@@ -27,10 +34,20 @@
 
   virtual MediaRouterActionController* action_controller();
 
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
  private:
   friend class MediaRouterUIBrowserTest;
 
+  void ConfigureService();
+  void DisableService();
+
+  Profile* profile_;
   std::unique_ptr<MediaRouterActionController> action_controller_;
+  std::unique_ptr<PrefChangeRegistrar> profile_pref_registrar_;
+
+  base::ObserverList<Observer> observers_;
 
   DISALLOW_COPY_AND_ASSIGN(MediaRouterUIService);
 };
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.cc b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.cc
index bcd926c..98c0f0e 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/webui/media_router/media_router_ui_service_factory.h"
 
 #include "chrome/browser/media/router/media_router_factory.h"
-#include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h"
 #include "chrome/browser/ui/webui/media_router/media_router_ui_service.h"
@@ -47,9 +46,7 @@
 
 KeyedService* MediaRouterUIServiceFactory::BuildServiceInstanceFor(
     BrowserContext* context) const {
-  return MediaRouterEnabled(context)
-             ? new MediaRouterUIService(Profile::FromBrowserContext(context))
-             : nullptr;
+  return new MediaRouterUIService(Profile::FromBrowserContext(context));
 }
 
 bool MediaRouterUIServiceFactory::ServiceIsCreatedWithBrowserContext() const {
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.h b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.h
index b5328f5..10d5761 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.h
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory.h
@@ -28,7 +28,9 @@
   friend struct base::DefaultSingletonTraits<MediaRouterUIServiceFactory>;
   FRIEND_TEST_ALL_PREFIXES(MediaRouterUIServiceFactoryUnitTest, CreateService);
   FRIEND_TEST_ALL_PREFIXES(MediaRouterUIServiceFactoryUnitTest,
-                           DoNotCreateServiceWhenDisabled);
+                           DoNotCreateActionControllerWhenDisabled);
+  FRIEND_TEST_ALL_PREFIXES(MediaRouterUIServiceFactoryUnitTest,
+                           DisablingMediaRouting);
 
   MediaRouterUIServiceFactory();
   ~MediaRouterUIServiceFactory() override;
diff --git a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc
index f66afd7..22005542 100644
--- a/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc
+++ b/chrome/browser/ui/webui/media_router/media_router_ui_service_factory_unittest.cc
@@ -16,8 +16,19 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+
+class MockMediaRouterUIServiceObserver
+    : public media_router::MediaRouterUIService::Observer {
+ public:
+  MOCK_METHOD0(OnServiceDisabled, void());
+};
+
+}  // namespace
+
 namespace media_router {
 
 class MediaRouterUIServiceFactoryUnitTest : public testing::Test {
@@ -59,12 +70,34 @@
   ASSERT_TRUE(service->action_controller());
 }
 
-TEST_F(MediaRouterUIServiceFactoryUnitTest, DoNotCreateServiceWhenDisabled) {
+TEST_F(MediaRouterUIServiceFactoryUnitTest,
+       DoNotCreateActionControllerWhenDisabled) {
   profile_->GetTestingPrefService()->SetManagedPref(
       prefs::kEnableMediaRouter, std::make_unique<base::Value>(false));
-  EXPECT_EQ(nullptr,
-            MediaRouterUIServiceFactory::GetInstance()->BuildServiceInstanceFor(
-                profile_.get()));
+  std::unique_ptr<MediaRouterUIService> service(
+      static_cast<MediaRouterUIService*>(
+          MediaRouterUIServiceFactory::GetInstance()->BuildServiceInstanceFor(
+              profile_.get())));
+  ASSERT_TRUE(service);
+  EXPECT_EQ(nullptr, service->action_controller());
+}
+
+TEST_F(MediaRouterUIServiceFactoryUnitTest, DisablingMediaRouting) {
+  std::unique_ptr<MediaRouterUIService> service(
+      static_cast<MediaRouterUIService*>(
+          MediaRouterUIServiceFactory::GetInstance()->BuildServiceInstanceFor(
+              profile_.get())));
+  ASSERT_TRUE(service);
+  ASSERT_TRUE(service->action_controller());
+
+  MockMediaRouterUIServiceObserver mock_observer;
+  service->AddObserver(&mock_observer);
+  EXPECT_CALL(mock_observer, OnServiceDisabled).Times(testing::Exactly(1));
+
+  profile_->GetTestingPrefService()->SetManagedPref(
+      prefs::kEnableMediaRouter, std::make_unique<base::Value>(false));
+  EXPECT_EQ(nullptr, service->action_controller());
+  service->RemoveObserver(&mock_observer);
 }
 
 }  // namespace media_router
diff --git a/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc b/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc
index be5aedb2..77e5b23 100644
--- a/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/privet_printer_handler.cc
@@ -19,10 +19,10 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/printing/cloud_print/privet_constants.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/webui/print_preview/print_preview_utils.h"
 #include "chrome/common/chrome_switches.h"
-#include "components/signin/core/browser/signin_manager.h"
+#include "services/identity/public/cpp/identity_manager.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace {
@@ -251,11 +251,11 @@
   privet_local_print_operation_->SetPageSize(page_size);
   privet_local_print_operation_->SetData(print_data);
 
-  SigninManagerBase* signin_manager =
-      SigninManagerFactory::GetForProfileIfExists(profile_);
-  if (signin_manager) {
+  identity::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfileIfExists(profile_);
+  if (identity_manager) {
     privet_local_print_operation_->SetUsername(
-        signin_manager->GetAuthenticatedAccountInfo().email);
+        identity_manager->GetPrimaryAccountInfo().email);
   }
 
   privet_local_print_operation_->Start();
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 62a8059..2846f79 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -2322,6 +2322,10 @@
      IDS_SETTINGS_SITE_SETTINGS_SITE_CLEAR_STORAGE_CONFIRMATION},
     {"siteSettingsSiteClearStorageDialogTitle",
      IDS_SETTINGS_SITE_SETTINGS_SITE_CLEAR_STORAGE_DIALOG_TITLE},
+    {"siteSettingsSiteGroupResetDialogTitle",
+     IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_RESET_DIALOG_TITLE},
+    {"siteSettingsSiteGroupResetConfirmation",
+     IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_RESET_CONFIRMATION},
     {"siteSettingsSiteResetAll", IDS_SETTINGS_SITE_SETTINGS_SITE_RESET_ALL},
     {"siteSettingsSiteResetConfirmation",
      IDS_SETTINGS_SITE_SETTINGS_SITE_RESET_CONFIRMATION},
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
index 1024ca6f..ab54d09 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
@@ -120,10 +120,6 @@
   const std::string& email = auth_data->FindKey("email")->GetString();
   CHECK(!email.empty());
 
-  // TODO(sinhak): Get URL Context from Account Manager when that is available.
-  net::URLRequestContextGetter* request_context =
-      g_browser_process->system_request_context();
-
   // TODO(sinhak): Do not depend on Profile unnecessarily.
   Profile* profile = Profile::FromWebUI(web_ui());
 
@@ -136,7 +132,8 @@
           ->GetAccountManager(profile->GetPath().value());
 
   // SigninHelper deletes itself after its work is done.
-  new SigninHelper(profile, account_manager, request_context, gaia_id, email,
+  new SigninHelper(profile, account_manager,
+                   account_manager->GetUrlRequestContext(), gaia_id, email,
                    auth_code);
 }
 
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 5e47d1e..d95817ea 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <utility>
 
+#include "base/base64.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/location.h"
@@ -25,10 +26,16 @@
 #include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 
+#if defined(OS_MACOSX)
+#include "device/fido/mac/credential_metadata.h"
+#endif
+
 namespace {
 
 // Returns true iff |relying_party_id| is listed in the
@@ -52,6 +59,20 @@
 
 }  // namespace
 
+#if defined(OS_MACOSX)
+static const char kWebAuthnTouchIdMetadataSecretPrefName[] =
+    "webauthn.touchid.metadata_secret";
+#endif
+
+// static
+void ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+#if defined(OS_MACOSX)
+  registry->RegisterStringPref(kWebAuthnTouchIdMetadataSecretPrefName,
+                               std::string());
+#endif
+}
+
 ChromeAuthenticatorRequestDelegate::ChromeAuthenticatorRequestDelegate(
     content::RenderFrameHost* render_frame_host)
     : render_frame_host_(render_frame_host), weak_ptr_factory_(this) {}
@@ -75,6 +96,12 @@
   return weak_ptr_factory_.GetWeakPtr();
 }
 
+content::BrowserContext* ChromeAuthenticatorRequestDelegate::browser_context()
+    const {
+  return content::WebContents::FromRenderFrameHost(render_frame_host())
+      ->GetBrowserContext();
+}
+
 void ChromeAuthenticatorRequestDelegate::DidStartRequest() {
 #if !defined(OS_ANDROID)
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -94,10 +121,7 @@
     const std::string& relying_party_id) {
   // If the RP ID is listed in the policy, signal that individual attestation is
   // permitted.
-  auto* web_contents =
-      content::WebContents::FromRenderFrameHost(render_frame_host());
-  auto* browser_context = web_contents->GetBrowserContext();
-  return IsWebauthnRPIDListedInEnterprisePolicy(browser_context,
+  return IsWebauthnRPIDListedInEnterprisePolicy(browser_context(),
                                                 relying_party_id);
 }
 
@@ -109,10 +133,7 @@
   // of prompting.
   std::move(callback).Run(true);
 #else
-  auto* web_contents =
-      content::WebContents::FromRenderFrameHost(render_frame_host());
-  auto* browser_context = web_contents->GetBrowserContext();
-  if (IsWebauthnRPIDListedInEnterprisePolicy(browser_context,
+  if (IsWebauthnRPIDListedInEnterprisePolicy(browser_context(),
                                              relying_party_id)) {
     std::move(callback).Run(true);
     return;
@@ -121,8 +142,8 @@
   // This does not use content::PermissionManager because that only works with
   // content settings, while this permission is a non-persisted, per-attested-
   // registration consent.
-  auto* permission_request_manager =
-      PermissionRequestManager::FromWebContents(web_contents);
+  auto* permission_request_manager = PermissionRequestManager::FromWebContents(
+      content::WebContents::FromRenderFrameHost(render_frame_host()));
   if (!permission_request_manager) {
     std::move(callback).Run(false);
     return;
@@ -157,7 +178,7 @@
 }
 
 #if defined(OS_MACOSX)
-base::StringPiece
+std::string
 ChromeAuthenticatorRequestDelegate::TouchIdAuthenticatorKeychainAccessGroup() {
   // This exact value must be whitelisted in the keychain-access-group section
   // of the entitlements plist file with which Chrome is signed. Note that
@@ -168,6 +189,21 @@
 }
 #endif
 
+#if defined(OS_MACOSX)
+std::string ChromeAuthenticatorRequestDelegate::TouchIdMetadataSecret() {
+  PrefService* prefs =
+      Profile::FromBrowserContext(browser_context())->GetPrefs();
+  std::string key = prefs->GetString(kWebAuthnTouchIdMetadataSecretPrefName);
+  if (key.empty() || !base::Base64Decode(key, &key)) {
+    key = device::fido::mac::CredentialMetadata::GenerateRandomSecret();
+    std::string encoded_key;
+    base::Base64Encode(key, &encoded_key);
+    prefs->SetString(kWebAuthnTouchIdMetadataSecretPrefName, encoded_key);
+  }
+  return key;
+}
+#endif
+
 void ChromeAuthenticatorRequestDelegate::OnModelDestroyed() {
   DCHECK(weak_dialog_model_);
   weak_dialog_model_ = nullptr;
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
index 936fd20..9a22815 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
@@ -11,7 +11,12 @@
 #include "content/public/browser/authenticator_request_client_delegate.h"
 
 namespace content {
+class BrowserContext;
 class RenderFrameHost;
+}  // namespace content
+
+namespace user_prefs {
+class PrefRegistrySyncable;
 }
 
 class AuthenticatorRequestDialogModel;
@@ -20,6 +25,8 @@
     : public content::AuthenticatorRequestClientDelegate,
       public AuthenticatorRequestDialogModel::Observer {
  public:
+  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
   // The |render_frame_host| must outlive this instance.
   explicit ChromeAuthenticatorRequestDelegate(
       content::RenderFrameHost* render_frame_host);
@@ -27,10 +34,16 @@
 
   base::WeakPtr<ChromeAuthenticatorRequestDelegate> AsWeakPtr();
 
+#if defined(OS_MACOSX)
+  std::string TouchIdAuthenticatorKeychainAccessGroup() override;
+  std::string TouchIdMetadataSecret() override;
+#endif
+
  private:
   content::RenderFrameHost* render_frame_host() const {
     return render_frame_host_;
   }
+  content::BrowserContext* browser_context() const;
 
   // content::AuthenticatorRequestClientDelegate:
   void DidStartRequest() override;
@@ -40,9 +53,6 @@
       const std::string& relying_party_id,
       base::OnceCallback<void(bool)> callback) override;
   bool IsFocused() override;
-#if defined(OS_MACOSX)
-  base::StringPiece TouchIdAuthenticatorKeychainAccessGroup() override;
-#endif
 
   // AuthenticatorRequestDialogModel::Observer:
   void OnModelDestroyed() override;
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
new file mode 100644
index 0000000..65bf984b
--- /dev/null
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
@@ -0,0 +1,56 @@
+// Copyright 2018 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/webauthn/chrome_authenticator_request_delegate.h"
+
+#include "build/build_config.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+
+class ChromeAuthenticatorRequestDelegateTest
+    : public ChromeRenderViewHostTestHarness {};
+
+#if defined(OS_MACOSX)
+TEST_F(ChromeAuthenticatorRequestDelegateTest, TouchIdMetadataSecret) {
+  ChromeAuthenticatorRequestDelegate delegate(main_rfh());
+  std::string secret = delegate.TouchIdMetadataSecret();
+  EXPECT_EQ(secret.size(), 32u);
+  EXPECT_EQ(secret, delegate.TouchIdMetadataSecret());
+}
+
+TEST_F(ChromeAuthenticatorRequestDelegateTest,
+       TouchIdMetadataSecret_EqualForSameProfile) {
+  // Different delegates on the same BrowserContext (Profile) should return the
+  // same secret.
+  EXPECT_EQ(
+      ChromeAuthenticatorRequestDelegate(main_rfh()).TouchIdMetadataSecret(),
+      ChromeAuthenticatorRequestDelegate(main_rfh()).TouchIdMetadataSecret());
+}
+
+TEST_F(ChromeAuthenticatorRequestDelegateTest,
+       TouchIdMetadataSecret_NotEqualForDifferentProfiles) {
+  // Different profiles have different secrets. (No way to reset
+  // browser_context(), so we have to create our own.)
+  auto browser_context = base::WrapUnique(CreateBrowserContext());
+  auto web_contents =
+      WebContentsTester::CreateTestWebContents(browser_context.get(), nullptr);
+  EXPECT_NE(
+      ChromeAuthenticatorRequestDelegate(main_rfh()).TouchIdMetadataSecret(),
+      ChromeAuthenticatorRequestDelegate(web_contents->GetMainFrame())
+          .TouchIdMetadataSecret());
+  // Ensure this second secret is actually valid.
+  EXPECT_EQ(32u,
+            ChromeAuthenticatorRequestDelegate(web_contents->GetMainFrame())
+                .TouchIdMetadataSecret()
+                .size());
+}
+#endif
+
+}  // namespace
+}  // namespace content
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 8a82f5c..c36abac 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -266,7 +266,6 @@
     "//gpu/config",
     "//ipc",
     "//media",
-    "//mojo/edk",
     "//mojo/public/cpp/bindings",
     "//pdf:buildflags",
     "//ppapi/buildflags",
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index a5dae45..153fab6 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -57,8 +57,3 @@
   # FIXME - refactor code and remove these dependencies
   "+chrome/installer/util",
 ]
-specific_include_rules = {
-  "service_process_util.*": [
-    "+mojo/edk/embedder",
-  ],
-}
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 7c16607..0b5e0e7 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -224,6 +224,10 @@
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
+// Makes Flash plugin permissions persistent only through the current session.
+const base::Feature kEnableEphemeralFlashPermission{
+    "EnableEphemeralFlashPermission", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // An experimental way of showing app banners, which has modal banners and gives
 // developers more control over when to show them.
 const base::Feature kExperimentalAppBanners {
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index a95a379..a1cc4ac 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -118,6 +118,8 @@
 extern const base::Feature kDownloadsLocationChange;
 #endif
 
+extern const base::Feature kEnableEphemeralFlashPermission;
+
 extern const base::Feature kExperimentalAppBanners;
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/common/chrome_paths_internal.h b/chrome/common/chrome_paths_internal.h
index ab812935..e15cd68 100644
--- a/chrome/common/chrome_paths_internal.h
+++ b/chrome/common/chrome_paths_internal.h
@@ -69,13 +69,6 @@
 // in the .app at Contents/Versions/w.x.y.z.
 base::FilePath GetVersionedDirectory();
 
-// This overrides the directory returned by |GetVersionedDirectory()|, to be
-// used when |GetVersionedDirectory()| can't automatically determine the proper
-// location. This is the case when the browser didn't load itself but by, e.g.,
-// the app mode loader. This should be called before |ChromeMain()|. This takes
-// ownership of the object |path| and the caller must not delete it.
-void SetOverrideVersionedDirectory(const base::FilePath* path);
-
 // Most of the application is further contained within the framework.  The
 // framework bundle is located within the versioned directory at a specific
 // path.  The only components in the versioned directory not included in the
diff --git a/chrome/common/chrome_paths_mac.mm b/chrome/common/chrome_paths_mac.mm
index 406298b..40a4d69 100644
--- a/chrome/common/chrome_paths_mac.mm
+++ b/chrome/common/chrome_paths_mac.mm
@@ -20,8 +20,6 @@
 
 namespace {
 
-const base::FilePath* g_override_versioned_directory = NULL;
-
 // Return a retained (NOT autoreleased) NSBundle* as the internal
 // implementation of chrome::OuterAppBundle(), which should be the only
 // caller.
@@ -152,9 +150,6 @@
 }
 
 base::FilePath GetVersionedDirectory() {
-  if (g_override_versioned_directory)
-    return *g_override_versioned_directory;
-
   // Start out with the path to the running executable.
   base::FilePath path;
   base::PathService::Get(base::FILE_EXE, &path);
@@ -177,13 +172,6 @@
   return path;
 }
 
-void SetOverrideVersionedDirectory(const base::FilePath* path) {
-  if (path != g_override_versioned_directory) {
-    delete g_override_versioned_directory;
-    g_override_versioned_directory = path;
-  }
-}
-
 base::FilePath GetFrameworkBundlePath() {
   // It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really
   // slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index a1d192a..a70812e7 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -292,6 +292,10 @@
 // Enables Domain Reliability Monitoring.
 const char kEnableDomainReliability[] = "enable-domain-reliability";
 
+// Makes Flash plugin permissions persistent only through the current session.
+const char kEnableEphemeralFlashPermission[] =
+    "enable-ephemeral-flash-permission";
+
 // Enables logging for extension activity.
 const char kEnableExtensionActivityLogging[] =
     "enable-extension-activity-logging";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 8112233..91c6e14 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -96,6 +96,7 @@
 extern const char kEnableDeviceDiscoveryNotifications[];
 extern const char kEnableDevToolsExperiments[];
 extern const char kEnableDomainReliability[];
+extern const char kEnableEphemeralFlashPermission[];
 extern const char kEnableExtensionActivityLogging[];
 extern const char kEnableExtensionActivityLogTesting[];
 extern const char kEnableFastUnload[];
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
index 1388ded..d435138 100644
--- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -151,7 +151,7 @@
 
   void EnableManualGenerationFallback() {
     scoped_feature_list_.InitAndEnableFeature(
-        password_manager::features::kEnableManualFallbacksGeneration);
+        password_manager::features::kManualFallbacksGeneration);
   }
 
   FakeContentPasswordManagerDriver fake_driver_;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 22980b8e..868b84f 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2651,6 +2651,7 @@
     "../browser/vr/metrics/session_metrics_helper_unittest.cc",
     "../browser/vr/vr_tab_helper_unittest.cc",
     "../browser/webauthn/authenticator_request_scheduler_unittest.cc",
+    "../browser/webauthn/chrome_authenticator_request_delegate_unittest.cc",
     "../browser/webshare/share_target_pref_helper_unittest.cc",
     "../browser/win/chrome_elf_init_unittest.cc",
     "../browser/win/jumplist_file_util_unittest.cc",
diff --git a/chrome/test/data/chromeos/wallpaper_manager/unit_tests/api_mock.js b/chrome/test/data/chromeos/wallpaper_manager/unit_tests/api_mock.js
index fe2dd56d..19f34ef0 100644
--- a/chrome/test/data/chromeos/wallpaper_manager/unit_tests/api_mock.js
+++ b/chrome/test/data/chromeos/wallpaper_manager/unit_tests/api_mock.js
@@ -286,6 +286,10 @@
     },
     getImagesInfo: function(collectionId, callback) {
       callback([{imageUrl: TestConstants.wallpaperUrl}]);
+    },
+    getSurpriseMeImage: function(collectionId, resumeToken, callback) {
+      callback(
+          {imageUrl: TestConstants.wallpaperUrl}, null /*nextResumeToken=*/);
     }
   },
   runtime: {lastError: null},
diff --git a/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html b/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html
index bf31dfc13..c0fb5fa 100644
--- a/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html
+++ b/chrome/test/data/vr/e2e_test_files/html/test_device_capabilities_match_expectations.html
@@ -29,6 +29,8 @@
         "hammerhead": android_expectation,  // Nexus 5
         "marlin": android_expectation,  // Pixel XL
         "sailfish": android_expectation,  // Pixel
+        "taimen": android_expectation,  // Pixel 2 XL
+        "walleye": android_expectation,  // Pixel 2
         "VR Orientation Device": { // GVR-less Magic Window implementation
           "isPresenting": false,
           "capabilities": {
diff --git a/chrome/test/data/webui/print_preview/destination_list_test.js b/chrome/test/data/webui/print_preview/destination_list_test.js
new file mode 100644
index 0000000..51a0bea
--- /dev/null
+++ b/chrome/test/data/webui/print_preview/destination_list_test.js
@@ -0,0 +1,124 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('destination_list_test', function() {
+  /** @enum {string} */
+  const TestNames = {
+    FilterDestinations: 'FilterDestinations',
+  };
+
+  const suiteName = 'DestinationListTest';
+
+  suite(suiteName, function() {
+    /** @type {?PrintPreviewDestinationListElement} */
+    let list = null;
+
+    /** @override */
+    setup(function() {
+      // Create destinations
+      const destinations = [
+        new print_preview.Destination(
+            'id1', print_preview.DestinationType.LOCAL,
+            print_preview.DestinationOrigin.LOCAL, 'One', true /* isRecent */,
+            print_preview.DestinationConnectionStatus.ONLINE,
+            {description: 'ABC'}),
+        new print_preview.Destination(
+            'id2', print_preview.DestinationType.LOCAL,
+            print_preview.DestinationOrigin.LOCAL, 'Two', true /* isRecent */,
+            print_preview.DestinationConnectionStatus.ONLINE,
+            {description: 'XYZ'}),
+        new print_preview.Destination(
+            'id3', print_preview.DestinationType.GOOGLE,
+            print_preview.DestinationOrigin.COOKIES, 'Three',
+            true /* isRecent */,
+            print_preview.DestinationConnectionStatus.ONLINE,
+            {description: 'ABC', tags: ['__cp__location=123']}),
+        new print_preview.Destination(
+            'id4', print_preview.DestinationType.GOOGLE,
+            print_preview.DestinationOrigin.COOKIES, 'Four',
+            true /* isRecent */,
+            print_preview.DestinationConnectionStatus.ONLINE,
+            {description: 'XYZ', tags: ['__cp__location=123']}),
+        new print_preview.Destination(
+            'id5', print_preview.DestinationType.GOOGLE,
+            print_preview.DestinationOrigin.COOKIES, 'Five',
+            true /* isRecent */,
+            print_preview.DestinationConnectionStatus.ONLINE,
+            {description: 'XYZ', tags: ['__cp__location=123']})
+      ];
+
+      // Set up list
+      list = document.createElement('print-preview-destination-list');
+      document.body.appendChild(list);
+
+      list.hasActionLink = true;
+      list.loadingDestinations = false;
+      list.title = 'test';
+      list.searchQuery = null;
+      list.destinations = destinations;
+      Polymer.dom.flush();
+    });
+
+    // Tests that the list correctly shows and hides destinations based on the
+    // value of the search query.
+    test(assert(TestNames.FilterDestinations), function() {
+      const items = list.shadowRoot.querySelectorAll(
+          'print-preview-destination-list-item');
+      const noMatchHint = list.$$('.no-destinations-message');
+      const total = list.$$('.total');
+
+      // Query is initialized to null. All items are shown and the hint is
+      // hidden. The total displays since there are 5 destinations.
+      items.forEach(item => assertFalse(item.hidden));
+      assertTrue(noMatchHint.hidden);
+      assertFalse(total.hidden);
+      assertTrue(total.textContent.includes('5'));
+
+      // Searching for "e" should show "One", "Three", and "Five".
+      list.searchQuery = /(e)/i;
+      items.forEach(
+          (item, index) => assertEquals(index == 1 || index == 3, item.hidden));
+      assertTrue(noMatchHint.hidden);
+      assertTrue(total.hidden);
+
+      // Searching for "ABC" should show "One" and "Three".
+      list.searchQuery = /(ABC)/i;
+      items.forEach(
+          (item, index) => assertEquals(index != 0 && index != 2, item.hidden));
+      assertTrue(noMatchHint.hidden);
+      assertTrue(total.hidden);
+
+      // Searching for "F" should show "Four" and "Five"
+      list.searchQuery = /(F)/i;
+      items.forEach((item, index) => assertEquals(index < 3, item.hidden));
+      assertTrue(noMatchHint.hidden);
+      assertTrue(total.hidden);
+
+      // Searching for UVW should show no destinations and display the "no
+      // match" hint.
+      list.searchQuery = /(UVW)/i;
+      items.forEach(item => assertTrue(item.hidden));
+      assertFalse(noMatchHint.hidden);
+      assertTrue(total.hidden);
+
+      // Searching for 123 should show destinations "Three", "Four", and "Five".
+      list.searchQuery = /(123)/i;
+      items.forEach((item, index) => assertEquals(index < 2, item.hidden));
+      assertTrue(noMatchHint.hidden);
+      assertTrue(total.hidden);
+
+      // Clearing the query restores the original state.
+      list.searchQuery = /()/i;
+      items.forEach(item => assertFalse(item.hidden));
+      assertTrue(noMatchHint.hidden);
+      assertFalse(total.hidden);
+      assertTrue(total.textContent.includes('5'));
+    });
+  });
+
+  return {
+    suiteName: suiteName,
+    TestNames: TestNames,
+  };
+});
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
index 3db6cf1..d051f5e9 100644
--- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -821,3 +821,26 @@
 TEST_F('PrintPreviewAdvancedItemTest', 'QueryOption', function() {
   this.runMochaTest(advanced_item_test.TestNames.QueryOption);
 });
+
+PrintPreviewDestinationListTest = class extends NewPrintPreviewTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://print/new/destination_list.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      'destination_list_test.js',
+    ]);
+  }
+
+  /** @override */
+  get suiteName() {
+    return destination_list_test.suiteName;
+  }
+};
+
+TEST_F('PrintPreviewDestinationListTest', 'FilterDestinations', function() {
+  this.runMochaTest(destination_list_test.TestNames.FilterDestinations);
+});
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 487055c..1468b82 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -974,7 +974,9 @@
 
   /** @override */
   extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([
+    '../test_browser_proxy.js',
     'test_util.js',
+    'test_site_settings_prefs_browser_proxy.js',
     'site_entry_tests.js',
   ]),
 };
diff --git a/chrome/test/data/webui/settings/site_details_permission_tests.js b/chrome/test/data/webui/settings/site_details_permission_tests.js
index f4ff0e8..ecc421b4 100644
--- a/chrome/test/data/webui/settings/site_details_permission_tests.js
+++ b/chrome/test/data/webui/settings/site_details_permission_tests.js
@@ -244,6 +244,7 @@
   test('info string correct for drm disabled source', function() {
     const origin = 'https://www.example.com';
     testElement.category = settings.ContentSettingsTypes.PROTECTED_CONTENT;
+    testElement.$.details.hidden = false;
     testElement.site = {
       origin: origin,
       embeddingOrigin: origin,
diff --git a/chrome/test/data/webui/settings/site_details_tests.js b/chrome/test/data/webui/settings/site_details_tests.js
index 5d0a9e5..9706e1cb 100644
--- a/chrome/test/data/webui/settings/site_details_tests.js
+++ b/chrome/test/data/webui/settings/site_details_tests.js
@@ -158,7 +158,7 @@
       loadTimeData.overrideValues(loadTimeDataOverride);
       testElement = createSiteDetails('https://foo.com:443');
       assertEquals(
-          numContentSettings + 1, testElement.getCategoryList_().length);
+          numContentSettings + 1, testElement.getCategoryList().length);
 
       // Check for setting = off at the end to ensure that the setting does
       // not carry over for the next iteration.
@@ -166,7 +166,7 @@
           [optionalSiteDetailsContentSettingsTypes[contentSetting]] = false;
       loadTimeData.overrideValues(loadTimeDataOverride);
       testElement = createSiteDetails('https://foo.com:443');
-      assertEquals(numContentSettings, testElement.getCategoryList_().length);
+      assertEquals(numContentSettings, testElement.getCategoryList().length);
     }
   });
 
@@ -320,7 +320,7 @@
     // Accepting the dialog will make a call to setOriginPermissions.
     return browserProxy.whenCalled('setOriginPermissions').then((args) => {
       assertEquals(testElement.origin, args[0]);
-      assertDeepEquals(testElement.getCategoryList_(), args[1]);
+      assertDeepEquals(testElement.getCategoryList(), args[1]);
       assertEquals(settings.ContentSetting.DEFAULT, args[2]);
     });
   });
diff --git a/chrome/test/data/webui/settings/site_entry_tests.js b/chrome/test/data/webui/settings/site_entry_tests.js
index b1511b7..70224e2 100644
--- a/chrome/test/data/webui/settings/site_entry_tests.js
+++ b/chrome/test/data/webui/settings/site_entry_tests.js
@@ -22,6 +22,12 @@
   ]);
 
   /**
+   * The mock proxy object to use during test.
+   * @type {TestSiteSettingsPrefsBrowserProxy}
+   */
+  let browserProxy;
+
+  /**
    * A site list element created before each test.
    * @type {SiteList}
    */
@@ -35,6 +41,9 @@
 
   // Initialize a site-list before each test.
   setup(function() {
+    browserProxy = new TestSiteSettingsPrefsBrowserProxy();
+    settings.SiteSettingsPrefsBrowserProxyImpl.instance_ = browserProxy;
+
     PolymerTest.clearBody();
     testElement = document.createElement('site-entry');
     assertTrue(!!testElement);
@@ -106,4 +115,49 @@
         TEST_MULTIPLE_SITE_GROUP.origins[1],
         settings.getQueryParameters().get('site'));
   });
+
+  test('with single origin does not show overflow menu', function() {
+    testElement.siteGroup = TEST_SINGLE_SITE_GROUP;
+    Polymer.dom.flush();
+    const overflowMenuButton = testElement.$.overflowMenuButton;
+    assertTrue(overflowMenuButton.closest('.row-aligned').hidden);
+  });
+
+  test(
+      'with multiple origins can reset settings via overflow menu', function() {
+        testElement.siteGroup = TEST_MULTIPLE_SITE_GROUP;
+        Polymer.dom.flush();
+        const overflowMenuButton = testElement.$.overflowMenuButton;
+        assertFalse(overflowMenuButton.closest('.row-aligned').hidden);
+
+        // Open the reset settings dialog and make sure both cancelling the
+        // action and resetting all permissions work.
+        const menuItems =
+            testElement.getOverflowMenu_().querySelectorAll('.dropdown-item');
+        ['cancel-button', 'action-button'].forEach(buttonType => {
+          // Test clicking on the overflow menu button opens the menu.
+          assertFalse(testElement.getOverflowMenu_().open);
+          MockInteractions.tap(overflowMenuButton);
+          assertTrue(testElement.getOverflowMenu_().open);
+
+          // Open the reset settings dialog and tap the |buttonType| button.
+          assertFalse(testElement.$.confirmResetSettings.open);
+          MockInteractions.tap(menuItems[0]);
+          assertTrue(testElement.$.confirmResetSettings.open);
+          const actionButtonList =
+              testElement.$.confirmResetSettings.getElementsByClassName(
+                  buttonType);
+          assertEquals(1, actionButtonList.length);
+          MockInteractions.tap(actionButtonList[0]);
+
+          // Check the dialog and overflow menu are now both closed.
+          assertFalse(testElement.$.confirmResetSettings.open);
+          assertFalse(testElement.getOverflowMenu_().open);
+        });
+
+        // Ensure a call was made to setOriginPermissions for each origin.
+        assertEquals(
+            TEST_MULTIPLE_SITE_GROUP.origins.length,
+            browserProxy.getCallCount('setOriginPermissions'));
+      });
 });
diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc
index 878deb4..2a69925a 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_browsertest.cc
@@ -27,6 +27,8 @@
 #include "chrome/common/media_router/issue.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/policy_constants.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -184,6 +186,13 @@
   test_navigation_observer_.reset();
 }
 
+void MediaRouterIntegrationBrowserTest::SetUpInProcessBrowserTestFixture() {
+  MediaRouterBaseBrowserTest::SetUpInProcessBrowserTestFixture();
+  EXPECT_CALL(provider_, IsInitializationComplete(testing::_))
+      .WillRepeatedly(testing::Return(true));
+  policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+}
+
 void MediaRouterIntegrationBrowserTest::ExecuteJavaScriptAPI(
     WebContents* web_contents,
     const std::string& script) {
@@ -683,6 +692,16 @@
   ExecuteJavaScriptAPI(web_contents, kTerminateSessionScript);
 }
 
+void MediaRouterIntegrationBrowserTest::SetEnableMediaRouter(bool enable) {
+  policy::PolicyMap policy;
+  policy.Set(policy::key::kEnableMediaRouter, policy::POLICY_LEVEL_MANDATORY,
+             policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+             std::make_unique<base::Value>(enable), nullptr);
+  provider_.UpdateChromePolicy(policy);
+  base::RunLoop loop;
+  loop.RunUntilIdle();
+}
+
 void MediaRouterIntegrationBrowserTest::RunReconnectSessionSameTabTest() {
   WebContents* web_contents = StartSessionWithTestPageAndChooseSink();
   CheckSessionValidity(web_contents);
diff --git a/chrome/test/media_router/media_router_integration_browsertest.h b/chrome/test/media_router/media_router_integration_browsertest.h
index b8b7e2b..db7f3e6 100644
--- a/chrome/test/media_router/media_router_integration_browsertest.h
+++ b/chrome/test/media_router/media_router_integration_browsertest.h
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/media_router/media_cast_mode.h"
 #include "chrome/browser/ui/toolbar/media_router_action.h"
 #include "chrome/test/media_router/media_router_base_browsertest.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 
@@ -31,6 +32,7 @@
  protected:
   // InProcessBrowserTest Overrides
   void TearDownOnMainThread() override;
+  void SetUpInProcessBrowserTestFixture() override;
 
   // MediaRouterBaseBrowserTest Overrides
   void ParseCommandLine() override;
@@ -208,6 +210,9 @@
   // same tab.
   void RunReconnectSessionSameTabTest();
 
+  // Sets whether media router is enabled.
+  void SetEnableMediaRouter(bool enable);
+
   std::string receiver() const { return receiver_; }
 
   // Enabled features
@@ -222,6 +227,7 @@
       base::FilePath::StringPieceType relative_path) const;
 
   std::unique_ptr<content::TestNavigationObserver> test_navigation_observer_;
+  policy::MockConfigurationPolicyProvider provider_;
 
   // Fields
   std::string receiver_;
diff --git a/chrome/test/media_router/media_router_integration_ui_browsertest.cc b/chrome/test/media_router/media_router_integration_ui_browsertest.cc
index a2373c06f..6e87923 100644
--- a/chrome/test/media_router/media_router_integration_ui_browsertest.cc
+++ b/chrome/test/media_router/media_router_integration_ui_browsertest.cc
@@ -7,6 +7,8 @@
 #include "base/files/file_util.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/media_router/media_router_dialog_controller_webui_impl.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "content/public/test/browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -171,4 +173,43 @@
   WaitUntilRouteCreated();
 }
 
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
+                       PRE_OpenDialogAfterEnablingMediaRouting) {
+  SetEnableMediaRouter(false);
+}
+
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
+                       OpenDialogAfterEnablingMediaRouting) {
+  // Enable media routing and open media router dialog.
+  SetEnableMediaRouter(true);
+  OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  OpenMRDialog(web_contents);
+
+  MediaRouterDialogControllerWebUIImpl* controller =
+      MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
+          web_contents);
+  ASSERT_TRUE(controller->IsShowingMediaRouterDialog());
+}
+
+IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest,
+                       DisableMediaRoutingWhenDialogIsOpened) {
+  // Open media router dialog.
+  OpenTestPage(FILE_PATH_LITERAL("basic_test.html"));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  OpenMRDialog(web_contents);
+
+  MediaRouterDialogControllerWebUIImpl* controller =
+      MediaRouterDialogControllerWebUIImpl::GetOrCreateForWebContents(
+          web_contents);
+  ASSERT_TRUE(controller->IsShowingMediaRouterDialog());
+
+  // Disable media routing.
+  SetEnableMediaRouter(false);
+
+  ASSERT_FALSE(controller->IsShowingMediaRouterDialog());
+}
+
 }  // namespace media_router
diff --git a/chromeos/account_manager/account_manager.cc b/chromeos/account_manager/account_manager.cc
index 0b15c2d..1f5094c6 100644
--- a/chromeos/account_manager/account_manager.cc
+++ b/chromeos/account_manager/account_manager.cc
@@ -352,6 +352,12 @@
 }
 
 net::URLRequestContextGetter* AccountManager::GetUrlRequestContext() {
+  // LSTs on Chrome are not channel/token bound for now and hence we can use
+  // the system request context.
+  // Note that we cannot use the Profile's request context since
+  // |AccountManager| acts outside the scope of Profiles.
+  // TODO(sinhak): Create a new |URLRequestContext| for |AccountManager| which
+  // conforms to token binding when those details are finalized.
   DCHECK(request_context_);
   return request_context_;
 }
diff --git a/chromeos/components/tether/message_transfer_operation.cc b/chromeos/components/tether/message_transfer_operation.cc
index db18b87..b3d4689 100644
--- a/chromeos/components/tether/message_transfer_operation.cc
+++ b/chromeos/components/tether/message_transfer_operation.cc
@@ -18,6 +18,8 @@
 
 namespace {
 
+const char kTetherFeature[] = "magic_tether";
+
 cryptauth::RemoteDeviceRefList RemoveDuplicatesFromVector(
     const cryptauth::RemoteDeviceRefList& remote_devices) {
   cryptauth::RemoteDeviceRefList updated_remote_devices;
@@ -148,7 +150,7 @@
               this, remote_device,
               secure_channel_client_->ListenForConnectionFromDevice(
                   remote_device, *device_sync_client_->GetLocalDeviceMetadata(),
-                  "tether", connection_priority_));
+                  kTetherFeature, connection_priority_));
     } else {
       connection_manager_->RegisterRemoteDevice(
           remote_device.GetDeviceId(), request_id_, connection_priority_);
diff --git a/chromeos/components/tether/message_transfer_operation_unittest.cc b/chromeos/components/tether/message_transfer_operation_unittest.cc
index 63553cb..d128e7d 100644
--- a/chromeos/components/tether/message_transfer_operation_unittest.cc
+++ b/chromeos/components/tether/message_transfer_operation_unittest.cc
@@ -34,6 +34,8 @@
 
 const uint32_t kTestTimeoutSeconds = 5;
 
+const char kTetherFeature[] = "magic_tether";
+
 // A test double for MessageTransferOperation is needed because
 // MessageTransferOperation has pure virtual methods which must be overridden in
 // order to create a concrete instantiation of the class.
@@ -224,6 +226,15 @@
     VerifyOperationStartedAndFinished(false /* has_started */,
                                       false /* has_finished */);
     operation_->Initialize();
+
+    if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
+      for (const auto* arguments :
+           fake_secure_channel_client_
+               ->last_listen_for_connection_request_arguments_list()) {
+        EXPECT_EQ(kTetherFeature, arguments->feature);
+      }
+    }
+
     VerifyOperationStartedAndFinished(true /* has_started */,
                                       false /* has_finished */);
   }
diff --git a/chromeos/services/secure_channel/ble_connection_manager_impl.cc b/chromeos/services/secure_channel/ble_connection_manager_impl.cc
index 03e8018..1fbbe56 100644
--- a/chromeos/services/secure_channel/ble_connection_manager_impl.cc
+++ b/chromeos/services/secure_channel/ble_connection_manager_impl.cc
@@ -240,10 +240,6 @@
   // connections to the same device can interfere with each other.
   PauseConnectionAttemptsToDevice(remote_device_id);
 
-  // Observe the channel to be notified of when either the channel authenticates
-  // successfully or faces BLE instability and disconnects.
-  secure_channel->AddObserver(this);
-
   if (base::ContainsKey(remote_device_id_to_secure_channel_map_,
                         remote_device_id)) {
     PA_LOG(ERROR) << "BleConnectionManager::OnReceivedAdvertisement(): A new "
@@ -254,6 +250,8 @@
     NOTREACHED();
   }
 
+  cryptauth::SecureChannel* secure_channel_raw = secure_channel.get();
+
   PA_LOG(INFO) << "BleConnectionManager::OnReceivedAdvertisement(): Connection "
                << "established; starting authentication process. Remote device "
                << "ID: "
@@ -262,6 +260,11 @@
                << ", Connection role: " << connection_role;
   remote_device_id_to_secure_channel_map_[remote_device_id] =
       std::make_pair(std::move(secure_channel), connection_role);
+
+  // Observe the channel to be notified of when either the channel authenticates
+  // successfully or faces BLE instability and disconnects.
+  secure_channel_raw->AddObserver(this);
+  secure_channel_raw->Initialize();
 }
 
 void BleConnectionManagerImpl::PauseConnectionAttemptsToDevice(
diff --git a/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc b/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc
index ba37d4b..08a90fc4 100644
--- a/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc
+++ b/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc
@@ -538,7 +538,7 @@
 
     cryptauth::FakeSecureChannel* last_created_secure_channel =
         fake_secure_channel_factory_->last_created_instance();
-    EXPECT_TRUE(last_created_secure_channel);
+    EXPECT_TRUE(last_created_secure_channel->was_initialized());
     return last_created_secure_channel;
   }
 
diff --git a/components/autofill/core/browser/autofill_handler.cc b/components/autofill/core/browser/autofill_handler.cc
index 89a5c7a..931de9f 100644
--- a/components/autofill/core/browser/autofill_handler.cc
+++ b/components/autofill/core/browser/autofill_handler.cc
@@ -4,11 +4,22 @@
 
 #include "components/autofill/core/browser/autofill_handler.h"
 
+#include "base/containers/adapters.h"
+#include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/common/autofill_data_validation.h"
+#include "components/autofill/core/common/signatures_util.h"
 #include "ui/gfx/geometry/rect_f.h"
 
 namespace autofill {
 
+namespace {
+
+// Set a conservative upper bound on the number of forms we are willing to
+// cache, simply to prevent unbounded memory consumption.
+const size_t kMaxFormCacheSize = 100;
+
+}  // namespace
+
 using base::TimeTicks;
 
 AutofillHandler::AutofillHandler(AutofillDriver* driver) : driver_(driver) {}
@@ -92,4 +103,67 @@
   driver_->SendFormDataToRenderer(query_id, action, data);
 }
 
+bool AutofillHandler::FindCachedForm(const FormData& form,
+                                     FormStructure** form_structure) const {
+  // Find the FormStructure that corresponds to |form|.
+  // Scan backward through the cached |form_structures_|, as updated versions of
+  // forms are added to the back of the list, whereas original versions of these
+  // forms might appear toward the beginning of the list.  The communication
+  // protocol with the crowdsourcing server does not permit us to discard the
+  // original versions of the forms.
+  *form_structure = nullptr;
+  const auto& form_signature = autofill::CalculateFormSignature(form);
+  for (auto& cur_form : base::Reversed(form_structures_)) {
+    if (cur_form->form_signature() == form_signature || *cur_form == form) {
+      *form_structure = cur_form.get();
+
+      // The same form might be cached with multiple field counts: in some
+      // cases, non-autofillable fields are filtered out, whereas in other cases
+      // they are not.  To avoid thrashing the cache, keep scanning until we
+      // find a cached version with the same number of fields, if there is one.
+      if (cur_form->field_count() == form.fields.size())
+        break;
+    }
+  }
+
+  if (!(*form_structure))
+    return false;
+
+  return true;
+}
+
+bool AutofillHandler::ParseForm(const FormData& form,
+                                const FormStructure* cached_form,
+                                FormStructure** parsed_form_structure) {
+  DCHECK(parsed_form_structure);
+  if (form_structures_.size() >= kMaxFormCacheSize)
+    return false;
+
+  auto form_structure = std::make_unique<FormStructure>(form);
+  form_structure->ParseFieldTypesFromAutocompleteAttributes();
+  if (!form_structure->ShouldBeParsed()) {
+    return false;
+  }
+
+  if (cached_form) {
+    // We need to keep the server data if available. We need to use them while
+    // determining the heuristics.
+    form_structure->RetrieveFromCache(*cached_form,
+                                      /*apply_is_autofilled=*/true,
+                                      /*only_server_and_autofill_state=*/true);
+  }
+
+  // Ownership is transferred to |form_structures_| which maintains it until
+  // the manager is Reset() or destroyed. It is safe to use references below
+  // as long as receivers don't take ownership.
+  form_structure->set_form_parsed_timestamp(TimeTicks::Now());
+  form_structures_.push_back(std::move(form_structure));
+  *parsed_form_structure = form_structures_.back().get();
+  return true;
+}
+
+void AutofillHandler::Reset() {
+  form_structures_.clear();
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_handler.h b/components/autofill/core/browser/autofill_handler.h
index b6592b1..fdef9d50 100644
--- a/components/autofill/core/browser/autofill_handler.h
+++ b/components/autofill/core/browser/autofill_handler.h
@@ -23,6 +23,7 @@
 
 struct FormData;
 struct FormFieldData;
+class FormStructure;
 
 // This class defines the interface should be implemented by autofill
 // implementation in browser side to interact with AutofillDriver.
@@ -100,13 +101,21 @@
   virtual void SelectFieldOptionsDidChange(const FormData& form) = 0;
 
   // Resets cache.
-  virtual void Reset() = 0;
+  virtual void Reset();
 
   // Send the form |data| to renderer for the specified |action|.
   void SendFormDataToRenderer(int query_id,
                               AutofillDriver::RendererFormDataAction action,
                               const FormData& data);
 
+  // Returns the number of forms this Autofill handler is aware of.
+  size_t NumFormsDetected() const { return form_structures_.size(); }
+
+  // Returns the present form structures seen by Autofill handler.
+  const std::vector<std::unique_ptr<FormStructure>>& form_structures() {
+    return form_structures_;
+  }
+
  protected:
   AutofillHandler(AutofillDriver* driver);
 
@@ -139,7 +148,27 @@
 
   AutofillDriver* driver() { return driver_; }
 
+  // Fills |form_structure| cached element corresponding to |form|.
+  // Returns false if the cached element was not found.
+  bool FindCachedForm(const FormData& form,
+                      FormStructure** form_structure) const WARN_UNUSED_RESULT;
+
+  std::vector<std::unique_ptr<FormStructure>>* mutable_form_structures() {
+    return &form_structures_;
+  }
+
+  // Parses the |form| with the server data retrieved from the |cached_form|
+  // (if any), and writes it to the |parse_form_structure|. Adds the
+  // |parse_form_structure| to the |form_structures_|. Returns true if the form
+  // is parsed.
+  bool ParseForm(const FormData& form,
+                 const FormStructure* cached_form,
+                 FormStructure** parsed_form_structure);
+
  private:
+  // Our copy of the form data.
+  std::vector<std::unique_ptr<FormStructure>> form_structures_;
+
   // Provides driver-level context to the shared code of the component. Must
   // outlive this object.
   AutofillDriver* driver_;
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 3c820e3..be6431b 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -65,7 +65,6 @@
 #include "components/autofill/core/common/form_data_predictions.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
-#include "components/autofill/core/common/signatures_util.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "components/security_state/core/security_state.h"
@@ -89,10 +88,6 @@
 
 const size_t kMaxRecentFormSignaturesToRemember = 3;
 
-// Set a conservative upper bound on the number of forms we are willing to
-// cache, simply to prevent unbounded memory consumption.
-const size_t kMaxFormCacheSize = 100;
-
 // Time to wait, in ms, after a dynamic form change before triggering a refill.
 // This is used for sites that change multiple things consecutively.
 const size_t kWaitTimeForDynamicFormsMs = 200;
@@ -932,11 +927,6 @@
   return full_card_request_ && full_card_request_->IsGettingFullCard();
 }
 
-const std::vector<std::unique_ptr<FormStructure>>&
-AutofillManager::GetFormStructures() {
-  return form_structures_;
-}
-
 payments::FullCardRequest* AutofillManager::GetOrCreateFullCardRequest() {
   if (!full_card_request_) {
     full_card_request_.reset(new payments::FullCardRequest(
@@ -973,7 +963,7 @@
   FormStructure* cached_form = nullptr;
   ignore_result(FindCachedForm(form, &cached_form));
 
-  if (!ParseForm(form, cached_form, &form_structure))
+  if (!ParseFormInternal(form, cached_form, &form_structure))
     return;
 
   if (ShouldTriggerRefill(*form_structure))
@@ -988,7 +978,7 @@
   // the end of the list (and reverse the resulting pointer vector).
   std::vector<FormStructure*> queried_forms;
   for (const std::string& signature : base::Reversed(form_signatures)) {
-    for (auto& cur_form : base::Reversed(form_structures_)) {
+    for (auto& cur_form : base::Reversed(form_structures())) {
       if (cur_form->FormSignatureAsStr() == signature) {
         queried_forms.push_back(cur_form.get());
         break;
@@ -1129,7 +1119,7 @@
   // save a card is shown after page navigation.
   ProcessPendingFormForUpload();
   DCHECK(!pending_form_data_);
-  form_structures_.clear();
+  AutofillHandler::Reset();
   form_interactions_ukm_logger_.reset(
       new AutofillMetrics::FormInteractionsUkmLogger(
           client_->GetUkmRecorder()));
@@ -1429,35 +1419,6 @@
   return submitted_form;
 }
 
-bool AutofillManager::FindCachedForm(const FormData& form,
-                                     FormStructure** form_structure) const {
-  // Find the FormStructure that corresponds to |form|.
-  // Scan backward through the cached |form_structures_|, as updated versions of
-  // forms are added to the back of the list, whereas original versions of these
-  // forms might appear toward the beginning of the list.  The communication
-  // protocol with the crowdsourcing server does not permit us to discard the
-  // original versions of the forms.
-  *form_structure = nullptr;
-  const auto& form_signature = autofill::CalculateFormSignature(form);
-  for (auto& cur_form : base::Reversed(form_structures_)) {
-    if (cur_form->form_signature() == form_signature || *cur_form == form) {
-      *form_structure = cur_form.get();
-
-      // The same form might be cached with multiple field counts: in some
-      // cases, non-autofillable fields are filtered out, whereas in other cases
-      // they are not.  To avoid thrashing the cache, keep scanning until we
-      // find a cached version with the same number of fields, if there is one.
-      if (cur_form->field_count() == form.fields.size())
-        break;
-    }
-  }
-
-  if (!(*form_structure))
-    return false;
-
-  return true;
-}
-
 bool AutofillManager::GetCachedFormAndField(const FormData& form,
                                             const FormFieldData& field,
                                             FormStructure** form_structure,
@@ -1536,7 +1497,7 @@
   // Note: We _must not_ remove the original version of the cached form from
   // the list of |form_structures_|. Otherwise, we break parsing of the
   // crowdsourcing server's response to our query.
-  if (!ParseForm(live_form, cached_form, updated_form))
+  if (!ParseFormInternal(live_form, cached_form, updated_form))
     return false;
 
   // Annotate the updated form with its predicted types.
@@ -1625,7 +1586,7 @@
     const auto parse_form_start_time = TimeTicks::Now();
 
     FormStructure* form_structure = nullptr;
-    if (!ParseForm(form, /*cached_form=*/nullptr, &form_structure))
+    if (!ParseFormInternal(form, /*cached_form=*/nullptr, &form_structure))
       continue;
     DCHECK(form_structure);
 
@@ -1681,7 +1642,7 @@
   // prompt for credit card assisted filling. Upon accepting the infobar, the
   // form will automatically be filled with the user's information through this
   // class' FillCreditCardForm().
-  if (autofill_assistant_.CanShowCreditCardAssist(form_structures_)) {
+  if (autofill_assistant_.CanShowCreditCardAssist(form_structures())) {
     const std::vector<CreditCard*> cards =
         personal_data_->GetCreditCardsToSuggest(
             client_->AreServerCardsSupported());
@@ -1704,37 +1665,16 @@
   }
 }
 
-bool AutofillManager::ParseForm(const FormData& form,
-                                const FormStructure* cached_form,
-                                FormStructure** parsed_form_structure) {
-  DCHECK(parsed_form_structure);
-  if (form_structures_.size() >= kMaxFormCacheSize)
-    return false;
-
-  auto form_structure = std::make_unique<FormStructure>(form);
-  form_structure->ParseFieldTypesFromAutocompleteAttributes();
-  if (!form_structure->ShouldBeParsed()) {
-    return false;
+bool AutofillManager::ParseFormInternal(const FormData& form,
+                                        const FormStructure* cached_form,
+                                        FormStructure** parsed_form_structure) {
+  if (ParseForm(form, cached_form, parsed_form_structure)) {
+    (*parsed_form_structure)
+        ->DetermineHeuristicTypes(client_->GetUkmRecorder(),
+                                  client_->GetUkmSourceId());
+    return true;
   }
-
-  if (cached_form) {
-    // We need to keep the server data if available. We need to use them while
-    // determining the heuristics.
-    form_structure->RetrieveFromCache(*cached_form,
-                                      /*apply_is_autofilled=*/true,
-                                      /*only_server_and_autofill_state=*/true);
-  }
-
-  // Ownership is transferred to |form_structures_| which maintains it until
-  // the manager is Reset() or destroyed. It is safe to use references below
-  // as long as receivers don't take ownership.
-  form_structure->set_form_parsed_timestamp(TimeTicks::Now());
-  form_structures_.push_back(std::move(form_structure));
-  *parsed_form_structure = form_structures_.back().get();
-  (*parsed_form_structure)
-      ->DetermineHeuristicTypes(client_->GetUkmRecorder(),
-                                client_->GetUkmSourceId());
-  return true;
+  return false;
 }
 
 int AutofillManager::BackendIDToInt(const std::string& backend_id) const {
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 6aeb4b7..5766de3 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -29,7 +29,6 @@
 #include "components/autofill/core/browser/card_unmask_delegate.h"
 #include "components/autofill/core/browser/field_filler.h"
 #include "components/autofill/core/browser/form_data_importer.h"
-#include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/form_types.h"
 #include "components/autofill/core/browser/payments/full_card_request.h"
 #include "components/autofill/core/browser/payments/payments_client.h"
@@ -136,9 +135,6 @@
   // Returns true when the Payments card unmask prompt is being displayed.
   bool IsShowingUnmaskPrompt();
 
-  // Returns the present form structures seen by Autofill manager.
-  const std::vector<std::unique_ptr<FormStructure>>& GetFormStructures();
-
   AutofillClient* client() { return client_; }
 
   AutofillDownloadManager* download_manager() {
@@ -206,9 +202,6 @@
   // to be uploadable. Exposed for testing.
   bool ShouldUploadForm(const FormStructure& form);
 
-  // Returns the number of forms this Autofill Manager is aware of.
-  size_t NumFormsDetected() const { return form_structures_.size(); }
-
  protected:
   // Test code should prefer to use this constructor.
   AutofillManager(AutofillDriver* driver,
@@ -267,10 +260,6 @@
                                     const FormFieldData& field,
                                     const gfx::RectF& bounding_box) override;
 
-  std::vector<std::unique_ptr<FormStructure>>* form_structures() {
-    return &form_structures_;
-  }
-
   AutofillMetrics::FormInteractionsUkmLogger* form_interactions_ukm_logger() {
     return form_interactions_ukm_logger_.get();
   }
@@ -338,6 +327,10 @@
     SuppressReason suppress_reason = SuppressReason::kNotSuppressed;
   };
 
+  bool ParseFormInternal(const FormData& form,
+                         const FormStructure* cached_form,
+                         FormStructure** parsed_form_structure);
+
   // AutofillDownloadManager::Observer:
   void OnLoadedServerPredictions(
       std::string response,
@@ -412,11 +405,6 @@
   // or personal data.
   std::unique_ptr<FormStructure> ValidateSubmittedForm(const FormData& form);
 
-  // Fills |form_structure| cached element corresponding to |form|.
-  // Returns false if the cached element was not found.
-  bool FindCachedForm(const FormData& form,
-                      FormStructure** form_structure) const WARN_UNUSED_RESULT;
-
   // Fills |form_structure| and |autofill_field| with the cached elements
   // corresponding to |form| and |field|.  This might have the side-effect of
   // updating the cache.  Returns false if the |form| is not autofillable, or if
@@ -464,14 +452,6 @@
   // Parses the forms using heuristic matching and querying the Autofill server.
   void ParseForms(const std::vector<FormData>& forms);
 
-  // Parses the |form| with the server data retrieved from the |cached_form|
-  // (if any), and writes it to the |parse_form_structure|. Adds the
-  // |parse_form_structure| to the |form_structures_|. Returns true if the form
-  // is parsed.
-  bool ParseForm(const FormData& form,
-                 const FormStructure* cached_form,
-                 FormStructure** parsed_form_structure);
-
   // If |initial_interaction_timestamp_| is unset or is set to a later time than
   // |interaction_timestamp|, updates the cached timestamp.  The latter check is
   // needed because IPC messages can arrive out of order.
@@ -599,9 +579,6 @@
   // page.
   base::TimeTicks initial_interaction_timestamp_;
 
-  // Our copy of the form data.
-  std::vector<std::unique_ptr<FormStructure>> form_structures_;
-
   // A copy of the currently interacted form data.
   std::unique_ptr<FormData> pending_form_data_;
 
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index 0dfe949..1e2e4d3 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -1683,7 +1683,8 @@
   TestFormStructure* form_structure_ptr = form_structure.get();
   form_structure->DetermineHeuristicTypes(nullptr /* ukm_service */,
                                           0 /* source_id */);
-  autofill_manager_->form_structures()->push_back(std::move(form_structure));
+  autofill_manager_->mutable_form_structures()->push_back(
+      std::move(form_structure));
 
   AutofillQueryResponseContents response;
   // Server response will match with autocomplete.
diff --git a/components/autofill/core/browser/password_generator_fips181.cc b/components/autofill/core/browser/password_generator_fips181.cc
index 9406629..3226576ea 100644
--- a/components/autofill/core/browser/password_generator_fips181.cc
+++ b/components/autofill/core/browser/password_generator_fips181.cc
@@ -50,6 +50,15 @@
   return num_lower_case && num_upper_case && num_digits;
 }
 
+// Password generation function for unit testing, default to nullptr.
+// If not null, ForceFixPassword() will also always use |kMinDigit| as the digit
+// replacement, instead of choosing randomly.
+int (*g_test_override_generator)(char* word,
+                                 char* hypenated_word,
+                                 unsigned short minlen,
+                                 unsigned short maxlen,
+                                 unsigned int pass_mode) = nullptr;
+
 }  // namespace
 
 namespace autofill {
@@ -66,7 +75,13 @@
   for (std::string::reverse_iterator iter = password->rbegin();
        iter != password->rend(); ++iter) {
     if (islower(*iter)) {
-      *iter = base::RandInt(kMinDigit, kMaxDigit);
+      // Tests will use |PasswordGeneratorFips181::SetGeneratorForTest| to put a
+      // non-random generator in |g_test_override_generator|. To eliminate the
+      // other source of randomness, always fix the chosen digit to |kMinDigit|
+      // in such case.
+      *iter = g_test_override_generator == nullptr
+                  ? base::RandInt(kMinDigit, kMaxDigit)
+                  : kMinDigit;
       break;
     }
   }
@@ -76,6 +91,15 @@
     : password_length_(GetLengthFromHint(max_length, kDefaultPasswordLength)) {}
 PasswordGeneratorFips181::~PasswordGeneratorFips181() {}
 
+void PasswordGeneratorFips181::SetGeneratorForTest(
+    int (*generator)(char* word,
+                     char* hypenated_word,
+                     unsigned short minlen,
+                     unsigned short maxlen,
+                     unsigned int pass_mode)) {
+  g_test_override_generator = generator;
+}
+
 std::string PasswordGeneratorFips181::Generate() const {
   char password[255];
   char unused_hypenated_password[255];
@@ -83,12 +107,13 @@
   // No special characters included for now.
   unsigned int mode = S_NB | S_CL | S_SL;
 
-  // Generate the password by gen_pron_pass(), if it is not conforming then
-  // force fix it.
-  gen_pron_pass(password, unused_hypenated_password, password_length_,
-                password_length_, mode);
-
+  // Generate the password and fix afterwards if needed.
+  auto generator =
+      g_test_override_generator ? g_test_override_generator : gen_pron_pass;
+  generator(password, unused_hypenated_password, password_length_,
+            password_length_, mode);
   std::string str_password(password);
+
   if (VerifyPassword(str_password))
     return str_password;
 
diff --git a/components/autofill/core/browser/password_generator_fips181.h b/components/autofill/core/browser/password_generator_fips181.h
index f5569a9..732cc73 100644
--- a/components/autofill/core/browser/password_generator_fips181.h
+++ b/components/autofill/core/browser/password_generator_fips181.h
@@ -37,6 +37,15 @@
   // Not thread safe.
   std::string Generate() const;
 
+  // This method allows to substitute a replacement for the fips181 method
+  // gen_pron_pass, used by the generator to generate the password. This is
+  // useful in tests, for providing a deterministic generator.
+  static void SetGeneratorForTest(int (*generator)(char* word,
+                                                   char* hypenated_word,
+                                                   unsigned short minlen,
+                                                   unsigned short maxlen,
+                                                   unsigned int pass_mode));
+
  private:
   // Unit test also need to access |kDefaultPasswordLength|.
   static const int kDefaultPasswordLength;
diff --git a/components/autofill/core/browser/password_generator_fips181_unittest.cc b/components/autofill/core/browser/password_generator_fips181_unittest.cc
index be0bae32..6188aa7 100644
--- a/components/autofill/core/browser/password_generator_fips181_unittest.cc
+++ b/components/autofill/core/browser/password_generator_fips181_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <stddef.h>
+#include <string.h>
 
 #include <locale>
 
@@ -28,44 +29,82 @@
   EXPECT_GT(num_digits, 0) << password;
 }
 
+const char* g_password_text = nullptr;
+
+int GenerateForTest(char* word,
+                    char* hypenated_word,
+                    unsigned short minlen,
+                    unsigned short maxlen,
+                    unsigned int pass_mode) {
+  EXPECT_LE(minlen, maxlen);
+  EXPECT_TRUE(word);
+  EXPECT_TRUE(hypenated_word);
+  EXPECT_TRUE(g_password_text) << "Set g_password_text before every call";
+  strncpy(word, g_password_text, maxlen);
+  g_password_text = nullptr;
+  // Resize password to |maxlen|.
+  word[maxlen] = '\0';
+  EXPECT_GE(strlen(word), minlen)
+      << "Make sure to provide enough characters in g_password_text";
+  return static_cast<int>(strlen(word));
+}
+
+class PasswordGeneratorFips181Test : public ::testing::Test {
+ public:
+  PasswordGeneratorFips181Test() {
+    autofill::PasswordGeneratorFips181::SetGeneratorForTest(GenerateForTest);
+  }
+  ~PasswordGeneratorFips181Test() override {
+    autofill::PasswordGeneratorFips181::SetGeneratorForTest(nullptr);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PasswordGeneratorFips181Test);
+};
+
 }  // namespace
 
 namespace autofill {
 
-TEST(PasswordGeneratorFips181Test, PasswordLength) {
+TEST_F(PasswordGeneratorFips181Test, PasswordLength) {
   PasswordGeneratorFips181 pg1(10);
+  g_password_text = "Aa12345678901234567890";
   std::string password = pg1.Generate();
   EXPECT_EQ(password.size(), 10u);
 
   PasswordGeneratorFips181 pg2(-1);
+  g_password_text = "Aa12345678901234567890";
   password = pg2.Generate();
   EXPECT_EQ(
       password.size(),
       static_cast<size_t>(PasswordGeneratorFips181::kDefaultPasswordLength));
 
   PasswordGeneratorFips181 pg3(100);
+  g_password_text = "Aa12345678901234567890";
   password = pg3.Generate();
   EXPECT_EQ(
       password.size(),
       static_cast<size_t>(PasswordGeneratorFips181::kDefaultPasswordLength));
 }
 
-TEST(PasswordGeneratorFips181Test, PasswordPattern) {
-  PasswordGeneratorFips181 pg(12);
-  std::string password = pg.Generate();
-  CheckPasswordCorrectness(password);
+TEST_F(PasswordGeneratorFips181Test, PasswordPattern) {
+  PasswordGeneratorFips181 pg1(12);
+  g_password_text = "012345678jkl";
+  std::string password1 = pg1.Generate();
+  CheckPasswordCorrectness(password1);
+
+  PasswordGeneratorFips181 pg2(12);
+  g_password_text = "abcDEFGHIJKL";
+  std::string password2 = pg2.Generate();
+  CheckPasswordCorrectness(password2);
+
+  PasswordGeneratorFips181 pg3(12);
+  g_password_text = "abcdefghijkl";
+  std::string password3 = pg3.Generate();
+  CheckPasswordCorrectness(password3);
 }
 
-TEST(PasswordGeneratorFips181Test, Printable) {
-  PasswordGeneratorFips181 pg(12);
-  std::string password = pg.Generate();
-  for (size_t i = 0; i < password.size(); i++) {
-    // Make sure that the character is printable.
-    EXPECT_TRUE(isgraph(password[i]));
-  }
-}
-
-TEST(PasswordGeneratorFips181Test, ForceFixPasswordTest) {
+TEST_F(PasswordGeneratorFips181Test, ForceFixPasswordTest) {
   std::string passwords_to_fix[] = {"nonumbersoruppercase",
                                     "nonumbersWithuppercase",
                                     "numbers3Anduppercase", "UmpAwgemHoc"};
diff --git a/components/autofill/core/browser/test_autofill_manager.cc b/components/autofill/core/browser/test_autofill_manager.cc
index fe77aec..467c8825 100644
--- a/components/autofill/core/browser/test_autofill_manager.cc
+++ b/components/autofill/core/browser/test_autofill_manager.cc
@@ -144,11 +144,11 @@
 void TestAutofillManager::AddSeenFormStructure(
     std::unique_ptr<FormStructure> form_structure) {
   form_structure->set_form_parsed_timestamp(base::TimeTicks::Now());
-  form_structures()->push_back(std::move(form_structure));
+  mutable_form_structures()->push_back(std::move(form_structure));
 }
 
 void TestAutofillManager::ClearFormStructures() {
-  form_structures()->clear();
+  mutable_form_structures()->clear();
 }
 
 const std::string TestAutofillManager::GetSubmittedFormSignature() {
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index caa6ce79..d40cee5 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -69,34 +69,32 @@
 #include "net/url_request/url_request_context_getter.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
-using syncer::BackendMigrator;
-using syncer::ClientTagBasedModelTypeProcessor;
 using syncer::DataTypeController;
 using syncer::DataTypeManager;
-using syncer::DataTypeStatusTable;
-using syncer::DeviceInfoSyncBridge;
 using syncer::EngineComponentsFactory;
 using syncer::EngineComponentsFactoryImpl;
-using syncer::JsBackend;
-using syncer::JsController;
-using syncer::JsEventHandler;
-using syncer::ModelSafeRoutingInfo;
-using syncer::ModelType;
-using syncer::ModelTypeSet;
-using syncer::ModelTypeStore;
-using syncer::ProtocolEventObserver;
-using syncer::SyncBackendRegistrar;
-using syncer::SyncClient;
-using syncer::SyncCredentials;
-using syncer::SyncEngine;
-using syncer::SyncManagerFactory;
-using syncer::SyncProtocolError;
-using syncer::WeakHandle;
 
 namespace browser_sync {
 
 namespace {
 
+// The initial state of sync, for the Sync.InitialState histogram. Even if
+// this value is CAN_START, sync startup might fail for reasons that we may
+// want to consider logging in the future, such as a passphrase needed for
+// decryption, or the version of Chrome being too old. This enum is used to
+// back a UMA histogram, and should therefore be treated as append-only.
+enum SyncInitialState {
+  CAN_START,                // Sync can attempt to start up.
+  NOT_SIGNED_IN,            // There is no signed in user.
+  NOT_REQUESTED,            // The user turned off sync.
+  NOT_REQUESTED_NOT_SETUP,  // The user turned off sync and setup completed
+                            // is false. Might indicate a stop-and-clear.
+  NEEDS_CONFIRMATION,       // The user must confirm sync settings.
+  IS_MANAGED,               // Sync is disallowed by enterprise policy.
+  NOT_ALLOWED_BY_PLATFORM,  // Sync is disallowed by the platform.
+  SYNC_INITIAL_STATE_LIMIT
+};
+
 constexpr char kSyncUnrecoverableErrorHistogram[] = "Sync.UnrecoverableErrors";
 
 constexpr base::FilePath::CharType kSyncDataFolderName[] =
@@ -141,7 +139,7 @@
   DataTypeController::TypeMap type_map;
   for (std::unique_ptr<DataTypeController>& controller : controllers) {
     DCHECK(controller);
-    ModelType type = controller->type();
+    syncer::ModelType type = controller->type();
     DCHECK_EQ(0U, type_map.count(type));
     type_map[type] = std::move(controller);
   }
@@ -252,7 +250,7 @@
         local_device_.get(), model_type_store_factory_,
         base::BindRepeating(&ProfileSyncService::NotifyForeignSessionUpdated,
                             sync_enabled_weak_factory_.GetWeakPtr()),
-        std::make_unique<ClientTagBasedModelTypeProcessor>(
+        std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
             syncer::SESSIONS,
             base::BindRepeating(&syncer::ReportUnrecoverableError, channel_)));
   } else {
@@ -265,9 +263,9 @@
                 sync_enabled_weak_factory_.GetWeakPtr()));
   }
 
-  device_info_sync_bridge_ = std::make_unique<DeviceInfoSyncBridge>(
+  device_info_sync_bridge_ = std::make_unique<syncer::DeviceInfoSyncBridge>(
       local_device_.get(), model_type_store_factory_,
-      std::make_unique<ClientTagBasedModelTypeProcessor>(
+      std::make_unique<syncer::ClientTagBasedModelTypeProcessor>(
           syncer::DEVICE_INFO,
           /*dump_stack=*/base::BindRepeating(&syncer::ReportUnrecoverableError,
                                              channel_)));
@@ -429,7 +427,7 @@
 void ProfileSyncService::AccountStateChanged() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (auth_manager_->GetAuthenticatedAccountInfo().account_id.empty()) {
+  if (!IsSignedIn()) {
     sync_disabled_by_admin_ = false;
     RequestStop(CLEAR_DATA);
     DCHECK(!engine_);
@@ -555,12 +553,12 @@
     DCHECK(success);
   }
 
-  SyncEngine::InitParams params;
+  syncer::SyncEngine::InitParams params;
   params.sync_task_runner = sync_thread_->task_runner();
   params.host = this;
-  params.registrar = std::make_unique<SyncBackendRegistrar>(
+  params.registrar = std::make_unique<syncer::SyncBackendRegistrar>(
       debug_identifier_,
-      base::BindRepeating(&SyncClient::CreateModelWorkerForGroup,
+      base::BindRepeating(&syncer::SyncClient::CreateModelWorkerForGroup,
                           base::Unretained(sync_client_.get())));
   params.encryption_observer_proxy = crypto_->GetEncryptionObserverProxy();
   params.extensions_activity = sync_client_->GetExtensionsActivity();
@@ -574,7 +572,7 @@
       sync_client_->GetInvalidationService();
   params.invalidator_client_id =
       invalidator ? invalidator->GetInvalidatorClientId() : "",
-  params.sync_manager_factory = std::make_unique<SyncManagerFactory>();
+  params.sync_manager_factory = std::make_unique<syncer::SyncManagerFactory>();
   // The first time we start up the engine we want to ensure we have a clean
   // directory, so delete any old one that might be there.
   params.delete_sync_data_folder = !IsFirstSetupComplete();
@@ -685,7 +683,7 @@
   // Shutdown the migrator before the engine to ensure it doesn't pull a null
   // snapshot.
   migrator_.reset();
-  sync_js_controller_.AttachJsBackend(WeakHandle<syncer::JsBackend>());
+  sync_js_controller_.AttachJsBackend(syncer::WeakHandle<syncer::JsBackend>());
 
   engine_->Shutdown(reason);
   engine_.reset();
@@ -777,7 +775,7 @@
 
 void ProfileSyncService::ClearStaleErrors() {
   ClearUnrecoverableError();
-  last_actionable_error_ = SyncProtocolError();
+  last_actionable_error_ = syncer::SyncProtocolError();
   // Clear the data type errors as well.
   if (data_type_manager_)
     data_type_manager_->ResetDataTypeErrors();
@@ -848,7 +846,7 @@
 }
 
 void ProfileSyncService::OnEngineInitialized(
-    ModelTypeSet initial_types,
+    syncer::ModelTypeSet initial_types,
     const syncer::WeakHandle<syncer::JsBackend>& js_backend,
     const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
         debug_info_listener,
@@ -991,7 +989,8 @@
   migrator_->MigrateTypes(types);
 }
 
-void ProfileSyncService::OnActionableError(const SyncProtocolError& error) {
+void ProfileSyncService::OnActionableError(
+    const syncer::SyncProtocolError& error) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   last_actionable_error_ = error;
   DCHECK_NE(last_actionable_error_.action, syncer::UNKNOWN_ACTION);
@@ -1156,7 +1155,7 @@
     engine_->EnableEncryptEverything();
   NotifyObservers();
 
-  if (migrator_.get() && migrator_->state() != BackendMigrator::IDLE) {
+  if (migrator_.get() && migrator_->state() != syncer::BackendMigrator::IDLE) {
     // Migration in progress.  Let the migrator know we just finished
     // configuring something.  It will be up to the migrator to call
     // StartSyncingWithServer() if migration is now finished.
@@ -1210,13 +1209,14 @@
   return startup_controller_->IsSetupInProgress();
 }
 
-bool ProfileSyncService::QueryDetailedSyncStatus(SyncEngine::Status* result) {
+bool ProfileSyncService::QueryDetailedSyncStatus(
+    syncer::SyncEngine::Status* result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (engine_ && engine_initialized_) {
     *result = engine_->GetDetailedStatus();
     return true;
   }
-  SyncEngine::Status status;
+  syncer::SyncEngine::Status status;
   status.sync_protocol_error = last_actionable_error_;
   *result = status;
   return false;
@@ -1388,16 +1388,10 @@
 
   if (data_type_manager_)
     data_type_manager_->ResetDataTypeErrors();
-  ChangePreferredDataTypes(chosen_types);
-}
 
-void ProfileSyncService::ChangePreferredDataTypes(
-    syncer::ModelTypeSet preferred_types) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DVLOG(1) << "ChangePreferredDataTypes invoked";
   const syncer::ModelTypeSet registered_types = GetRegisteredDataTypes();
   // Will only enable those types that are registered and preferred.
-  sync_prefs_.SetPreferredDataTypes(registered_types, preferred_types);
+  sync_prefs_.SetPreferredDataTypes(registered_types, chosen_types);
 
   // Now reconfigure the DTM.
   ReconfigureDatatypeManager();
@@ -1505,7 +1499,7 @@
   // as the Local State file is guaranteed to be UTF-8.
   const std::string path =
       FormatSharedModelTypeStorePath(base_path).AsUTF8Unsafe();
-  return base::BindRepeating(&ModelTypeStore::CreateStore, path);
+  return base::BindRepeating(&syncer::ModelTypeStore::CreateStore, path);
 }
 
 void ProfileSyncService::ConfigureDataTypeManager() {
@@ -1526,7 +1520,7 @@
     restart = true;
 
     // We create the migrator at the same time.
-    migrator_ = std::make_unique<BackendMigrator>(
+    migrator_ = std::make_unique<syncer::BackendMigrator>(
         debug_identifier_, GetUserShare(), this, data_type_manager_.get(),
         base::BindRepeating(&ProfileSyncService::StartSyncingWithServer,
                             base::Unretained(this)));
@@ -1574,7 +1568,7 @@
   engine_->HasUnsyncedItemsForTest(std::move(cb));
 }
 
-BackendMigrator* ProfileSyncService::GetBackendMigratorForTest() {
+syncer::BackendMigrator* ProfileSyncService::GetBackendMigratorForTest() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return migrator_.get();
 }
@@ -1587,9 +1581,10 @@
     return std::move(result);
   }
 
-  SyncEngine::Status detailed_status = engine_->GetDetailedStatus();
-  const ModelTypeSet& throttled_types(detailed_status.throttled_types);
-  const ModelTypeSet& backed_off_types(detailed_status.backed_off_types);
+  syncer::SyncEngine::Status detailed_status = engine_->GetDetailedStatus();
+  const syncer::ModelTypeSet& throttled_types(detailed_status.throttled_types);
+  const syncer::ModelTypeSet& backed_off_types(
+      detailed_status.backed_off_types);
 
   std::unique_ptr<base::DictionaryValue> type_status_header(
       new base::DictionaryValue());
@@ -1602,11 +1597,12 @@
   type_status_header->SetString("group_type", "Group Type");
   result->Append(std::move(type_status_header));
 
-  ModelSafeRoutingInfo routing_info;
+  syncer::ModelSafeRoutingInfo routing_info;
   engine_->GetModelSafeRoutingInfo(&routing_info);
-  const ModelTypeSet registered = GetRegisteredDataTypes();
-  for (ModelTypeSet::Iterator it = registered.First(); it.Good(); it.Inc()) {
-    ModelType type = it.Get();
+  const syncer::ModelTypeSet registered = GetRegisteredDataTypes();
+  for (syncer::ModelTypeSet::Iterator it = registered.First(); it.Good();
+       it.Inc()) {
+    syncer::ModelType type = it.Get();
 
     auto type_status = std::make_unique<base::DictionaryValue>();
     type_status->SetString("name", ModelTypeToString(type));
@@ -1757,7 +1753,7 @@
 }
 
 void ProfileSyncService::AddProtocolEventObserver(
-    ProtocolEventObserver* observer) {
+    syncer::ProtocolEventObserver* observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   protocol_event_observers_.AddObserver(observer);
   if (engine_) {
@@ -1766,7 +1762,7 @@
 }
 
 void ProfileSyncService::RemoveProtocolEventObserver(
-    ProtocolEventObserver* observer) {
+    syncer::ProtocolEventObserver* observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   protocol_event_observers_.RemoveObserver(observer);
   if (engine_ && !protocol_event_observers_.might_have_observers()) {
@@ -1889,13 +1885,14 @@
     return;
   }
 
-  ModelTypeSet all_types = GetActiveDataTypes();
+  syncer::ModelTypeSet all_types = GetActiveDataTypes();
   all_types.PutAll(syncer::ControlTypes());
   scoped_refptr<GetAllNodesRequestHelper> helper =
       new GetAllNodesRequestHelper(all_types, callback);
 
-  for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
-    ModelType type = it.Get();
+  for (syncer::ModelTypeSet::Iterator it = all_types.First(); it.Good();
+       it.Inc()) {
+    syncer::ModelType type = it.Get();
     const auto dtc_iter = data_type_controllers_.find(type);
     if (dtc_iter != data_type_controllers_.end()) {
       dtc_iter->second->GetAllNodes(base::BindRepeating(
@@ -2156,9 +2153,9 @@
 }
 
 void ProfileSyncService::RecordMemoryUsageHistograms() {
-  ModelTypeSet active_types = GetActiveDataTypes();
-  for (ModelTypeSet::Iterator type_it = active_types.First(); type_it.Good();
-       type_it.Inc()) {
+  syncer::ModelTypeSet active_types = GetActiveDataTypes();
+  for (syncer::ModelTypeSet::Iterator type_it = active_types.First();
+       type_it.Good(); type_it.Inc()) {
     auto dtc_it = data_type_controllers_.find(type_it.Get());
     if (dtc_it != data_type_controllers_.end())
       dtc_it->second->RecordMemoryUsageHistogram();
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 0237a0d..469ed8b 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -94,8 +94,7 @@
 //
 //      When a datatype is registered, the user has the option of syncing it.
 //      The sync opt-in UI will show only registered types; a checkbox should
-//      never be shown for an unregistered type, and nor should it ever be
-//      synced.
+//      never be shown for an unregistered type, nor can it ever be synced.
 //
 //   'Preferred' (user preferences and opt-out for a datatype)
 //
@@ -104,7 +103,7 @@
 //      If a user has opted out of syncing a particular datatype, it will
 //      be registered, but not preferred.
 //
-//      This state is controlled by the ConfigurePreferredDataTypes and
+//      This state is controlled by OnUserChoseDatatypes and
 //      GetPreferredDataTypes.  They are stored in the preferences system,
 //      and persist; though if a datatype is not registered, it cannot
 //      be a preferred datatype.
@@ -374,13 +373,12 @@
   // Reconfigures the data type manager with the latest enabled types.
   // Note: Does not initialize the engine if it is not already initialized.
   // This function needs to be called only after sync has been initialized
-  // (i.e.,only for reconfigurations). The reason we don't initialize the
+  // (i.e., only for reconfigurations). The reason we don't initialize the
   // engine is because if we had encountered an unrecoverable error we don't
   // want to startup once more.
-  // This function is called by |SetSetupInProgress|.
   virtual void ReconfigureDatatypeManager();
 
-  syncer::PassphraseRequiredReason passphrase_required_reason() const {
+  syncer::PassphraseRequiredReason passphrase_required_reason_for_test() const {
     return crypto_->passphrase_required_reason();
   }
 
@@ -408,15 +406,14 @@
 
   // Returns whether sync is managed, i.e. controlled by configuration
   // management. If so, the user is not allowed to configure sync.
-  virtual bool IsManaged() const;
+  // TODO(crbug.com/839834): This is misnamed, it means "is force-disabled by
+  // policy".
+  bool IsManaged() const;
 
   // syncer::UnrecoverableErrorHandler implementation.
   void OnUnrecoverableError(const base::Location& from_here,
                             const std::string& message) override;
 
-  // The functions below (until ActivateDataType()) should only be
-  // called if IsEngineInitialized() is true.
-
   // Returns whether or not the underlying sync engine has made any
   // local changes to items that have not yet been synced with the
   // server.
@@ -434,15 +431,9 @@
   // SyncPrefObserver implementation.
   void OnSyncManagedPrefChange(bool is_sync_managed) override;
 
-  // Changes which data types we're going to be syncing to |preferred_types|.
-  // If it is running, the DataTypeManager will be instructed to reconfigure
-  // the sync engine so that exactly these datatypes are actively synced. See
-  // class comment for more on what it means for a datatype to be Preferred.
-  virtual void ChangePreferredDataTypes(syncer::ModelTypeSet preferred_types);
-
   // Returns the set of types which are enforced programmatically and can not
   // be disabled by the user.
-  virtual syncer::ModelTypeSet GetForcedDataTypes() const;
+  syncer::ModelTypeSet GetForcedDataTypes() const;
 
   // Gets the set of all data types that could be allowed (the set that
   // should be advertised to the user).  These will typically only change
@@ -456,7 +447,7 @@
   virtual void SetEncryptEverythingAllowed(bool allowed);
 
   // Returns true if the syncer is waiting for new datatypes to be encrypted.
-  virtual bool encryption_pending() const;
+  bool encryption_pending() const;
 
   syncer::SyncErrorController* sync_error_controller() {
     return sync_error_controller_.get();
@@ -532,23 +523,6 @@
     ERROR_REASON_LIMIT
   };
 
-  // The initial state of sync, for the Sync.InitialState histogram. Even if
-  // this value is CAN_START, sync startup might fail for reasons that we may
-  // want to consider logging in the future, such as a passphrase needed for
-  // decryption, or the version of Chrome being too old. This enum is used to
-  // back a UMA histogram, and should therefore be treated as append-only.
-  enum SyncInitialState {
-    CAN_START,                // Sync can attempt to start up.
-    NOT_SIGNED_IN,            // There is no signed in user.
-    NOT_REQUESTED,            // The user turned off sync.
-    NOT_REQUESTED_NOT_SETUP,  // The user turned off sync and setup completed
-                              // is false. Might indicate a stop-and-clear.
-    NEEDS_CONFIRMATION,       // The user must confirm sync settings.
-    IS_MANAGED,               // Sync is disallowed by enterprise policy.
-    NOT_ALLOWED_BY_PLATFORM,  // Sync is disallowed by the platform.
-    SYNC_INITIAL_STATE_LIMIT
-  };
-
   friend class TestProfileSyncService;
 
   // Returns whether sync is currently allowed on this platform.
@@ -669,6 +643,8 @@
   // email address.
   const std::unique_ptr<SigninManagerWrapper> signin_;
 
+  // Handles tracking of the authenticated account and acquiring access tokens.
+  // Only null after Shutdown().
   std::unique_ptr<SyncAuthManager> auth_manager_;
 
   // The product channel of the embedder.
diff --git a/components/browser_sync/profile_sync_service_mock.h b/components/browser_sync/profile_sync_service_mock.h
index 75ae3e6c..d569c78 100644
--- a/components/browser_sync/profile_sync_service_mock.h
+++ b/components/browser_sync/profile_sync_service_mock.h
@@ -64,8 +64,6 @@
   MOCK_CONST_METHOD0(IsEncryptEverythingEnabled, bool());
   MOCK_METHOD0(EnableEncryptEverything, void());
 
-  MOCK_METHOD1(ChangePreferredDataTypes,
-               void(syncer::ModelTypeSet preferred_types));
   MOCK_CONST_METHOD0(GetActiveDataTypes, syncer::ModelTypeSet());
   MOCK_CONST_METHOD0(GetPreferredDataTypes, syncer::ModelTypeSet());
   MOCK_CONST_METHOD0(GetRegisteredDataTypes, syncer::ModelTypeSet());
diff --git a/components/content_view/java/src/org/chromium/components/content_view/ContentView.java b/components/content_view/java/src/org/chromium/components/content_view/ContentView.java
index 94b6ef4..513233d 100644
--- a/components/content_view/java/src/org/chromium/components/content_view/ContentView.java
+++ b/components/content_view/java/src/org/chromium/components/content_view/ContentView.java
@@ -35,7 +35,7 @@
  * the various {@link View} functionality to it.
  */
 public class ContentView
-        extends FrameLayout implements ContentViewCore.InternalAccessDelegate, SmartClipProvider {
+        extends FrameLayout implements ViewEventSink.InternalAccessDelegate, SmartClipProvider {
     private static final String TAG = "cr.ContentView";
 
     // Default value to signal that the ContentView's size need not be overridden.
@@ -321,7 +321,7 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
-    //              Start Implementation of ContentViewCore.InternalAccessDelegate               //
+    //              Start Implementation of ViewEventSink.InternalAccessDelegate                 //
     ///////////////////////////////////////////////////////////////////////////////////////////////
 
     @Override
@@ -340,7 +340,7 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
-    //                End Implementation of ContentViewCore.InternalAccessDelegate               //
+    //                End Implementation of ViewEventSink.InternalAccessDelegate                 //
     ///////////////////////////////////////////////////////////////////////////////////////////////
 
     private static class ContentViewApi23 extends ContentView {
diff --git a/components/cryptauth/fake_secure_channel.cc b/components/cryptauth/fake_secure_channel.cc
index c09929f3..fd997de 100644
--- a/components/cryptauth/fake_secure_channel.cc
+++ b/components/cryptauth/fake_secure_channel.cc
@@ -50,6 +50,7 @@
 }
 
 void FakeSecureChannel::Initialize() {
+  was_initialized_ = true;
   ChangeStatus(Status::CONNECTING);
 }
 
diff --git a/components/cryptauth/fake_secure_channel.h b/components/cryptauth/fake_secure_channel.h
index 9d4850d..dee292b 100644
--- a/components/cryptauth/fake_secure_channel.h
+++ b/components/cryptauth/fake_secure_channel.h
@@ -21,6 +21,8 @@
     destructor_callback_ = std::move(destructor_callback);
   }
 
+  bool was_initialized() { return was_initialized_; }
+
   struct SentMessage {
     SentMessage(const std::string& feature, const std::string& payload);
 
@@ -46,6 +48,7 @@
 
  private:
   int next_sequence_number_ = 0;
+  bool was_initialized_ = false;
   std::vector<Observer*> observers_;
   std::vector<SentMessage> sent_messages_;
 
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc
index c1694c4..f3e2369 100644
--- a/components/download/internal/common/in_progress_download_manager.cc
+++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -314,7 +314,13 @@
 
 void InProgressDownloadManager::ResumeInterruptedDownload(
     std::unique_ptr<DownloadUrlParameters> params,
-    const GURL& site_url) {}
+    const GURL& site_url) {
+  if (!url_loader_factory_getter_)
+    return;
+
+  BeginDownload(std::move(params), url_loader_factory_getter_, false, site_url,
+                GURL(), GURL());
+}
 
 base::Optional<DownloadEntry> InProgressDownloadManager::GetInProgressEntry(
     DownloadItemImpl* download) {
diff --git a/components/download/public/common/in_progress_download_manager.h b/components/download/public/common/in_progress_download_manager.h
index 31a103c..34a3a62 100644
--- a/components/download/public/common/in_progress_download_manager.h
+++ b/components/download/public/common/in_progress_download_manager.h
@@ -128,6 +128,11 @@
   }
   DownloadFileFactory* file_factory() { return file_factory_.get(); }
 
+  void set_url_loader_factory_getter(
+      scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter) {
+    url_loader_factory_getter_ = std::move(url_loader_factory_getter);
+  }
+
  private:
   // UrlDownloadHandler::Delegate implementations.
   void OnUrlDownloadStarted(
@@ -179,6 +184,10 @@
   // is managing all downloads.
   std::vector<std::unique_ptr<DownloadItemImpl>> in_progress_downloads_;
 
+  // URLLoaderFactoryGetter for issuing network request when DownloadMangerImpl
+  // is not available.
+  scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter_;
+
   base::WeakPtrFactory<InProgressDownloadManager> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(InProgressDownloadManager);
diff --git a/components/nacl/broker/DEPS b/components/nacl/broker/DEPS
index f09975f..3fd2d9f 100644
--- a/components/nacl/broker/DEPS
+++ b/components/nacl/broker/DEPS
@@ -1,6 +1,5 @@
 include_rules = [
   "+content/public/app/sandbox_helper_win.h",
-  "+mojo/edk/embedder",
   "+mojo/public/cpp/system",
   "+sandbox/win/src",
   "+services/service_manager/sandbox",
diff --git a/components/nacl/browser/BUILD.gn b/components/nacl/browser/BUILD.gn
index 0f542635..d6f2729 100644
--- a/components/nacl/browser/BUILD.gn
+++ b/components/nacl/browser/BUILD.gn
@@ -39,7 +39,6 @@
     "//components/url_formatter",
     "//content/public/browser",
     "//content/public/common",
-    "//mojo/edk",
     "//native_client/src/trusted/service_runtime:sel_main_chrome",
     "//net",
     "//ppapi/host",
diff --git a/components/nacl/browser/DEPS b/components/nacl/browser/DEPS
index 8d8ba62c..ac0b7e8 100644
--- a/components/nacl/browser/DEPS
+++ b/components/nacl/browser/DEPS
@@ -2,7 +2,6 @@
   "+components/url_formatter",
   "+content/public/browser",
   "+content/public/test",
-  "+mojo/edk/embedder",
   "+native_client/src/public",
   "+net",
   "+ppapi/host",
diff --git a/components/nacl/browser/nacl_broker_host_win.cc b/components/nacl/browser/nacl_broker_host_win.cc
index 7b04f80..fd6e1d1e 100644
--- a/components/nacl/browser/nacl_broker_host_win.cc
+++ b/components/nacl/browser/nacl_broker_host_win.cc
@@ -24,7 +24,6 @@
 #include "content/public/common/child_process_host.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
-#include "mojo/edk/embedder/embedder.h"
 
 namespace {
 // NOTE: changes to this class need to be reviewed by the security team.
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index 08cd994..9613821 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -55,7 +55,6 @@
 #include "content/public/common/process_type.h"
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
 #include "ipc/ipc_channel.h"
-#include "mojo/edk/embedder/embedder.h"
 #include "net/socket/socket_descriptor.h"
 #include "ppapi/host/host_factory.h"
 #include "ppapi/host/ppapi_host.h"
diff --git a/components/password_manager/OWNERS b/components/password_manager/OWNERS
index b43b8ca..261ec61 100644
--- a/components/password_manager/OWNERS
+++ b/components/password_manager/OWNERS
@@ -1,4 +1,5 @@
 dvadym@chromium.org
+ioanap@chromium.org
 kolos@chromium.org
 vabr@chromium.org
 vasilii@chromium.org
diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc
index 1bea801..da6a830 100644
--- a/components/password_manager/core/browser/password_autofill_manager.cc
+++ b/components/password_manager/core/browser/password_autofill_manager.cc
@@ -266,7 +266,7 @@
           show_all_saved_passwords_shown_context_);
     }
     if (base::FeatureList::IsEnabled(
-            password_manager::features::kEnableManualFallbacksGeneration) &&
+            password_manager::features::kManualFallbacksGeneration) &&
         password_manager_util::GetPasswordSyncState(
             autofill_client_->GetSyncService()) == SYNCING_NORMAL_ENCRYPTION) {
       AddSimpleSuggestionWithSeparatorOnTop(
@@ -307,7 +307,7 @@
       show_all_saved_passwords_shown_context_);
 
   if (base::FeatureList::IsEnabled(
-          password_manager::features::kEnableManualFallbacksGeneration) &&
+          password_manager::features::kManualFallbacksGeneration) &&
       password_manager_util::GetPasswordSyncState(
           autofill_client_->GetSyncService()) == SYNCING_NORMAL_ENCRYPTION) {
     AddSimpleSuggestionWithSeparatorOnTop(
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
index e67f5d4..8989e33 100644
--- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -196,7 +196,7 @@
         password_manager::features::kManualFallbacksFilling.name,
         password_manager::features::kManualFallbacksFillingStandalone
             .name,
-        password_manager::features::kEnableManualFallbacksGeneration.name};
+        password_manager::features::kManualFallbacksGeneration.name};
     if (enabled) {
       scoped_feature_list_.InitFromCommandLine(base::JoinString(features, ","),
                                                std::string());
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index e934adf..21ef10b 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -20,8 +20,8 @@
 
 // Enable additional elements in the form popup UI, which will allow the user to
 // view all saved passwords.
-const base::Feature kEnableManualFallbacksGeneration = {
-    "EnableManualFallbacksGeneration", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kManualFallbacksGeneration = {
+    "ManualFallbacksGeneration", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enable additional elements in the form popup UI, which will allow the user to
 // trigger generation or view all saved passwords.
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index 4a888f85..dd3f735 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -21,7 +21,7 @@
 extern const base::Feature kHtmlBasedUsernameDetector;
 extern const base::Feature kManualFallbacksFilling;
 extern const base::Feature kManualFallbacksFillingStandalone;
-extern const base::Feature kEnableManualFallbacksGeneration;
+extern const base::Feature kManualFallbacksGeneration;
 extern const base::Feature kEnableManualPasswordGeneration;
 extern const base::Feature kPasswordGenerationRequirements;
 extern const base::Feature kPasswordGenerationRequirementsDomainOverrides;
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn
index 632ad1c..a6818db3 100644
--- a/components/sync/BUILD.gn
+++ b/components/sync/BUILD.gn
@@ -63,6 +63,7 @@
     "base/stop_source.h",
     "base/sync_prefs.cc",
     "base/sync_prefs.h",
+    "base/sync_stop_metadata_fate.cc",
     "base/sync_stop_metadata_fate.h",
     "base/syncer_error.cc",
     "base/syncer_error.h",
diff --git a/components/sync/base/sync_stop_metadata_fate.cc b/components/sync/base/sync_stop_metadata_fate.cc
new file mode 100644
index 0000000..c8fa6ca4
--- /dev/null
+++ b/components/sync/base/sync_stop_metadata_fate.cc
@@ -0,0 +1,23 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/base/sync_stop_metadata_fate.h"
+
+#include "base/logging.h"
+
+namespace syncer {
+
+const char* SyncStopMetadataFateToString(SyncStopMetadataFate metadata_fate) {
+  switch (metadata_fate) {
+    case KEEP_METADATA:
+      return "KEEP_METADATA";
+    case CLEAR_METADATA:
+      return "CLEAR_METADATA";
+  }
+
+  NOTREACHED() << "Invalid metadata fate " << static_cast<int>(metadata_fate);
+  return "INVALID";
+}
+
+}  // namespace syncer
diff --git a/components/sync/base/sync_stop_metadata_fate.h b/components/sync/base/sync_stop_metadata_fate.h
index 26f74c2..b56e093 100644
--- a/components/sync/base/sync_stop_metadata_fate.h
+++ b/components/sync/base/sync_stop_metadata_fate.h
@@ -12,6 +12,8 @@
 // TODO(mastiz): Unify with SyncStopDataFate.
 enum SyncStopMetadataFate { KEEP_METADATA, CLEAR_METADATA };
 
+const char* SyncStopMetadataFateToString(SyncStopMetadataFate metadata_fate);
+
 }  // namespace syncer
 
 #endif  // COMPONENTS_SYNC_BASE_SYNC_STOP_METADATA_FATE_H_
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index f799ad0..e36f7f3 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -299,7 +299,9 @@
   if (catch_up_in_progress_)
     model_association_manager_.Stop(KEEP_METADATA);
   download_started_ = false;
-  model_association_manager_.Initialize(last_enabled_types_);
+  model_association_manager_.Initialize(
+      last_enabled_types_ /* desired_types */,
+      last_requested_types_ /* preferred_types */);
 }
 
 void DataTypeManagerImpl::OnAllDataTypesReadyForConfigure() {
diff --git a/components/sync/driver/data_type_manager_impl_unittest.cc b/components/sync/driver/data_type_manager_impl_unittest.cc
index 7e608f43..e1974d8 100644
--- a/components/sync/driver/data_type_manager_impl_unittest.cc
+++ b/components/sync/driver/data_type_manager_impl_unittest.cc
@@ -542,6 +542,7 @@
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   EXPECT_EQ(ModelTypeSet(BOOKMARKS, PREFERENCES),
             configurer_.registered_directory_types());
+  EXPECT_EQ(0, GetController(BOOKMARKS)->clear_metadata_call_count());
 
   // Step 5.
   FinishDownload(ModelTypeSet(), ModelTypeSet());
@@ -599,6 +600,7 @@
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
   EXPECT_EQ(ModelTypeSet(PREFERENCES),
             configurer_.registered_directory_types());
+  EXPECT_EQ(1, GetController(BOOKMARKS)->clear_metadata_call_count());
 
   // Step 5.
   FinishDownload(ModelTypeSet(), ModelTypeSet());
@@ -918,10 +920,12 @@
   to_migrate.Put(BOOKMARKS);
   to_migrate.PutAll(ControlTypes());
 
+  EXPECT_EQ(0, GetController(BOOKMARKS)->clear_metadata_call_count());
   SetConfigureStartExpectation();
   SetConfigureDoneExpectation(DataTypeManager::OK, DataTypeStatusTable());
   dtm_->PurgeForMigration(to_migrate, CONFIGURE_REASON_MIGRATION);
   EXPECT_EQ(DataTypeManager::CONFIGURING, dtm_->state());
+  EXPECT_EQ(1, GetController(BOOKMARKS)->clear_metadata_call_count());
 
   // The DTM will call ConfigureDataTypes(), even though it is unnecessary.
   FinishDownload(ModelTypeSet(), ModelTypeSet());
@@ -935,6 +939,7 @@
   FinishDownload(to_migrate, ModelTypeSet());
   GetController(BOOKMARKS)->FinishStart(DataTypeController::OK);
   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
+  EXPECT_EQ(1, GetController(BOOKMARKS)->clear_metadata_call_count());
 }
 
 // Test receipt of a Configure request while a purge is in flight.
@@ -984,6 +989,8 @@
   // the BOOKMARKS because it was never stopped.
   GetController(PREFERENCES)->FinishStart(DataTypeController::OK);
   EXPECT_EQ(DataTypeManager::CONFIGURED, dtm_->state());
+  EXPECT_EQ(0, GetController(BOOKMARKS)->clear_metadata_call_count());
+  EXPECT_EQ(0, GetController(PREFERENCES)->clear_metadata_call_count());
 }
 
 TEST_F(SyncDataTypeManagerImplTest, PrioritizedConfiguration) {
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index 0f410b2..63b01e59 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -103,12 +103,16 @@
 
 ModelAssociationManager::~ModelAssociationManager() {}
 
-void ModelAssociationManager::Initialize(ModelTypeSet desired_types) {
+void ModelAssociationManager::Initialize(ModelTypeSet desired_types,
+                                         ModelTypeSet preferred_types) {
   // state_ can be INITIALIZED if types are reconfigured when
   // data is being downloaded, so StartAssociationAsync() is never called for
   // the first configuration.
   DCHECK_NE(ASSOCIATING, state_);
 
+  // |desired_types| must be a subset of |preferred_types|.
+  DCHECK(preferred_types.HasAll(desired_types));
+
   // Only keep types that have controllers.
   desired_types_.Clear();
   for (ModelTypeSet::Iterator it = desired_types.First(); it.Good(); it.Inc()) {
@@ -122,7 +126,7 @@
   state_ = INITIALIZED;
   notified_about_ready_for_configure_ = false;
 
-  StopDisabledTypes();
+  StopDisabledTypes(preferred_types);
   LoadEnabledTypes();
 }
 
@@ -140,15 +144,18 @@
   }
 }
 
-void ModelAssociationManager::StopDisabledTypes() {
+void ModelAssociationManager::StopDisabledTypes(ModelTypeSet preferred_types) {
   DVLOG(1) << "ModelAssociationManager: Stopping disabled types.";
   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
        it != controllers_->end(); ++it) {
     DataTypeController* dtc = (*it).second.get();
     if (dtc->state() != DataTypeController::NOT_RUNNING &&
         !desired_types_.Has(dtc->type())) {
-      DVLOG(1) << "ModelAssociationManager: stop " << dtc->name();
-      StopDatatype(SyncError(), KEEP_METADATA, dtc);
+      const SyncStopMetadataFate metadata_fate =
+          preferred_types.Has(dtc->type()) ? KEEP_METADATA : CLEAR_METADATA;
+      DVLOG(1) << "ModelAssociationManager: stop " << dtc->name() << " with "
+               << SyncStopMetadataFateToString(metadata_fate);
+      StopDatatype(SyncError(), metadata_fate, dtc);
     }
   }
 }
diff --git a/components/sync/driver/model_association_manager.h b/components/sync/driver/model_association_manager.h
index e8a804a..34d04ca 100644
--- a/components/sync/driver/model_association_manager.h
+++ b/components/sync/driver/model_association_manager.h
@@ -13,13 +13,12 @@
 
 #include "components/sync/base/sync_stop_metadata_fate.h"
 #include "components/sync/base/weak_handle.h"
+#include "components/sync/driver/data_type_controller.h"
 #include "components/sync/driver/data_type_manager.h"
 #include "components/sync/engine/data_type_association_stats.h"
 
 namespace syncer {
 
-class DataTypeController;
-
 // |ModelAssociationManager| does the heavy lifting for doing the actual model
 // association. It instructs DataTypeControllers to load models, start
 // associating and stopping. Since the operations are async it uses an
@@ -84,8 +83,10 @@
   // of Initialize is only allowed if the ModelAssociationManager has invoked
   // |OnModelAssociationDone| on the |ModelAssociationManagerDelegate|. After
   // this call, there should be several calls to StartAssociationAsync()
-  // to associate subset of |desired_types|.
-  void Initialize(ModelTypeSet desired_types);
+  // to associate subset of |desired_types| which must be a subset of
+  // |preferred_types|.
+  // |preferred_types| contains types selected by user.
+  void Initialize(ModelTypeSet desired_types, ModelTypeSet preferred_types);
 
   // Can be called at any time. Synchronously stops all datatypes.
   // If |metadata_fate| equals  CLEAR_METADATA controllers should clear sync
@@ -111,7 +112,8 @@
   void ResetForNextAssociation();
 
   // Called by Initialize() to stop types that are not in |desired_types_|.
-  void StopDisabledTypes();
+  // For types that not in |preferred_types| also clears sync metadata.
+  void StopDisabledTypes(ModelTypeSet preferred_types);
 
   // Start loading non-running types that are in |desired_types_|.
   void LoadEnabledTypes();
diff --git a/components/sync/driver/model_association_manager_unittest.cc b/components/sync/driver/model_association_manager_unittest.cc
index 3b4a5a5..40849965 100644
--- a/components/sync/driver/model_association_manager_unittest.cc
+++ b/components/sync/driver/model_association_manager_unittest.cc
@@ -78,7 +78,8 @@
             DataTypeController::NOT_RUNNING);
 
   // Initialize() kicks off model loading.
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::MODEL_LOADED);
@@ -110,7 +111,8 @@
       .WillOnce(VerifyResult(expected_result));
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStop(BOOKMARKS, _));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
   model_association_manager.StartAssociationAsync(types);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
@@ -134,7 +136,8 @@
       .WillOnce(VerifyResult(expected_result));
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStop(BOOKMARKS, _));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
   model_association_manager.StartAssociationAsync(types);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
@@ -160,7 +163,8 @@
   EXPECT_CALL(delegate_, OnModelAssociationDone(_))
       .WillOnce(VerifyResult(expected_result));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
   model_association_manager.StartAssociationAsync(types);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
@@ -184,8 +188,8 @@
   EXPECT_CALL(delegate_, OnModelAssociationDone(_))
       .WillOnce(VerifyResult(expected_result));
 
-  model_association_manager.Initialize(types);
-
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
   model_association_manager.StartAssociationAsync(types);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
@@ -211,7 +215,8 @@
   EXPECT_CALL(delegate_, OnModelAssociationDone(_))
       .WillOnce(VerifyResult(expected_result_partially_done));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
   model_association_manager.StartAssociationAsync(types);
   GetController(controllers_, APPS)->FinishStart(DataTypeController::OK);
 
@@ -239,7 +244,8 @@
       .WillOnce(VerifyResult(result_1st))
       .WillOnce(VerifyResult(result_2nd));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
 
   // Start BOOKMARKS first.
   model_association_manager.StartAssociationAsync(ModelTypeSet(BOOKMARKS));
@@ -280,7 +286,9 @@
   EXPECT_CALL(delegate_, OnModelAssociationDone(_))
       .WillOnce(VerifyResult(expected_result));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
+
   EXPECT_EQ(DataTypeController::NOT_RUNNING,
             GetController(controllers_, BOOKMARKS)->state());
   model_association_manager.StartAssociationAsync(types);
@@ -299,7 +307,8 @@
   EXPECT_CALL(delegate_, OnModelAssociationDone(_))
       .WillOnce(VerifyResult(expected_result));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
   model_association_manager.StartAssociationAsync(types);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
@@ -335,7 +344,8 @@
   EXPECT_CALL(delegate_, OnModelAssociationDone(_))
       .WillOnce(VerifyResult(expected_result_partially_done));
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
   model_association_manager.StartAssociationAsync(types);
   GetController(controllers_, APPS)->FinishStart(DataTypeController::OK);
   EXPECT_EQ(GetController(controllers_, APPS)->state(),
@@ -371,7 +381,8 @@
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStart(APPS));
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure()).Times(0);
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
 
   EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::MODEL_STARTING);
@@ -395,8 +406,14 @@
   testing::Mock::VerifyAndClearExpectations(&delegate_);
 
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
+
   ModelTypeSet reduced_types(APPS);
-  model_association_manager.Initialize(reduced_types);
+  model_association_manager.Initialize(reduced_types /* desired_types */,
+                                       reduced_types /* preferred_types */);
+
+  EXPECT_EQ(0, GetController(controllers_, APPS)->clear_metadata_call_count());
+  EXPECT_EQ(
+      1, GetController(controllers_, BOOKMARKS)->clear_metadata_call_count());
 }
 
 // Test that OnAllDataTypesReadyForConfigure() is called correctly after
@@ -417,7 +434,8 @@
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStart(APPS));
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure()).Times(0);
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
 
   EXPECT_EQ(GetController(controllers_, APPS)->state(),
             DataTypeController::MODEL_STARTING);
@@ -460,7 +478,8 @@
   EXPECT_CALL(delegate_, OnSingleDataTypeWillStart(APPS));
   EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure()).Times(0);
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
 
   GetController(controllers_, APPS)->SimulateModelLoadFinishing();
 
@@ -510,7 +529,8 @@
     EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
   }
 
-  model_association_manager.Initialize(types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
 
   EXPECT_EQ(DataTypeController::MODEL_LOADED,
             GetController(controllers_, BOOKMARKS)->state());
@@ -526,10 +546,11 @@
   ASSERT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::NOT_RUNNING);
 
-  ModelTypeSet desired_types(BOOKMARKS);
+  ModelTypeSet types(BOOKMARKS);
 
   // Initialize() kicks off model loading.
-  model_association_manager.Initialize(desired_types);
+  model_association_manager.Initialize(types /* desired_types */,
+                                       types /* preferred_types */);
 
   ASSERT_EQ(GetController(controllers_, BOOKMARKS)->state(),
             DataTypeController::MODEL_LOADED);
@@ -542,4 +563,50 @@
       1, GetController(controllers_, BOOKMARKS)->clear_metadata_call_count());
 }
 
+// Test that Initialize stops controllers with KEEP_METADATA for preferred
+// types.
+TEST_F(SyncModelAssociationManagerTest, KeepsMetadataForPreferredDataType) {
+  // Associate model with two data types.
+  controllers_[BOOKMARKS] = std::make_unique<FakeDataTypeController>(BOOKMARKS);
+  controllers_[APPS] = std::make_unique<FakeDataTypeController>(APPS);
+  ModelAssociationManager model_association_manager(&controllers_, &delegate_);
+  ModelTypeSet preferred_types(BOOKMARKS, APPS);
+  ModelTypeSet desired_types = preferred_types;
+
+  DataTypeManager::ConfigureResult expected_result(DataTypeManager::OK,
+                                                   desired_types);
+  EXPECT_CALL(delegate_, OnSingleDataTypeWillStart(BOOKMARKS));
+  EXPECT_CALL(delegate_, OnSingleDataTypeWillStart(APPS));
+  EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
+  EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(BOOKMARKS, _));
+  EXPECT_CALL(delegate_, OnSingleDataTypeAssociationDone(APPS, _));
+  EXPECT_CALL(delegate_, OnModelAssociationDone(_))
+      .WillOnce(VerifyResult(expected_result));
+
+  model_association_manager.Initialize(desired_types, preferred_types);
+  model_association_manager.StartAssociationAsync(desired_types);
+  GetController(controllers_, BOOKMARKS)->FinishStart(DataTypeController::OK);
+  GetController(controllers_, APPS)->FinishStart(DataTypeController::OK);
+
+  ASSERT_EQ(GetController(controllers_, BOOKMARKS)->state(),
+            DataTypeController::RUNNING);
+  ASSERT_EQ(GetController(controllers_, APPS)->state(),
+            DataTypeController::RUNNING);
+  testing::Mock::VerifyAndClearExpectations(&delegate_);
+
+  // Stop one data type without disabling sync.
+  desired_types.Remove(APPS);
+
+  EXPECT_CALL(delegate_, OnSingleDataTypeWillStop(APPS, _));
+  EXPECT_CALL(delegate_, OnAllDataTypesReadyForConfigure());
+
+  model_association_manager.Initialize(desired_types, preferred_types);
+
+  EXPECT_EQ(GetController(controllers_, BOOKMARKS)->state(),
+            DataTypeController::RUNNING);
+  EXPECT_EQ(GetController(controllers_, APPS)->state(),
+            DataTypeController::NOT_RUNNING);
+  EXPECT_EQ(0, GetController(controllers_, APPS)->clear_metadata_call_count());
+}
+
 }  // namespace syncer
diff --git a/components/sync/driver/model_type_controller.cc b/components/sync/driver/model_type_controller.cc
index b7a0325..b2ca14a 100644
--- a/components/sync/driver/model_type_controller.cc
+++ b/components/sync/driver/model_type_controller.cc
@@ -94,7 +94,6 @@
     : DataTypeController(type),
       sync_client_(sync_client),
       model_thread_(model_thread),
-      sync_prefs_(sync_client->GetPrefService()),
       state_(NOT_RUNNING) {}
 
 ModelTypeController::~ModelTypeController() {}
@@ -238,22 +237,11 @@
   if (state() == NOT_RUNNING)
     return;
 
-  // Check preferences if datatype is not in preferred datatypes. Only call
-  // StopSync() if the delegate is ready to handle it (controller is in loaded
-  // state).
-  ModelTypeSet preferred_types =
-      sync_prefs_.GetPreferredDataTypes(ModelTypeSet(type()));
-
+  // Only call StopSync if the delegate is ready to handle it (controller is
+  // in loaded state).
   if (state() == MODEL_LOADED || state() == RUNNING) {
-    // TODO(lixan@yandex-team.ru): Migrate away from preference-based inferring
-    // of |reason| and instead consume |metadata_fate|.
-    if (sync_prefs_.IsFirstSetupComplete() && preferred_types.Has(type())) {
-      PostModelTask(FROM_HERE, base::BindOnce(&StopSyncHelperOnModelThread,
-                                              KEEP_METADATA));
-    } else {
-      PostModelTask(FROM_HERE, base::BindOnce(&StopSyncHelperOnModelThread,
-                                              CLEAR_METADATA));
-    }
+    PostModelTask(FROM_HERE,
+                  base::BindOnce(&StopSyncHelperOnModelThread, metadata_fate));
   }
 
   state_ = NOT_RUNNING;
diff --git a/components/sync/driver/model_type_controller.h b/components/sync/driver/model_type_controller.h
index e4a2080..6a67ed6 100644
--- a/components/sync/driver/model_type_controller.h
+++ b/components/sync/driver/model_type_controller.h
@@ -13,7 +13,6 @@
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "components/sync/base/model_type.h"
-#include "components/sync/base/sync_prefs.h"
 #include "components/sync/driver/data_type_controller.h"
 #include "components/sync/model/model_error.h"
 #include "components/sync/model/model_type_controller_delegate.h"
@@ -87,10 +86,6 @@
   // The thread the model type lives on.
   scoped_refptr<base::SingleThreadTaskRunner> model_thread_;
 
-  // Sync prefs. Used for determinig if DisableSync should be called during call
-  // to Stop().
-  SyncPrefs sync_prefs_;
-
   // State of this datatype controller.
   State state_;
 
diff --git a/components/sync/driver/model_type_controller_unittest.cc b/components/sync/driver/model_type_controller_unittest.cc
index 236fd6b..3ff70f9 100644
--- a/components/sync/driver/model_type_controller_unittest.cc
+++ b/components/sync/driver/model_type_controller_unittest.cc
@@ -28,7 +28,6 @@
 #include "components/sync/model/fake_model_type_change_processor.h"
 #include "components/sync/model/fake_model_type_controller_delegate.h"
 #include "components/sync/model/stub_model_type_sync_bridge.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -167,10 +166,7 @@
 
 class ModelTypeControllerTest : public testing::Test {
  public:
-  ModelTypeControllerTest() : model_thread_("modelthread") {
-    SyncPrefs::RegisterProfilePrefs(pref_service_.registry());
-    sync_prefs_ = std::make_unique<SyncPrefs>(&pref_service_);
-  }
+  ModelTypeControllerTest() : model_thread_("modelthread") {}
 
   void SetUp() override {
     model_thread_.Start();
@@ -182,8 +178,6 @@
 
     ON_CALL(sync_client_mock_, GetSyncService())
         .WillByDefault(testing::Return(&sync_service_));
-    ON_CALL(sync_client_mock_, GetPrefService())
-        .WillByDefault(testing::Return(&pref_service_));
     ON_CALL(sync_client_mock_, GetControllerDelegateForModelType(_))
         .WillByDefault(testing::Return(
             bridge_->change_processor()->GetControllerDelegateOnUIThread()));
@@ -218,9 +212,9 @@
     EXPECT_TRUE(association_callback_called_);
   }
 
-  void DeactivateDataTypeAndStop() {
+  void DeactivateDataTypeAndStop(SyncStopMetadataFate metadata_fate) {
     controller_->DeactivateDataType(&configurer_);
-    controller_->Stop(KEEP_METADATA);
+    controller_->Stop(metadata_fate);
   }
 
   // These threads can ping-pong for a bit so we run the model thread twice.
@@ -255,7 +249,6 @@
     processor_->set_initial_sync_done(initial_sync_done);
   }
 
-  SyncPrefs* sync_prefs() { return sync_prefs_.get(); }
   DataTypeController* controller() { return controller_.get(); }
   int load_models_done_count() { return load_models_done_count_; }
   int cleared_metadata_count() { return cleared_metadata_count_; }
@@ -316,10 +309,6 @@
 
   base::MessageLoop message_loop_;
   base::Thread model_thread_;
-  // TODO(mastiz): Remove all preferences-related dependencies once
-  // ModelTypeController doesn't actually read from preferences.
-  sync_preferences::TestingPrefServiceSyncable pref_service_;
-  std::unique_ptr<SyncPrefs> sync_prefs_;
   TestSyncService sync_service_;
   testing::NiceMock<SyncClientMock> sync_client_mock_;
   TestModelTypeConfigurer configurer_;
@@ -381,80 +370,46 @@
 
   StartAssociating();
 
-  DeactivateDataTypeAndStop();
+  DeactivateDataTypeAndStop(KEEP_METADATA);
   EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state());
 }
 
-// Test emulates normal browser shutdown. Ensures that DisableSync is not
-// called.
+// Test emulates normal browser shutdown. Ensures that metadata was not cleared.
 TEST_F(ModelTypeControllerTest, StopWhenDatatypeEnabled) {
-  // Enable datatype through preferences.
-  sync_prefs()->SetFirstSetupComplete();
-  sync_prefs()->SetKeepEverythingSynced(true);
-
   LoadModels();
   RunAllTasks();
   StartAssociating();
 
-  DeactivateDataTypeAndStop();
+  DeactivateDataTypeAndStop(KEEP_METADATA);
   RunAllTasks();
   EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state());
-  // Ensure that DisableSync is not called.
+  // Ensures that metadata was not cleared.
   EXPECT_EQ(0, cleared_metadata_count());
   ExpectProcessorConnected(false);
 }
 
-// Test emulates scenario when user disables datatype. DisableSync should be
-// called.
+// Test emulates scenario when user disables datatype. Metadata should be
+// cleared.
 TEST_F(ModelTypeControllerTest, StopWhenDatatypeDisabled) {
-  // Enable datatype through preferences.
-  sync_prefs()->SetFirstSetupComplete();
-  sync_prefs()->SetKeepEverythingSynced(true);
   LoadModels();
   RunAllTasks();
   StartAssociating();
 
-  // Disable datatype through preferences.
-  sync_prefs()->SetKeepEverythingSynced(false);
-  sync_prefs()->SetPreferredDataTypes(ModelTypeSet(kTestModelType),
-                                      ModelTypeSet());
-
-  DeactivateDataTypeAndStop();
-  EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state());
-  // Ensure that DisableSync is called.
-  PumpModelThread();
-  EXPECT_EQ(1, cleared_metadata_count());
-}
-
-// Test emulates disabling sync by signing out. DisableSync should be called.
-TEST_F(ModelTypeControllerTest, StopWithInitialSyncPrefs) {
-  // Enable datatype through preferences.
-  sync_prefs()->SetFirstSetupComplete();
-  sync_prefs()->SetKeepEverythingSynced(true);
-  LoadModels();
+  DeactivateDataTypeAndStop(CLEAR_METADATA);
   RunAllTasks();
-  StartAssociating();
-
-  // Clearing preferences emulates signing out.
-  sync_prefs()->ClearPreferences();
-  DeactivateDataTypeAndStop();
   EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state());
-  // Ensure that DisableSync is called.
-  PumpModelThread();
+  // Ensures that metadata was cleared.
   EXPECT_EQ(1, cleared_metadata_count());
+  ExpectProcessorConnected(false);
 }
 
-// Test emulates disabling sync when datatype is not loaded yet. DisableSync
-// should not be called as the bridge is potentially not ready to handle it.
+// Test emulates disabling sync when datatype is not loaded yet. Metadata should
+// not be cleared as the delegate is potentially not ready to handle it.
 TEST_F(ModelTypeControllerTest, StopBeforeLoadModels) {
-  // Enable datatype through preferences.
-  sync_prefs()->SetFirstSetupComplete();
-  sync_prefs()->SetKeepEverythingSynced(true);
   EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state());
 
-  // Clearing preferences emulates signing out.
-  sync_prefs()->ClearPreferences();
-  controller()->Stop(KEEP_METADATA);
+  controller()->Stop(CLEAR_METADATA);
+
   EXPECT_EQ(DataTypeController::NOT_RUNNING, controller()->state());
   // Ensure that DisableSync is not called.
   EXPECT_EQ(0, cleared_metadata_count());
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index f4a60e9..bfe666f 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -250,8 +250,8 @@
       WARN_UNUSED_RESULT = 0;
 
   // Checks whether the Cryptographer is ready to encrypt and decrypt updates
-  // for sensitive data types. Caller must be holding a
-  // syncapi::BaseTransaction to ensure thread safety.
+  // for sensitive data types. Caller must be holding a syncer::BaseTransaction
+  // to ensure thread safety.
   virtual bool IsCryptographerReady(const BaseTransaction* trans) const = 0;
 
   // TODO(akalin): This is called mostly by ModelAssociators and
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.cc b/components/sync_bookmarks/synced_bookmark_tracker.cc
index e82787368..205c53b 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker.cc
@@ -37,6 +37,10 @@
 
 SyncedBookmarkTracker::Entity::~Entity() = default;
 
+bool SyncedBookmarkTracker::Entity::IsUnsynced() const {
+  return metadata_->sequence_number() > metadata_->acked_sequence_number();
+}
+
 bool SyncedBookmarkTracker::Entity::MatchesData(
     const syncer::EntityData& data) const {
   if (metadata_->is_deleted() || data.is_deleted()) {
@@ -55,10 +59,6 @@
   return hash == metadata_->specifics_hash();
 }
 
-bool SyncedBookmarkTracker::Entity::IsUnsynced() const {
-  return metadata_->sequence_number() > metadata_->acked_sequence_number();
-}
-
 SyncedBookmarkTracker::SyncedBookmarkTracker(
     std::vector<NodeMetadataPair> nodes_metadata,
     std::unique_ptr<sync_pb::ModelTypeState> model_type_state)
@@ -89,6 +89,8 @@
   metadata->set_server_id(sync_id);
   metadata->set_server_version(server_version);
   metadata->set_creation_time(syncer::TimeToProtoTime(creation_time));
+  metadata->set_sequence_number(0);
+  metadata->set_acked_sequence_number(0);
   HashSpecifics(specifics, metadata->mutable_specifics_hash());
   sync_id_to_entities_map_[sync_id] =
       std::make_unique<Entity>(bookmark_node, std::move(metadata));
@@ -113,6 +115,17 @@
   sync_id_to_entities_map_.erase(sync_id);
 }
 
+void SyncedBookmarkTracker::IncrementSequenceNumber(
+    const std::string& sync_id) {
+  Entity* entity = sync_id_to_entities_map_.find(sync_id)->second.get();
+  DCHECK(entity);
+  DCHECK(!entity->metadata()->is_deleted());
+  // TODO(crbug.com/516866): Update base hash specifics here if the entity is
+  // not already out of sync.
+  entity->metadata()->set_sequence_number(
+      entity->metadata()->sequence_number() + 1);
+}
+
 sync_pb::BookmarkModelMetadata
 SyncedBookmarkTracker::BuildBookmarkModelMetadata() const {
   sync_pb::BookmarkModelMetadata model_metadata;
@@ -130,7 +143,13 @@
 }
 
 bool SyncedBookmarkTracker::HasLocalChanges() const {
-  NOTIMPLEMENTED();
+  for (const std::pair<const std::string, std::unique_ptr<Entity>>& pair :
+       sync_id_to_entities_map_) {
+    Entity* entity = pair.second.get();
+    if (entity->IsUnsynced()) {
+      return true;
+    }
+  }
   return false;
 }
 
diff --git a/components/sync_bookmarks/synced_bookmark_tracker.h b/components/sync_bookmarks/synced_bookmark_tracker.h
index 8bb34a1..541ecd2a 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker.h
+++ b/components/sync_bookmarks/synced_bookmark_tracker.h
@@ -96,6 +96,10 @@
   // |sync_id_to_entities_map_|.
   void Remove(const std::string& sync_id);
 
+  // Increment sequence number in the metadata for the entity with |sync_id|.
+  // Tracker must contain a non-tomstone entity with server id = |sync_id|.
+  void IncrementSequenceNumber(const std::string& sync_id);
+
   sync_pb::BookmarkModelMetadata BuildBookmarkModelMetadata() const;
 
   // Returns true if there are any local entities to be committed.
diff --git a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
index c671c6f..9d1eb4e 100644
--- a/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
+++ b/components/sync_bookmarks/synced_bookmark_tracker_unittest.cc
@@ -39,7 +39,7 @@
   const base::Time kCreationTime(base::Time::Now() -
                                  base::TimeDelta::FromSeconds(1));
   const sync_pb::EntitySpecifics specifics =
-      GenerateSpecifics(std::string(), std::string());
+      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
 
   bookmarks::BookmarkNode node(kId, kUrl);
   tracker.Add(kSyncId, &node, kServerVersion, kCreationTime, specifics);
@@ -66,7 +66,7 @@
   const base::Time kModificationTime(base::Time::Now() -
                                      base::TimeDelta::FromSeconds(1));
   const sync_pb::EntitySpecifics specifics =
-      GenerateSpecifics(std::string(), std::string());
+      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
   bookmarks::BookmarkNode node(kId, GURL());
   tracker.Add(kSyncId, &node, kServerVersion, kModificationTime, specifics);
   ASSERT_THAT(tracker.GetEntityForSyncId(kSyncId), NotNull());
@@ -74,6 +74,27 @@
   EXPECT_THAT(tracker.GetEntityForSyncId(kSyncId), IsNull());
 }
 
+TEST(SyncedBookmarkTrackerTest,
+     ShouldRequireCommitRequestWhenSequenceNumberIsIncremented) {
+  SyncedBookmarkTracker tracker(std::vector<NodeMetadataPair>(),
+                                std::make_unique<sync_pb::ModelTypeState>());
+  const std::string kSyncId = "SYNC_ID";
+  const int64_t kId = 1;
+  const int64_t kServerVersion = 1000;
+  const base::Time kModificationTime(base::Time::Now() -
+                                     base::TimeDelta::FromSeconds(1));
+  const sync_pb::EntitySpecifics specifics =
+      GenerateSpecifics(/*title=*/std::string(), /*url=*/std::string());
+  bookmarks::BookmarkNode node(kId, GURL());
+  tracker.Add(kSyncId, &node, kServerVersion, kModificationTime, specifics);
+
+  EXPECT_THAT(tracker.HasLocalChanges(), Eq(false));
+  tracker.IncrementSequenceNumber(kSyncId);
+  EXPECT_THAT(tracker.HasLocalChanges(), Eq(true));
+  // TODO(crbug.com/516866): Test HasLocalChanges after submitting commit
+  // request in a separate test probably.
+}
+
 }  // namespace
 
 }  // namespace sync_bookmarks
diff --git a/components/sync_sessions/local_session_event_handler_impl.cc b/components/sync_sessions/local_session_event_handler_impl.cc
index 8d5eaa17..62106fb0 100644
--- a/components/sync_sessions/local_session_event_handler_impl.cc
+++ b/components/sync_sessions/local_session_event_handler_impl.cc
@@ -46,6 +46,20 @@
          window_delegate.HasWindow();
 }
 
+// On Android, it's possible to not have any tabbed windows when only custom
+// tabs are currently open. This means that there is tab data that will be
+// restored later, but we cannot access it.
+bool ScanForTabbedWindow(SyncedWindowDelegatesGetter* delegates_getter) {
+  for (const auto& window_iter_pair :
+       delegates_getter->GetSyncedWindowDelegates()) {
+    const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
+    if (window_delegate->IsTypeTabbed() && IsWindowSyncable(*window_delegate)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace
 
 LocalSessionEventHandlerImpl::WriteBatch::WriteBatch() = default;
@@ -77,7 +91,7 @@
 
 void LocalSessionEventHandlerImpl::OnSessionRestoreComplete() {
   std::unique_ptr<WriteBatch> batch = delegate_->CreateLocalSessionWriteBatch();
-  AssociateWindows(RELOAD_TABS, ScanForTabbedWindow(), batch.get());
+  AssociateWindows(RELOAD_TABS, batch.get());
   batch->Commit();
 }
 
@@ -88,9 +102,12 @@
 }
 
 void LocalSessionEventHandlerImpl::AssociateWindows(ReloadTabsOption option,
-                                                    bool has_tabbed_window,
                                                     WriteBatch* batch) {
   DCHECK(!IsSessionRestoreInProgress(sessions_client_));
+
+  const bool has_tabbed_window =
+      ScanForTabbedWindow(sessions_client_->GetSyncedWindowDelegatesGetter());
+
   // Note that |current_session| is a pointer owned by |session_tracker_|.
   // |session_tracker_| will continue to update |current_session| under
   // the hood so care must be taken accessing it. In particular, invoking
@@ -113,8 +130,6 @@
     session_tracker_->ResetSessionTracking(current_session_tag_);
     current_session->modified_time = base::Time::Now();
   } else {
-    // TODO(mastiz): Investigate if this whole code block should be
-    // conditioned to RELOAD_TABS.
     DVLOG(1) << "Found no tabbed windows. Reloading "
              << current_session->windows.size()
              << " windows from previous session.";
@@ -162,9 +177,12 @@
       if (synced_tab->IsPlaceholderTab()) {
         // For tabs without WebContents update |window_id|, as it could have
         // changed after a session restore.
+        // TODO(crbug.com/854493): Avoid associating placeholder tabs
+        // altogether, because it's not worth to update the window ID in tab
+        // entities.
         AssociateRestoredPlaceholderTab(*synced_tab, tab_id, window_id, batch);
       } else if (RELOAD_TABS == option) {
-        AssociateTab(synced_tab, has_tabbed_window, batch);
+        AssociateTab(synced_tab, batch);
       }
 
       // If the tab was syncable, it would have been added to the tracker
@@ -222,7 +240,6 @@
 
 void LocalSessionEventHandlerImpl::AssociateTab(
     SyncedTabDelegate* const tab_delegate,
-    bool has_tabbed_window,
     WriteBatch* batch) {
   DCHECK(!tab_delegate->IsPlaceholderTab());
 
@@ -241,29 +258,19 @@
   }
 
   SessionID tab_id = tab_delegate->GetSessionId();
-  DVLOG(1) << "Syncing tab " << tab_id.id() << " from window "
-           << tab_delegate->GetWindowId().id();
-
   int tab_node_id =
       session_tracker_->LookupTabNodeFromTabId(current_session_tag_, tab_id);
 
-  if (tab_node_id != TabNodePool::kInvalidTabNodeID) {
-    // Already associated, so do nothing.
-  } else if (has_tabbed_window) {
+  if (tab_node_id == TabNodePool::kInvalidTabNodeID) {
     // Allocate a new (or reused) sync node for this tab.
     tab_node_id = session_tracker_->AssociateLocalTabWithFreeTabNode(tab_id);
     DCHECK_NE(TabNodePool::kInvalidTabNodeID, tab_node_id)
         << "https://crbug.com/639009";
-  } else {
-    // Only allowed to allocate sync ids when we have native data, which is only
-    // true when we have a tabbed window. Without a sync id we cannot sync this
-    // data, the tracker cannot even really track it. So don't do any more work.
-    // This effectively breaks syncing custom tabs when the native browser isn't
-    // fully loaded. Ideally this is fixed by saving tab data and sync data
-    // atomically, see https://crbug.com/681921.
-    return;
   }
 
+  DVLOG(1) << "Syncing tab " << tab_id << " from window "
+           << tab_delegate->GetWindowId() << " using tab node " << tab_node_id;
+
   // Get the previously synced url.
   sessions::SessionTab* session_tab =
       session_tracker_->GetTab(current_session_tag_, tab_id);
@@ -359,14 +366,13 @@
       modified_tab->GetCurrentEntryIndex(), &current);
   delegate_->TrackLocalNavigationId(current.timestamp(), current.unique_id());
 
-  bool found_tabbed_window = ScanForTabbedWindow();
   std::unique_ptr<WriteBatch> batch = delegate_->CreateLocalSessionWriteBatch();
-  AssociateTab(modified_tab, found_tabbed_window, batch.get());
+  AssociateTab(modified_tab, batch.get());
   // Note, we always associate windows because it's possible a tab became
   // "interesting" by going to a valid URL, in which case it needs to be added
   // to the window's tab information. Similarly, if a tab became
   // "uninteresting", we remove it from the window's tab information.
-  AssociateWindows(DONT_RELOAD_TABS, found_tabbed_window, batch.get());
+  AssociateWindows(DONT_RELOAD_TABS, batch.get());
   batch->Commit();
 }
 
@@ -399,7 +405,10 @@
   // Update the window id on the SessionTab itself.
   sessions::SessionTab* local_tab =
       session_tracker_->GetTab(current_session_tag_, tab_id);
-  // TODO(mastiz): Return early if the window ID hasn't changed.
+  if (local_tab->window_id == new_window_id) {
+    // Nothing to update.
+    return;
+  }
   local_tab->window_id = new_window_id;
 
   // Filter out placeholder tabs that have been associated but don't have known
@@ -409,7 +418,7 @@
   }
 
   // Rewrite the specifics based on the reassociated SessionTab to preserve
-  // the new tab and window ids.
+  // the new window id.
   auto specifics = std::make_unique<sync_pb::SessionSpecifics>();
   local_tab->ToSyncData().Swap(specifics->mutable_tab());
   specifics->set_session_tag(current_session_tag_);
@@ -478,16 +487,4 @@
   return specifics;
 }
 
-bool LocalSessionEventHandlerImpl::ScanForTabbedWindow() {
-  for (const auto& window_iter_pair :
-       sessions_client_->GetSyncedWindowDelegatesGetter()
-           ->GetSyncedWindowDelegates()) {
-    const SyncedWindowDelegate* window_delegate = window_iter_pair.second;
-    if (window_delegate->IsTypeTabbed() && IsWindowSyncable(*window_delegate)) {
-      return true;
-    }
-  }
-  return false;
-}
-
 }  // namespace sync_sessions
diff --git a/components/sync_sessions/local_session_event_handler_impl.h b/components/sync_sessions/local_session_event_handler_impl.h
index 30f3a67b..9272381 100644
--- a/components/sync_sessions/local_session_event_handler_impl.h
+++ b/components/sync_sessions/local_session_event_handler_impl.h
@@ -80,23 +80,20 @@
   enum ReloadTabsOption { RELOAD_TABS, DONT_RELOAD_TABS };
 
   void AssociateWindows(ReloadTabsOption option,
-                        bool has_tabbed_window,
                         WriteBatch* batch);
 
   // Loads and reassociates the local tab referenced in |tab|.
   // |batch| must not be null. This function will append necessary
-  // changes for processing later. Will only assign a new sync id if there is
-  // a tabbed window, which results in failure for tabs without sync ids yet.
+  // changes for processing later.
   void AssociateTab(SyncedTabDelegate* const tab,
-                    bool has_tabbed_window,
                     WriteBatch* batch);
 
   // It's possible that when we associate windows, tabs aren't all loaded
   // into memory yet (e.g on android) and we don't have a WebContents. In this
   // case we can't do a full association, but we still want to update tab IDs
   // as they may have changed after a session was restored.  This method
-  // compares new_tab_id and new_window_id against the previously persisted tab
-  // ID and window ID (from our TabNodePool) and updates them if either differs.
+  // new_window_id against the previously persisted window ID (from our
+  // TabNodePool) and updates it.
   void AssociateRestoredPlaceholderTab(const SyncedTabDelegate& tab_delegate,
                                        SessionID tab_id,
                                        SessionID new_window_id,
@@ -112,12 +109,6 @@
   // Update |tab_specifics| with the corresponding task ids.
   void WriteTasksIntoSpecifics(sync_pb::SessionTab* tab_specifics);
 
-  // On Android, it's possible to not have any tabbed windows when only custom
-  // tabs are currently open. This means that there is tab data that will be
-  // restored later, but we cannot access it. This method is an elaborate way to
-  // check if we're currently in that state or not.
-  bool ScanForTabbedWindow();
-
   // Injected dependencies (not owned).
   Delegate* const delegate_;
   SyncSessionsClient* const sessions_client_;
diff --git a/components/sync_sessions/local_session_event_handler_impl_unittest.cc b/components/sync_sessions/local_session_event_handler_impl_unittest.cc
index 862e908..7aeb24bb 100644
--- a/components/sync_sessions/local_session_event_handler_impl_unittest.cc
+++ b/components/sync_sessions/local_session_event_handler_impl_unittest.cc
@@ -528,6 +528,35 @@
   AddTab(kWindowId1, kBar1, kTabId2);
 }
 
+TEST_F(LocalSessionEventHandlerImplTest, PropagateNewCustomTab) {
+  InitHandler();
+
+  // Tab creation triggers an update event due to the tab parented notification,
+  // so the event handler issues two commits as well (one for tab creation, one
+  // for tab update). During the first update, however, the tab is not syncable
+  // and is hence skipped.
+  auto tab_create_mock_batch = std::make_unique<StrictMock<MockWriteBatch>>();
+  EXPECT_CALL(*tab_create_mock_batch,
+              Put(Pointee(MatchesHeader(kSessionTag, {}, {}))));
+  EXPECT_CALL(*tab_create_mock_batch, Commit());
+
+  auto navigation_mock_batch = std::make_unique<StrictMock<MockWriteBatch>>();
+  EXPECT_CALL(
+      *navigation_mock_batch,
+      Put(Pointee(MatchesHeader(kSessionTag, {kWindowId1}, {kTabId1}))));
+  EXPECT_CALL(*navigation_mock_batch,
+              Put(Pointee(MatchesTab(kSessionTag, kWindowId1, kTabId1,
+                                     /*tab_node_id=*/0, /*urls=*/{kFoo1}))));
+  EXPECT_CALL(*navigation_mock_batch, Commit());
+
+  EXPECT_CALL(mock_delegate_, CreateLocalSessionWriteBatch())
+      .WillOnce(Return(ByMove(std::move(tab_create_mock_batch))))
+      .WillOnce(Return(ByMove(std::move(navigation_mock_batch))));
+
+  AddWindow(kWindowId1, sync_pb::SessionWindow_BrowserType_TYPE_CUSTOM_TAB);
+  AddTab(kWindowId1, kFoo1, kTabId1);
+}
+
 TEST_F(LocalSessionEventHandlerImplTest, PropagateNewWindow) {
   AddWindow(kWindowId1);
   AddTab(kWindowId1, kFoo1, kTabId1);
diff --git a/components/sync_sessions/session_sync_bridge_unittest.cc b/components/sync_sessions/session_sync_bridge_unittest.cc
index da54970..85899ff 100644
--- a/components/sync_sessions/session_sync_bridge_unittest.cc
+++ b/components/sync_sessions/session_sync_bridge_unittest.cc
@@ -518,16 +518,17 @@
 }
 
 TEST_F(SessionSyncBridgeTest, ShouldUpdateIdsDuringRestore) {
-  const int kWindowId = 1000001;
-  const int kTabId1 = 1000002;
-  const int kTabId2 = 1000003;
+  const int kWindowId1 = 1000001;
+  const int kWindowId2 = 1000002;
+  const int kTabId1 = 1000003;
+  const int kTabId2 = 1000004;
   // Zero is the first assigned tab node ID.
   const int kTabNodeId1 = 0;
   const int kTabNodeId2 = 1;
 
-  AddWindow(kWindowId);
-  AddTab(kWindowId, "http://foo.com/", kTabId1);
-  AddTab(kWindowId, "http://bar.com/", kTabId2);
+  AddWindow(kWindowId1);
+  AddTab(kWindowId1, "http://foo.com/", kTabId1);
+  AddTab(kWindowId1, "http://bar.com/", kTabId2);
 
   const std::string header_storage_key =
       SessionStore::GetHeaderStorageKey(kLocalSessionTag);
@@ -541,14 +542,14 @@
 
   ASSERT_THAT(GetData(header_storage_key),
               EntityDataHasSpecifics(MatchesHeader(
-                  kLocalSessionTag, {kWindowId}, {kTabId1, kTabId2})));
+                  kLocalSessionTag, {kWindowId1}, {kTabId1, kTabId2})));
   ASSERT_THAT(
       GetData(tab_storage_key1),
-      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId, kTabId1,
+      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId1, kTabId1,
                                         kTabNodeId1, {"http://foo.com/"})));
   ASSERT_THAT(
       GetData(tab_storage_key2),
-      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId, kTabId2,
+      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId1, kTabId2,
                                         kTabNodeId2, {"http://bar.com/"})));
 
   ShutdownBridge();
@@ -560,7 +561,7 @@
   PlaceholderTabDelegate placeholder_tab2(
       SessionID::FromSerializedValue(kTabId2));
   ResetWindows();
-  TestSyncedWindowDelegate* window = AddWindow(kWindowId);
+  TestSyncedWindowDelegate* window = AddWindow(kWindowId2);
   window->OverrideTabAt(0, &placeholder_tab1);
   window->OverrideTabAt(1, &placeholder_tab2);
 
@@ -569,16 +570,16 @@
   EXPECT_CALL(mock_processor(),
               Put(header_storage_key,
                   EntityDataHasSpecifics(MatchesHeader(
-                      kLocalSessionTag, {kWindowId}, {kTabId1, kTabId2})),
+                      kLocalSessionTag, {kWindowId2}, {kTabId1, kTabId2})),
                   _));
   EXPECT_CALL(mock_processor(), Put(tab_storage_key1,
                                     EntityDataHasSpecifics(MatchesTab(
-                                        kLocalSessionTag, kWindowId, kTabId1,
+                                        kLocalSessionTag, kWindowId2, kTabId1,
                                         kTabNodeId1, {"http://foo.com/"})),
                                     _));
   EXPECT_CALL(mock_processor(), Put(tab_storage_key2,
                                     EntityDataHasSpecifics(MatchesTab(
-                                        kLocalSessionTag, kWindowId, kTabId2,
+                                        kLocalSessionTag, kWindowId2, kTabId2,
                                         kTabNodeId2, {"http://bar.com/"})),
                                     _));
 
@@ -588,14 +589,14 @@
 
   EXPECT_THAT(GetData(header_storage_key),
               EntityDataHasSpecifics(MatchesHeader(
-                  kLocalSessionTag, {kWindowId}, {kTabId1, kTabId2})));
+                  kLocalSessionTag, {kWindowId2}, {kTabId1, kTabId2})));
   EXPECT_THAT(
       GetData(tab_storage_key1),
-      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId, kTabId1,
+      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId2, kTabId1,
                                         kTabNodeId1, {"http://foo.com/"})));
   EXPECT_THAT(
       GetData(tab_storage_key2),
-      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId, kTabId2,
+      EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, kWindowId2, kTabId2,
                                         kTabNodeId2, {"http://bar.com/"})));
 
   EXPECT_THAT(
@@ -603,27 +604,28 @@
       UnorderedElementsAre(
           Pair(header_storage_key,
                EntityDataHasSpecifics(MatchesHeader(
-                   kLocalSessionTag, {kWindowId}, {kTabId1, kTabId2}))),
+                   kLocalSessionTag, {kWindowId2}, {kTabId1, kTabId2}))),
           Pair(tab_storage_key1, EntityDataHasSpecifics(MatchesTab(
-                                     kLocalSessionTag, kWindowId, kTabId1,
+                                     kLocalSessionTag, kWindowId2, kTabId1,
                                      kTabNodeId1, {"http://foo.com/"}))),
           Pair(tab_storage_key2, EntityDataHasSpecifics(MatchesTab(
-                                     kLocalSessionTag, kWindowId, kTabId2,
+                                     kLocalSessionTag, kWindowId2, kTabId2,
                                      kTabNodeId2, {"http://bar.com/"})))));
 }
 
 TEST_F(SessionSyncBridgeTest,
        ShouldIgnoreUnsyncablePlaceholderTabDuringRestore) {
-  const int kWindowId = 1000001;
+  const int kWindowId1 = 1000001;
+  const int kWindowId2 = 1000002;
   const int kTabId1 = 1000002;
   const int kTabId2 = 1000003;
   // Zero is the first assigned tab node ID.
   const int kTabNodeId1 = 0;
 
-  AddWindow(kWindowId);
-  AddTab(kWindowId, "http://foo.com/", kTabId1);
+  AddWindow(kWindowId1);
+  AddTab(kWindowId1, "http://foo.com/", kTabId1);
   // Tab 2 is unsyncable because of the URL scheme.
-  AddTab(kWindowId, "about:blank", kTabId2);
+  AddTab(kWindowId1, "about:blank", kTabId2);
 
   const std::string header_storage_key =
       SessionStore::GetHeaderStorageKey(kLocalSessionTag);
@@ -638,9 +640,9 @@
       UnorderedElementsAre(
           Pair(header_storage_key,
                EntityDataHasSpecifics(
-                   MatchesHeader(kLocalSessionTag, {kWindowId}, {kTabId1}))),
+                   MatchesHeader(kLocalSessionTag, {kWindowId1}, {kTabId1}))),
           Pair(tab_storage_key1, EntityDataHasSpecifics(MatchesTab(
-                                     kLocalSessionTag, kWindowId, kTabId1,
+                                     kLocalSessionTag, kWindowId1, kTabId1,
                                      kTabNodeId1, {"http://foo.com/"})))));
 
   ShutdownBridge();
@@ -652,7 +654,7 @@
   PlaceholderTabDelegate placeholder_tab2(
       SessionID::FromSerializedValue(kTabId2));
   ResetWindows();
-  TestSyncedWindowDelegate* window = AddWindow(kWindowId);
+  TestSyncedWindowDelegate* window = AddWindow(kWindowId2);
   window->OverrideTabAt(0, &placeholder_tab1);
   window->OverrideTabAt(1, &placeholder_tab2);
 
@@ -665,20 +667,21 @@
       UnorderedElementsAre(
           Pair(header_storage_key,
                EntityDataHasSpecifics(
-                   MatchesHeader(kLocalSessionTag, {kWindowId}, {kTabId1}))),
+                   MatchesHeader(kLocalSessionTag, {kWindowId2}, {kTabId1}))),
           Pair(tab_storage_key1, EntityDataHasSpecifics(MatchesTab(
-                                     kLocalSessionTag, kWindowId, kTabId1,
+                                     kLocalSessionTag, kWindowId2, kTabId1,
                                      kTabNodeId1, {"http://foo.com/"})))));
 }
 
 // Ensure that tabbed windows from a previous session are preserved if no
 // windows are present on startup.
 TEST_F(SessionSyncBridgeTest, ShouldRestoreTabbedDataIfNoWindowsDuringStartup) {
-  const int kWindowId = 1000001;
+  const int kWindowId1 = 1000001;
+  const int kWindowId2 = 1000002;
   const int kTabNodeId = 0;
 
-  AddWindow(kWindowId);
-  TestSyncedTabDelegate* tab = AddTab(kWindowId, "http://foo.com/");
+  AddWindow(kWindowId1);
+  TestSyncedTabDelegate* tab = AddTab(kWindowId1, "http://foo.com/");
 
   const std::string header_storage_key =
       SessionStore::GetHeaderStorageKey(kLocalSessionTag);
@@ -725,7 +728,7 @@
                       kLocalSessionTag, /*window_id=*/_, /*tab_id=*/_,
                       kTabNodeId, {"http://foo.com/", "http://bar.com/"})),
                   _));
-  AddWindow(kWindowId)->OverrideTabAt(0, tab);
+  AddWindow(kWindowId2)->OverrideTabAt(0, tab);
   tab->Navigate("http://bar.com/");
 }
 
@@ -758,17 +761,18 @@
   InitializeBridge();
   StartSyncing();
 
-  // The previous session should be preserved. The transient window cannot be
-  // synced because we do not have enough local data to ensure that we wouldn't
-  // vend the same sync ID if our persistent storage didn't match upon the last
-  // shutdown.
-  EXPECT_THAT(GetAllData(),
-              UnorderedElementsAre(
-                  Pair(_, EntityDataHasSpecifics(
-                              MatchesHeader(kLocalSessionTag, _, _))),
-                  Pair(_, EntityDataHasSpecifics(MatchesTab(
-                              kLocalSessionTag, _, _,
-                              /*tab_node_id=*/0, {"http://foo.com/"})))));
+  // The previous session should be preserved, together with the new custom tab.
+  EXPECT_THAT(
+      GetAllData(),
+      UnorderedElementsAre(
+          Pair(_,
+               EntityDataHasSpecifics(MatchesHeader(kLocalSessionTag, _, _))),
+          Pair(_, EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, _, _,
+                                                    /*tab_node_id=*/0,
+                                                    {"http://foo.com/"}))),
+          Pair(_, EntityDataHasSpecifics(MatchesTab(kLocalSessionTag, _, _,
+                                                    /*tab_node_id=*/1,
+                                                    {"http://bar.com/"})))));
 }
 
 // Ensure that tabbed windows from a previous session are preserved and combined
@@ -815,19 +819,24 @@
 }
 
 // Ensure that, in a scenario without prior sync data, encountering a custom
-// tab only ( no tabbed window) does not vend new sync IDs.
-TEST_F(SessionSyncBridgeTest, ShouldIgnoreIfCustomTabOnlyOnStartup) {
+// tab only (no tabbed window) starts syncing that tab.
+TEST_F(SessionSyncBridgeTest, ShouldAssociateIfCustomTabOnlyOnStartup) {
   const int kWindowId = 1000001;
+  const int kTabId = 1000002;
 
   AddWindow(kWindowId, sync_pb::SessionWindow_BrowserType_TYPE_CUSTOM_TAB);
-  AddTab(kWindowId, "http://foo.com/");
+  AddTab(kWindowId, "http://foo.com/", kTabId);
 
   InitializeBridge();
   StartSyncing();
 
   EXPECT_THAT(GetAllData(),
-              UnorderedElementsAre(Pair(_, EntityDataHasSpecifics(MatchesHeader(
-                                               kLocalSessionTag, _, _)))));
+              UnorderedElementsAre(
+                  Pair(_, EntityDataHasSpecifics(MatchesHeader(
+                              kLocalSessionTag, {kWindowId}, {kTabId}))),
+                  Pair(_, EntityDataHasSpecifics(MatchesTab(
+                              kLocalSessionTag, kWindowId, kTabId,
+                              /*tab_node_id=*/0, {"http://foo.com/"})))));
 }
 
 // Ensure that all tabs are exposed in a scenario where only a custom tab
@@ -840,45 +849,35 @@
   const int kTabId2 = 1000004;
 
   AddWindow(kWindowId1, sync_pb::SessionWindow_BrowserType_TYPE_CUSTOM_TAB);
-  TestSyncedTabDelegate* custom_tab =
-      AddTab(kWindowId1, "http://foo.com/", kTabId1);
+  AddTab(kWindowId1, "http://foo.com/", kTabId1);
 
   InitializeBridge();
   StartSyncing();
 
   ASSERT_THAT(GetAllData(),
-              UnorderedElementsAre(Pair(_, EntityDataHasSpecifics(MatchesHeader(
-                                               kLocalSessionTag, _, _)))));
+              UnorderedElementsAre(
+                  Pair(_, EntityDataHasSpecifics(MatchesHeader(
+                              kLocalSessionTag, {kWindowId1}, {kTabId1}))),
+                  Pair(_, EntityDataHasSpecifics(MatchesTab(
+                              kLocalSessionTag, kWindowId1, kTabId1,
+                              /*tab_node_id=*/0, {"http://foo.com/"})))));
 
   // Load the actual tabbed window, now that we're syncing.
   AddWindow(kWindowId2);
   AddTab(kWindowId2, "http://bar.com/", kTabId2);
 
-  // The local change should be created and tracked correctly. This doesn't
-  // actually start syncing the custom tab yet, because the tab itself isn't
-  // associated yet.
-  EXPECT_THAT(GetAllData(),
-              UnorderedElementsAre(
-                  Pair(_, EntityDataHasSpecifics(MatchesHeader(
-                              kLocalSessionTag, {kWindowId2}, {kTabId2}))),
-                  Pair(_, EntityDataHasSpecifics(MatchesTab(
-                              kLocalSessionTag, kWindowId2, kTabId2,
-                              /*tab_node_id=*/0, {"http://bar.com/"})))));
-
-  // Now trigger OnLocalTabModified() for the custom tab again, it should sync.
-  custom_tab->Navigate("http://baz.com/");
+  // The local change should be created and tracked correctly.
   EXPECT_THAT(GetAllData(),
               UnorderedElementsAre(
                   Pair(_, EntityDataHasSpecifics(MatchesHeader(
                               kLocalSessionTag, {kWindowId1, kWindowId2},
                               {kTabId1, kTabId2}))),
                   Pair(_, EntityDataHasSpecifics(MatchesTab(
-                              kLocalSessionTag, kWindowId2, kTabId2,
-                              /*tab_node_id=*/0, {"http://bar.com/"}))),
-                  Pair(_, EntityDataHasSpecifics(MatchesTab(
                               kLocalSessionTag, kWindowId1, kTabId1,
-                              /*tab_node_id=*/1,
-                              {"http://foo.com/", "http://baz.com/"})))));
+                              /*tab_node_id=*/0, {"http://foo.com/"}))),
+                  Pair(_, EntityDataHasSpecifics(MatchesTab(
+                              kLocalSessionTag, kWindowId2, kTabId2,
+                              /*tab_node_id=*/1, {"http://bar.com/"})))));
 }
 
 TEST_F(SessionSyncBridgeTest, ShouldDisableSyncAndReenable) {
diff --git a/components/sync_sessions/sessions_sync_manager_unittest.cc b/components/sync_sessions/sessions_sync_manager_unittest.cc
index fa9ec44..6481cb129 100644
--- a/components/sync_sessions/sessions_sync_manager_unittest.cc
+++ b/components/sync_sessions/sessions_sync_manager_unittest.cc
@@ -485,36 +485,13 @@
   manager()->StopSyncing(syncer::SESSIONS);
   ResetWindows();
   window = AddWindow(sync_pb::SessionWindow_BrowserType_TYPE_CUSTOM_TAB);
-  TestSyncedTabDelegate* custom_tab = AddTab(window->GetSessionId(), kBar1);
+  AddTab(window->GetSessionId(), kBar1);
   InitWithSyncDataTakeOutput(ConvertToRemote(in), &out);
 
-  // The previous session should be preserved. The transient window cannot be
-  // synced because we do not have enough local data to ensure that we wouldn't
-  // vend the same sync id if our persistent storage didn't match upon the last
-  // shutdown.
-  ASSERT_TRUE(ChangeTypeMatches(out, {SyncChange::ACTION_UPDATE}));
-  VerifyLocalHeaderChange(out[0], 1, 1);
-  out.clear();
-
-  // Now re-create local data and modify it.
-  TestSyncedWindowDelegate* alive_again = AddWindow();
-  alive_again->OverrideTabAt(0, tab);
-  tab->Navigate(kBaz1);
-
-  // The local change should be created and tracked correctly. This doesn't
-  // actually start syncing the custom tab yet, because the tab itself isn't
-  // associated yet.
-  ASSERT_TRUE(ChangeTypeMatches(
-      out, {SyncChange::ACTION_UPDATE, SyncChange::ACTION_UPDATE}));
-  VerifyLocalTabChange(out[0], 3, kBaz1);
-  VerifyLocalHeaderChange(out[1], 1, 1);
-  out.clear();
-
-  // Now trigger OnLocalTabModified() for the custom tab again, it should sync.
-  custom_tab->Navigate(kBar2);
+  // The previous session should be preserved, together with the new custom tab.
   ASSERT_TRUE(ChangeTypeMatches(
       out, {SyncChange::ACTION_ADD, SyncChange::ACTION_UPDATE}));
-  VerifyLocalTabChange(out[0], 2, kBar2);
+  VerifyLocalTabChange(out[0], 1, kBar1);
   VerifyLocalHeaderChange(out[1], 2, 2);
 }
 
@@ -1822,9 +1799,12 @@
   in.push_back(CreateRemoteData(t1_entity));
   out.clear();
   manager()->StopSyncing(syncer::SESSIONS);
+  ResetWindows();
 
   PlaceholderTabDelegate t1_override(
       SessionID::FromSerializedValue(t1_entity.session().tab().tab_id()));
+  window = AddWindow();
+  window->OverrideTabAt(0, tab1);
   window->OverrideTabAt(1, &t1_override);
   InitWithSyncDataTakeOutput(in, &out);
 
diff --git a/components/viz/OWNERS b/components/viz/OWNERS
index de51ef0..7adfede 100644
--- a/components/viz/OWNERS
+++ b/components/viz/OWNERS
@@ -13,7 +13,7 @@
 vmpstr@chromium.org
 weiliangc@chromium.org
 
-# CopyOutputRequests/Results
+# CopyOutputRequests/Results and FrameSinkVideoCapture
 miu@chromium.org
 
 # renderers (GL/Skia/Software)
diff --git a/components/viz/host/BUILD.gn b/components/viz/host/BUILD.gn
index dea8270..f59610d 100644
--- a/components/viz/host/BUILD.gn
+++ b/components/viz/host/BUILD.gn
@@ -92,6 +92,5 @@
     ":host",
     "//base/test:test_support",
     "//components/viz/test:test_support",
-    "//mojo/edk",
   ]
 }
diff --git a/components/viz/host/client_frame_sink_video_capturer.cc b/components/viz/host/client_frame_sink_video_capturer.cc
index 331fa07..433c6d7 100644
--- a/components/viz/host/client_frame_sink_video_capturer.cc
+++ b/components/viz/host/client_frame_sink_video_capturer.cc
@@ -4,6 +4,8 @@
 
 #include "components/viz/host/client_frame_sink_video_capturer.h"
 
+#include <utility>
+
 namespace viz {
 
 namespace {
@@ -57,7 +59,7 @@
 }
 
 void ClientFrameSinkVideoCapturer::ChangeTarget(
-    const FrameSinkId& frame_sink_id) {
+    const base::Optional<FrameSinkId>& frame_sink_id) {
   target_ = frame_sink_id;
   capturer_->ChangeTarget(frame_sink_id);
 }
@@ -109,11 +111,6 @@
                              update_rect, content_rect, std::move(callbacks));
 }
 
-void ClientFrameSinkVideoCapturer::OnTargetLost(
-    const FrameSinkId& frame_sink_id) {
-  consumer_->OnTargetLost(frame_sink_id);
-}
-
 void ClientFrameSinkVideoCapturer::OnStopped() {
   consumer_->OnStopped();
 }
@@ -137,7 +134,7 @@
   if (auto_throttling_enabled_)
     capturer_->SetAutoThrottlingEnabled(*auto_throttling_enabled_);
   if (target_)
-    capturer_->ChangeTarget(*target_);
+    capturer_->ChangeTarget(target_);
   if (is_started_)
     StartInternal();
 }
diff --git a/components/viz/host/client_frame_sink_video_capturer.h b/components/viz/host/client_frame_sink_video_capturer.h
index dd6c5fb..71ad5a5 100644
--- a/components/viz/host/client_frame_sink_video_capturer.h
+++ b/components/viz/host/client_frame_sink_video_capturer.h
@@ -17,8 +17,12 @@
 namespace viz {
 
 // Client library for using FrameSinkVideoCapturer. Clients should use this
-// class instead of talking directly to FrameSinkVideoCapturer in order to
-// survive Viz crashes.
+// instead of talking directly to FrameSinkVideoCapturer in order to survive Viz
+// crashes.
+//
+// An instance of ClientFrameSinkVideoCapturer must only be used in the same
+// sequence (e.g., single-threaded).
+//
 // TODO(samans): Move this class and all its dependencies to the client
 // directory.
 class VIZ_HOST_EXPORT ClientFrameSinkVideoCapturer
@@ -38,7 +42,7 @@
                                 const gfx::Size& max_size,
                                 bool use_fixed_aspect_ratio);
   void SetAutoThrottlingEnabled(bool enabled);
-  void ChangeTarget(const FrameSinkId& frame_sink_id);
+  void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id);
   void Stop();
   void RequestRefreshFrame();
 
@@ -77,7 +81,6 @@
       const gfx::Rect& update_rect,
       const gfx::Rect& content_rect,
       mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) final;
-  void OnTargetLost(const FrameSinkId& frame_sink_id) final;
   void OnStopped() final;
 
   // Establishes connection to FrameSinkVideoCapturer and sends the existing
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 5d64c66..a9ac7d2 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -410,6 +410,5 @@
     ":service",
     "//base/test:test_support",
     "//components/viz/test:test_support",
-    "//mojo/edk",
   ]
 }
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index 7a8c0af..6b489aa 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <limits>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -93,8 +94,9 @@
     resolved_target_->AttachCaptureClient(this);
     RefreshEntireSourceSoon();
   } else {
-    // Not calling consumer_->OnTargetLost() because SetResolvedTarget() should
-    // be called by FrameSinkManagerImpl with a valid target very soon.
+    // The capturer will remain idle until either: 1) the requested target is
+    // re-resolved by the |frame_sink_manager_|, or 2) a new target is set via a
+    // call to ChangeTarget().
   }
 }
 
@@ -102,13 +104,6 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   SetResolvedTarget(nullptr);
-
-  // TODO(crbug/754872): Remove this, since it's misleading: Resolved targets
-  // can be temporarily deleted and then re-created. So, the target really isn't
-  // lost.
-  if (requested_target_.is_valid() && consumer_) {
-    consumer_->OnTargetLost(requested_target_);
-  }
 }
 
 void FrameSinkVideoCapturerImpl::SetFormat(media::VideoPixelFormat format,
@@ -206,12 +201,17 @@
 }
 
 void FrameSinkVideoCapturerImpl::ChangeTarget(
-    const FrameSinkId& frame_sink_id) {
+    const base::Optional<FrameSinkId>& frame_sink_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  requested_target_ = frame_sink_id;
-  SetResolvedTarget(
-      frame_sink_manager_->FindCapturableFrameSink(frame_sink_id));
+  if (frame_sink_id) {
+    requested_target_ = *frame_sink_id;
+    SetResolvedTarget(
+        frame_sink_manager_->FindCapturableFrameSink(requested_target_));
+  } else {
+    requested_target_ = FrameSinkId();
+    SetResolvedTarget(nullptr);
+  }
 }
 
 void FrameSinkVideoCapturerImpl::Start(
@@ -474,15 +474,15 @@
       media::LetterboxVideoFrame(frame.get(), gfx::Rect());
     }
     dirty_rect_ = gfx::Rect();
-    DidCaptureFrame(frame_number, oracle_frame_number, std::move(frame),
-                    gfx::Rect());
+    DidCaptureFrame(frame_number, oracle_frame_number, gfx::Rect(),
+                    std::move(frame));
     return;
   }
 
   // For passive refreshes, just deliver the resurrected frame.
   if (dirty_rect_.IsEmpty()) {
-    DidCaptureFrame(frame_number, oracle_frame_number, std::move(frame),
-                    content_rect);
+    DidCaptureFrame(frame_number, oracle_frame_number, content_rect,
+                    std::move(frame));
     return;
   }
 
@@ -493,7 +493,7 @@
           : CopyOutputRequest::ResultFormat::RGBA_BITMAP,
       base::BindOnce(&FrameSinkVideoCapturerImpl::DidCopyFrame,
                      capture_weak_factory_.GetWeakPtr(), frame_number,
-                     oracle_frame_number, std::move(frame), content_rect)));
+                     oracle_frame_number, content_rect, std::move(frame))));
   request->set_source(copy_request_source_);
   request->set_area(gfx::Rect(source_size));
   request->SetScaleRatio(
@@ -510,8 +510,8 @@
 void FrameSinkVideoCapturerImpl::DidCopyFrame(
     int64_t frame_number,
     OracleFrameNumber oracle_frame_number,
-    scoped_refptr<VideoFrame> frame,
     const gfx::Rect& content_rect,
+    scoped_refptr<VideoFrame> frame,
     std::unique_ptr<CopyOutputResult> result) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_GE(frame_number, next_delivery_frame_number_);
@@ -566,15 +566,15 @@
     }
   }
 
-  DidCaptureFrame(frame_number, oracle_frame_number, std::move(frame),
-                  content_rect);
+  DidCaptureFrame(frame_number, oracle_frame_number, content_rect,
+                  std::move(frame));
 }
 
 void FrameSinkVideoCapturerImpl::DidCaptureFrame(
     int64_t frame_number,
     OracleFrameNumber oracle_frame_number,
-    scoped_refptr<VideoFrame> frame,
-    const gfx::Rect& content_rect) {
+    const gfx::Rect& content_rect,
+    scoped_refptr<VideoFrame> frame) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_GE(frame_number, next_delivery_frame_number_);
 
@@ -585,12 +585,12 @@
 
   // Ensure frames are delivered in-order by using a min-heap, and only
   // deliver the next frame(s) in-sequence when they are found at the top.
-  delivery_queue_.emplace(frame_number, oracle_frame_number, std::move(frame),
-                          content_rect);
+  delivery_queue_.emplace(frame_number, oracle_frame_number, content_rect,
+                          std::move(frame));
   while (delivery_queue_.top().frame_number == next_delivery_frame_number_) {
     auto& next = delivery_queue_.top();
-    MaybeDeliverFrame(next.oracle_frame_number, std::move(next.frame),
-                      next.content_rect);
+    MaybeDeliverFrame(next.oracle_frame_number, next.content_rect,
+                      std::move(next.frame));
     ++next_delivery_frame_number_;
     delivery_queue_.pop();
     if (delivery_queue_.empty()) {
@@ -601,8 +601,8 @@
 
 void FrameSinkVideoCapturerImpl::MaybeDeliverFrame(
     OracleFrameNumber oracle_frame_number,
-    scoped_refptr<VideoFrame> frame,
-    const gfx::Rect& content_rect) {
+    const gfx::Rect& content_rect,
+    scoped_refptr<VideoFrame> frame) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // The Oracle has the final say in whether frame delivery will proceed. It
@@ -694,14 +694,14 @@
 }
 
 FrameSinkVideoCapturerImpl::CapturedFrame::CapturedFrame(
-    int64_t fn,
-    OracleFrameNumber ofn,
-    scoped_refptr<VideoFrame> fr,
-    const gfx::Rect& cr)
-    : frame_number(fn),
-      oracle_frame_number(ofn),
-      frame(std::move(fr)),
-      content_rect(cr) {}
+    int64_t frame_number,
+    OracleFrameNumber oracle_frame_number,
+    const gfx::Rect& content_rect,
+    scoped_refptr<media::VideoFrame> frame)
+    : frame_number(frame_number),
+      oracle_frame_number(oracle_frame_number),
+      content_rect(content_rect),
+      frame(std::move(frame)) {}
 
 FrameSinkVideoCapturerImpl::CapturedFrame::CapturedFrame(
     const CapturedFrame& other) = default;
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
index c1c552d..09f9eb02 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <queue>
 
 #include "base/macros.h"
@@ -17,7 +18,6 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "base/unguessable_token.h"
-#include "components/viz/common/frame_sinks/begin_frame_args.h"
 #include "components/viz/common/quads/compositor_frame_metadata.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h"
@@ -37,8 +37,8 @@
 
 namespace viz {
 
-class FrameSinkVideoCapturerManager;
 class CopyOutputResult;
+class FrameSinkVideoCapturerManager;
 
 // Captures the frames of a CompositorFrameSink's surface as a video stream. See
 // mojom for usage details.
@@ -100,7 +100,7 @@
                                 const gfx::Size& max_size,
                                 bool use_fixed_aspect_ratio) final;
   void SetAutoThrottlingEnabled(bool enabled) final;
-  void ChangeTarget(const FrameSinkId& frame_sink_id) final;
+  void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id) final;
   void Start(mojom::FrameSinkVideoConsumerPtr consumer) final;
   void Stop() final;
   void RequestRefreshFrame() final;
@@ -174,8 +174,8 @@
   // |content_rect| region of a [possibly letterboxed] video |frame|.
   void DidCopyFrame(int64_t frame_number,
                     OracleFrameNumber oracle_frame_number,
-                    scoped_refptr<media::VideoFrame> frame,
                     const gfx::Rect& content_rect,
+                    scoped_refptr<media::VideoFrame> frame,
                     std::unique_ptr<CopyOutputResult> result);
 
   // Places the frame in the |delivery_queue_| and calls MaybeDeliverFrame(),
@@ -183,16 +183,16 @@
   // completed, but unsuccessful capture.
   void DidCaptureFrame(int64_t frame_number,
                        OracleFrameNumber oracle_frame_number,
-                       scoped_refptr<media::VideoFrame> frame,
-                       const gfx::Rect& content_rect);
+                       const gfx::Rect& content_rect,
+                       scoped_refptr<media::VideoFrame> frame);
 
   // Delivers a |frame| to the consumer, if the VideoCaptureOracle allows
   // it. |frame| can be null to indicate a completed, but unsuccessful capture.
   // In this case, some state will be updated, but nothing will be sent to the
   // consumer.
   void MaybeDeliverFrame(OracleFrameNumber oracle_frame_number,
-                         scoped_refptr<media::VideoFrame> frame,
-                         const gfx::Rect& content_rect);
+                         const gfx::Rect& content_rect,
+                         scoped_refptr<media::VideoFrame> frame);
 
   // For ARGB format, ensures that every dimension of |size| is positive. For
   // I420 format, ensures that every dimension is even and at least 2.
@@ -262,12 +262,12 @@
   struct CapturedFrame {
     int64_t frame_number;
     OracleFrameNumber oracle_frame_number;
-    scoped_refptr<media::VideoFrame> frame;
     gfx::Rect content_rect;
+    scoped_refptr<media::VideoFrame> frame;
     CapturedFrame(int64_t frame_number,
                   OracleFrameNumber oracle_frame_number,
-                  scoped_refptr<media::VideoFrame> frame,
-                  const gfx::Rect& content_rect);
+                  const gfx::Rect& content_rect,
+                  scoped_refptr<media::VideoFrame> frame);
     CapturedFrame(const CapturedFrame& other);
     ~CapturedFrame();
     bool operator<(const CapturedFrame& other) const;
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
index babe29c..2711489 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
 
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/callback.h"
@@ -111,7 +112,6 @@
                void(scoped_refptr<VideoFrame> frame,
                     const gfx::Rect& update_rect,
                     mojom::FrameSinkVideoConsumerFrameCallbacks* callbacks));
-  MOCK_METHOD1(OnTargetLost, void(const FrameSinkId& frame_sink_id));
   MOCK_METHOD0(OnStopped, void());
 
   int num_frames_received() const { return frames_.size(); }
@@ -442,37 +442,6 @@
   EXPECT_EQ(&capturer_, frame_sink_.attached_client());
 }
 
-// Tests that the capturer reports a lost target to the consumer. The consumer
-// may then change targets to capture something else.
-TEST_F(FrameSinkVideoCapturerTest, ReportsTargetLost) {
-  FakeCapturableFrameSink prior_frame_sink;
-  constexpr FrameSinkId kPriorFrameSinkId = FrameSinkId(1, 2);
-  EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kPriorFrameSinkId))
-      .WillOnce(Return(&prior_frame_sink));
-  EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
-      .WillOnce(Return(&frame_sink_));
-
-  NiceMock<MockConsumer> consumer;
-  EXPECT_CALL(consumer, OnTargetLost(kPriorFrameSinkId)).Times(1);
-  StartCapture(&consumer);
-
-  capturer_.ChangeTarget(kPriorFrameSinkId);
-  EXPECT_EQ(kPriorFrameSinkId, capturer_.requested_target());
-  EXPECT_EQ(&capturer_, prior_frame_sink.attached_client());
-  EXPECT_EQ(nullptr, frame_sink_.attached_client());
-
-  NotifyTargetWentAway();
-  EXPECT_EQ(nullptr, prior_frame_sink.attached_client());
-  EXPECT_EQ(nullptr, frame_sink_.attached_client());
-
-  capturer_.ChangeTarget(kFrameSinkId);
-  EXPECT_EQ(kFrameSinkId, capturer_.requested_target());
-  EXPECT_EQ(nullptr, prior_frame_sink.attached_client());
-  EXPECT_EQ(&capturer_, frame_sink_.attached_client());
-
-  StopCapture();
-}
-
 // Tests that no initial frame is sent after Start() is called until after the
 // target has been resolved.
 TEST_F(FrameSinkVideoCapturerTest, PostponesCaptureWithoutATarget) {
@@ -481,7 +450,6 @@
 
   MockConsumer consumer;
   EXPECT_CALL(consumer, OnFrameCapturedMock(_, _, _)).Times(0);
-  EXPECT_CALL(consumer, OnTargetLost(kFrameSinkId)).Times(0);
   EXPECT_CALL(consumer, OnStopped()).Times(1);
 
   StartCapture(&consumer);
@@ -526,7 +494,6 @@
       3 * FrameSinkVideoCapturerImpl::kDesignLimitMaxFrames;
   EXPECT_CALL(consumer, OnFrameCapturedMock(_, _, _))
       .Times(num_refresh_frames + num_update_frames);
-  EXPECT_CALL(consumer, OnTargetLost(_)).Times(0);
   EXPECT_CALL(consumer, OnStopped()).Times(1);
   StartCapture(&consumer);
 
@@ -778,7 +745,6 @@
   // Start capturing to the first consumer.
   MockConsumer consumer;
   EXPECT_CALL(consumer, OnFrameCapturedMock(_, _, _)).Times(2);
-  EXPECT_CALL(consumer, OnTargetLost(_)).Times(0);
   EXPECT_CALL(consumer, OnStopped()).Times(1);
   StartCapture(&consumer);
   // With the start, an immediate refresh should have occurred.
@@ -814,7 +780,6 @@
   const int num_captures_for_second_consumer = 3;
   EXPECT_CALL(consumer2, OnFrameCapturedMock(_, _, _))
       .Times(num_captures_for_second_consumer);
-  EXPECT_CALL(consumer2, OnTargetLost(_)).Times(0);
   EXPECT_CALL(consumer2, OnStopped()).Times(1);
   StartCapture(&consumer2);
   // With the start, a refresh was attempted, but since the attempt occurred so
@@ -868,7 +833,6 @@
   const int num_update_frames = 3;
   EXPECT_CALL(consumer, OnFrameCapturedMock(_, _, _))
       .Times(num_refresh_frames + num_update_frames);
-  EXPECT_CALL(consumer, OnTargetLost(_)).Times(0);
   EXPECT_CALL(consumer, OnStopped()).Times(1);
   StartCapture(&consumer);
 
@@ -925,7 +889,6 @@
   const int num_update_frames = 1;
   EXPECT_CALL(consumer, OnFrameCapturedMock(_, _, _))
       .Times(num_refresh_frames + num_update_frames);
-  EXPECT_CALL(consumer, OnTargetLost(_)).Times(0);
   EXPECT_CALL(consumer, OnStopped()).Times(1);
   StartCapture(&consumer);
 
diff --git a/components/viz/service/hit_test/DEPS b/components/viz/service/hit_test/DEPS
index fdd37f6..0956a68 100644
--- a/components/viz/service/hit_test/DEPS
+++ b/components/viz/service/hit_test/DEPS
@@ -12,6 +12,5 @@
   "hit_test_manager_fuzzer.cc": [
     "+components/viz/service/frame_sinks",
     "+components/viz/test",
-    "+mojo/edk/embedder",
   ],
 }
diff --git a/content/app/android/content_main.cc b/content/app/android/content_main.cc
index fbd2b1b..33e04b4 100644
--- a/content/app/android/content_main.cc
+++ b/content/app/android/content_main.cc
@@ -27,14 +27,24 @@
 
 }  // namespace
 
+// TODO(qinmin/hanxi): split this function into 2 separate methods: One to
+// start the ServiceManager and one to start the remainder of the browser
+// process. The first method should always be called upon browser start, and
+// the second method can be deferred. See http://crbug.com/854209.
 static jint JNI_ContentMain_Start(JNIEnv* env,
-                                  const JavaParamRef<jclass>& clazz) {
+                                  const JavaParamRef<jclass>& clazz,
+                                  jboolean start_service_manager_only) {
   TRACE_EVENT0("startup", "content::Start");
 
-  DCHECK(!g_service_manager_main_delegate.Get());
-  g_service_manager_main_delegate.Get() =
-      std::make_unique<ContentServiceManagerMainDelegate>(
-          ContentMainParams(g_content_main_delegate.Get().get()));
+  DCHECK(!g_service_manager_main_delegate.Get() || !start_service_manager_only);
+
+  if (!g_service_manager_main_delegate.Get()) {
+    g_service_manager_main_delegate.Get() =
+        std::make_unique<ContentServiceManagerMainDelegate>(
+            ContentMainParams(g_content_main_delegate.Get().get()));
+  } else {
+    return 0;
+  }
 
   service_manager::MainParams main_params(
       g_service_manager_main_delegate.Get().get());
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index 0f81f052..59fc90f07 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -462,8 +462,7 @@
     ContentClient* content_client = GetContentClient();
 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
     if (process_type.empty()) {
-      if (delegate)
-        content_client->browser_ = delegate->CreateContentBrowserClient();
+      content_client->browser_ = delegate->CreateContentBrowserClient();
       if (!content_client->browser_)
         content_client->browser_ = &g_empty_content_browser_client.Get();
     }
@@ -474,24 +473,21 @@
     if (process_type == switches::kGpuProcess ||
         cmd->HasSwitch(switches::kSingleProcess) ||
         (process_type.empty() && cmd->HasSwitch(switches::kInProcessGPU))) {
-      if (delegate)
-        content_client->gpu_ = delegate->CreateContentGpuClient();
+      content_client->gpu_ = delegate->CreateContentGpuClient();
       if (!content_client->gpu_)
         content_client->gpu_ = &g_empty_content_gpu_client.Get();
     }
 
     if (process_type == switches::kRendererProcess ||
         cmd->HasSwitch(switches::kSingleProcess)) {
-      if (delegate)
-        content_client->renderer_ = delegate->CreateContentRendererClient();
+      content_client->renderer_ = delegate->CreateContentRendererClient();
       if (!content_client->renderer_)
         content_client->renderer_ = &g_empty_content_renderer_client.Get();
     }
 
     if (process_type == switches::kUtilityProcess ||
         cmd->HasSwitch(switches::kSingleProcess)) {
-      if (delegate)
-        content_client->utility_ = delegate->CreateContentUtilityClient();
+      content_client->utility_ = delegate->CreateContentUtilityClient();
       // TODO(scottmg): http://crbug.com/237249 Should be in _child.
       if (!content_client->utility_)
         content_client->utility_ = &g_empty_content_utility_client.Get();
@@ -523,10 +519,8 @@
 
   std::vector<std::unique_ptr<service_manager::ZygoteForkDelegate>>
       zygote_fork_delegates;
-  if (delegate) {
-    delegate->ZygoteStarting(&zygote_fork_delegates);
-    media::InitializeMediaLibrary();
-  }
+  delegate->ZygoteStarting(&zygote_fork_delegates);
+  media::InitializeMediaLibrary();
 
 #if defined(OS_LINUX)
   PreSandboxInit();
@@ -537,8 +531,7 @@
     return 1;
   }
 
-  if (delegate)
-    delegate->ZygoteForked();
+  delegate->ZygoteForked();
 
   // Zygote::HandleForkRequest may have reallocated the command
   // line so update it here with the new version.
@@ -568,11 +561,7 @@
       return kMainFunctions[i].function(main_params);
   }
 
-  if (delegate)
-    return delegate->RunProcess(process_type, main_params);
-
-  NOTREACHED() << "Unknown zygote process type: " << process_type;
-  return 1;
+  return delegate->RunProcess(process_type, main_params);
 }
 #endif  // BUILDFLAG(USE_ZYGOTE_HANDLE)
 
@@ -603,22 +592,21 @@
     const MainFunctionParams& main_function_params,
     ContentMainDelegate* delegate,
     std::unique_ptr<BrowserProcessSubThread> service_manager_thread) {
-  if (delegate) {
-    int exit_code = delegate->RunProcess("", main_function_params);
+  int exit_code = delegate->RunProcess("", main_function_params);
 #if defined(OS_ANDROID)
-    // In Android's browser process, the negative exit code doesn't mean the
-    // default behavior should be used as the UI message loop is managed by
-    // the Java and the browser process's default behavior is always
-    // overridden.
+  // In Android's browser process, the negative exit code doesn't mean the
+  // default behavior should be used as the UI message loop is managed by
+  // the Java and the browser process's default behavior is always
+  // overridden.
+  return exit_code;
+#else
+  if (exit_code >= 0)
     return exit_code;
-#endif
-    if (exit_code >= 0)
-      return exit_code;
-  }
   // GetServiceManagerTaskRunnerForEmbedderProcess() needs to be invoked before
   // Run() for the browser process.
   DCHECK(service_manager_thread);
   return BrowserMain(main_function_params, std::move(service_manager_thread));
+#endif
 }
 #endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)
 
@@ -640,12 +628,9 @@
 
   for (size_t i = 0; i < base::size(kMainFunctions); ++i) {
     if (process_type == kMainFunctions[i].name) {
-      if (delegate) {
-        int exit_code =
-            delegate->RunProcess(process_type, main_function_params);
-        if (exit_code >= 0)
-          return exit_code;
-      }
+      int exit_code = delegate->RunProcess(process_type, main_function_params);
+      if (exit_code >= 0)
+        return exit_code;
       return kMainFunctions[i].function(main_function_params);
     }
   }
@@ -659,11 +644,7 @@
 #endif  // BUILDFLAG(USE_ZYGOTE_HANDLE)
 
   // If it's a process we don't know about, the embedder should know.
-  if (delegate)
-    return delegate->RunProcess(process_type, main_function_params);
-
-  NOTREACHED() << "Unknown process type: " << process_type;
-  return 1;
+  return delegate->RunProcess(process_type, main_function_params);
 }
 
 // static
@@ -683,11 +664,7 @@
 }
 
 int ContentMainRunnerImpl::TerminateForFatalInitializationError() {
-  if (delegate_)
-    return delegate_->TerminateForFatalInitializationError();
-
-  CHECK(false);
-  return 0;
+  return delegate_->TerminateForFatalInitializationError();
 }
 
 int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) {
@@ -748,7 +725,7 @@
 #endif  // !OS_ANDROID
 
   int exit_code = 0;
-  if (delegate_ && delegate_->BasicStartupComplete(&exit_code))
+  if (delegate_->BasicStartupComplete(&exit_code))
     return exit_code;
   completed_basic_startup_ = true;
 
@@ -809,13 +786,11 @@
     // It's important not to allocate the ports for processes which don't
     // register with the power monitor - see https://crbug.com/88867.
     if (process_type.empty() ||
-        (delegate_ &&
-         delegate_->ProcessRegistersWithSystemProcess(process_type))) {
+        delegate_->ProcessRegistersWithSystemProcess(process_type)) {
       base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
     }
 
-    if (!process_type.empty() &&
-        (!delegate_ || delegate_->ShouldSendMachPort(process_type))) {
+    if (!process_type.empty() && delegate_->ShouldSendMachPort(process_type)) {
       MachBroker::ChildSendTaskPortToParent();
     }
 #endif
@@ -890,8 +865,7 @@
     }
 #endif  // !defined(OFFICIAL_BUILD)
 
-    if (delegate_)
-      delegate_->PreSandboxStartup();
+    delegate_->PreSandboxStartup();
 
 #if defined(OS_WIN)
     if (!InitializeSandbox(
@@ -906,7 +880,7 @@
 
     if (process_type == switches::kRendererProcess ||
         process_type == switches::kPpapiPluginProcess || v2_enabled ||
-        (delegate_ && delegate_->DelaySandboxInitialization(process_type))) {
+        delegate_->DelaySandboxInitialization(process_type)) {
       // On OS X the renderer sandbox needs to be initialized later in the
       // startup sequence in RendererMainPlatformDelegate::EnableSandbox().
     } else {
@@ -915,8 +889,7 @@
     }
 #endif
 
-    if (delegate_)
-      delegate_->SandboxInitialized(process_type);
+    delegate_->SandboxInitialized(process_type);
 
 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
     if (process_type.empty()) {
@@ -971,8 +944,7 @@
       base::TaskScheduler::Create("Browser");
     }
 
-    if (delegate_)
-      delegate_->PreContentInitialization();
+    delegate_->PreContentInitialization();
 
     // Create a MessageLoop if one does not already exist for the current
     // thread. This thread won't be promoted as BrowserThread::UI until
@@ -992,7 +964,7 @@
   DCHECK(is_initialized_);
   DCHECK(!is_shutdown_);
 
-  if (completed_basic_startup_ && delegate_) {
+  if (completed_basic_startup_) {
     const base::CommandLine& command_line =
         *base::CommandLine::ForCurrentProcess();
     std::string process_type =
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index d19df7f..9ca97f3 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2283,7 +2283,7 @@
       "renderer_host/popup_window_mac.h",
       "renderer_host/popup_window_mac.mm",
       "renderer_host/render_widget_host_ns_view_bridge.h",
-      "renderer_host/render_widget_host_ns_view_bridge.mm",
+      "renderer_host/render_widget_host_ns_view_bridge_local.mm",
       "renderer_host/render_widget_host_ns_view_client.h",
       "renderer_host/render_widget_host_view_cocoa.h",
       "renderer_host/render_widget_host_view_cocoa.mm",
diff --git a/content/browser/android/browser_startup_controller.cc b/content/browser/android/browser_startup_controller.cc
index a4f8ad0..3bd5389 100644
--- a/content/browser/android/browser_startup_controller.cc
+++ b/content/browser/android/browser_startup_controller.cc
@@ -21,6 +21,11 @@
   Java_BrowserStartupControllerImpl_browserStartupComplete(env, result);
 }
 
+void ServiceManagerStartupComplete() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_BrowserStartupControllerImpl_serviceManagerStartupComplete(env);
+}
+
 bool ShouldStartGpuProcessOnBrowserStartup() {
   JNIEnv* env = base::android::AttachCurrentThread();
   return Java_BrowserStartupControllerImpl_shouldStartGpuProcessOnBrowserStartup(
diff --git a/content/browser/android/browser_startup_controller.h b/content/browser/android/browser_startup_controller.h
index 162f1e8..6db34d1 100644
--- a/content/browser/android/browser_startup_controller.h
+++ b/content/browser/android/browser_startup_controller.h
@@ -9,6 +9,7 @@
 
 void BrowserStartupComplete(int result);
 bool ShouldStartGpuProcessOnBrowserStartup();
+void ServiceManagerStartupComplete();
 
 }  // namespace content
 #endif  // CONTENT_BROWSER_ANDROID_BROWSER_STARTUP_CONTROLLER_H_
diff --git a/content/browser/cookie_store/cookie_store_manager_unittest.cc b/content/browser/cookie_store/cookie_store_manager_unittest.cc
index 68c926c..ad21a91 100644
--- a/content/browser/cookie_store/cookie_store_manager_unittest.cc
+++ b/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -288,19 +288,8 @@
     return registration_id;
   }
 
-  // Simplified helper for SetCanonicalCookie.
-  //
-  // Creates a CanonicalCookie that is not secure, not http-only,
-  // and not restricted to first parties. Returns false if creation fails.
-  bool SetSessionCookie(const char* name,
-                        const char* value,
-                        const char* domain,
-                        const char* path) {
-    net::CanonicalCookie cookie(
-        name, value, domain, path, base::Time(), base::Time(), base::Time(),
-        /* secure = */ false,
-        /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
-        net::COOKIE_PRIORITY_DEFAULT);
+  // Synchronous helper for CookieManager::SetCanonicalCookie.
+  bool SetCanonicalCookie(const net::CanonicalCookie& cookie) {
     base::RunLoop run_loop;
     bool success = false;
     cookie_manager_->SetCanonicalCookie(
@@ -315,6 +304,21 @@
     return success;
   }
 
+  // Simplified helper for SetCanonicalCookie.
+  //
+  // Creates a CanonicalCookie that is not secure, not http-only,
+  // and not restricted to first parties. Returns false if creation fails.
+  bool SetSessionCookie(const char* name,
+                        const char* value,
+                        const char* domain,
+                        const char* path) {
+    return SetCanonicalCookie(net::CanonicalCookie(
+        name, value, domain, path, base::Time(), base::Time(), base::Time(),
+        /* secure = */ false,
+        /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
+        net::COOKIE_PRIORITY_DEFAULT));
+  }
+
   bool reset_context_during_test() const { return GetParam(); }
 
   static constexpr const int64_t kInvalidRegistrationId = -1;
@@ -824,6 +828,58 @@
             worker_test_helper_->changes()[0].second);
 }
 
+TEST_P(CookieStoreManagerTest, HttpOnlyCookieChange) {
+  std::vector<CookieStoreSync::Subscriptions> batches;
+  batches.emplace_back();
+
+  CookieStoreSync::Subscriptions& subscriptions = batches.back();
+  subscriptions.emplace_back(blink::mojom::CookieChangeSubscription::New());
+  subscriptions.back()->name = "";
+  subscriptions.back()->match_type =
+      ::network::mojom::CookieMatchType::STARTS_WITH;
+  subscriptions.back()->url = GURL(kExampleScope);
+
+  worker_test_helper_->SetOnInstallSubscriptions(std::move(batches),
+                                                 example_service_ptr_.get());
+  int64_t registration_id =
+      RegisterServiceWorker(kExampleScope, kExampleWorkerScript);
+  ASSERT_NE(registration_id, kInvalidRegistrationId);
+
+  base::Optional<CookieStoreSync::Subscriptions> all_subscriptions_opt =
+      example_service_->GetSubscriptions(registration_id);
+  ASSERT_TRUE(all_subscriptions_opt.has_value());
+  ASSERT_EQ(1u, all_subscriptions_opt.value().size());
+
+  if (reset_context_during_test())
+    ResetServiceWorkerContext();
+
+  ASSERT_TRUE(SetCanonicalCookie(net::CanonicalCookie(
+      "cookie-name-1", "cookie-value-1", "example.com", "/", base::Time(),
+      base::Time(), base::Time(),
+      /* secure = */ false,
+      /* httponly = */ true, net::CookieSameSite::NO_RESTRICTION,
+      net::COOKIE_PRIORITY_DEFAULT)));
+  thread_bundle_.RunUntilIdle();
+  EXPECT_EQ(0u, worker_test_helper_->changes().size());
+
+  worker_test_helper_->changes().clear();
+  ASSERT_TRUE(SetCanonicalCookie(net::CanonicalCookie(
+      "cookie-name-2", "cookie-value-2", "example.com", "/", base::Time(),
+      base::Time(), base::Time(),
+      /* secure = */ false,
+      /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
+      net::COOKIE_PRIORITY_DEFAULT)));
+  thread_bundle_.RunUntilIdle();
+
+  ASSERT_EQ(1u, worker_test_helper_->changes().size());
+  EXPECT_EQ("cookie-name-2", worker_test_helper_->changes()[0].first.Name());
+  EXPECT_EQ("cookie-value-2", worker_test_helper_->changes()[0].first.Value());
+  EXPECT_EQ("example.com", worker_test_helper_->changes()[0].first.Domain());
+  EXPECT_EQ("/", worker_test_helper_->changes()[0].first.Path());
+  EXPECT_EQ(::network::mojom::CookieChangeCause::INSERTED,
+            worker_test_helper_->changes()[0].second);
+}
+
 TEST_P(CookieStoreManagerTest, GetSubscriptionsFromWrongOrigin) {
   std::vector<CookieStoreSync::Subscriptions> batches;
   batches.emplace_back();
diff --git a/content/browser/devtools/devtools_video_consumer.cc b/content/browser/devtools/devtools_video_consumer.cc
index ece36ef4..2b185d0 100644
--- a/content/browser/devtools/devtools_video_consumer.cc
+++ b/content/browser/devtools/devtools_video_consumer.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/devtools/devtools_video_consumer.h"
 
+#include <utility>
+
 #include "cc/paint/skia_paint_canvas.h"
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
@@ -73,8 +75,12 @@
 void DevToolsVideoConsumer::SetFrameSinkId(
     const viz::FrameSinkId& frame_sink_id) {
   frame_sink_id_ = frame_sink_id;
-  if (capturer_)
-    capturer_->ChangeTarget(frame_sink_id_);
+  if (capturer_) {
+    if (frame_sink_id_.is_valid())
+      capturer_->ChangeTarget(frame_sink_id_);
+    else
+      capturer_->ChangeTarget(base::nullopt);
+  }
 }
 
 void DevToolsVideoConsumer::SetMinCapturePeriod(
@@ -104,7 +110,8 @@
   capturer_->SetMinSizeChangePeriod(kDefaultMinPeriod);
   capturer_->SetResolutionConstraints(min_frame_size_, max_frame_size_,
                                       kDefaultUseFixedAspectRatio);
-  capturer_->ChangeTarget(frame_sink_id_);
+  if (frame_sink_id_.is_valid())
+    capturer_->ChangeTarget(frame_sink_id_);
 
   capturer_->Start(this);
 }
@@ -152,9 +159,6 @@
   callback_.Run(std::move(frame));
 }
 
-void DevToolsVideoConsumer::OnTargetLost(
-    const viz::FrameSinkId& frame_sink_id) {}
-
 void DevToolsVideoConsumer::OnStopped() {}
 
 }  // namespace content
diff --git a/content/browser/devtools/devtools_video_consumer.h b/content/browser/devtools/devtools_video_consumer.h
index 719882d2..dd17f36 100644
--- a/content/browser/devtools/devtools_video_consumer.h
+++ b/content/browser/devtools/devtools_video_consumer.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_VIDEO_CONSUMER_H_
 #define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_VIDEO_CONSUMER_H_
 
+#include <memory>
+
 #include "base/time/time.h"
 #include "components/viz/host/client_frame_sink_video_capturer.h"
 #include "content/common/content_export.h"
@@ -68,7 +70,6 @@
       const gfx::Rect& update_rect,
       const gfx::Rect& content_rect,
       viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) override;
-  void OnTargetLost(const viz::FrameSinkId& frame_sink_id) override;
   void OnStopped() override;
 
   // Default min frame size is 1x1, as otherwise, nothing would be captured.
diff --git a/content/browser/devtools/devtools_video_consumer_unittest.cc b/content/browser/devtools/devtools_video_consumer_unittest.cc
index 1c62070b..826ab906 100644
--- a/content/browser/devtools/devtools_video_consumer_unittest.cc
+++ b/content/browser/devtools/devtools_video_consumer_unittest.cc
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <memory>
+#include <utility>
+#include <vector>
 
 #include "base/message_loop/message_loop.h"
 #include "content/browser/devtools/devtools_video_consumer.h"
@@ -71,8 +72,9 @@
                     bool use_fixed_aspect_ratio));
   // This is never called.
   MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool));
-  void ChangeTarget(const viz::FrameSinkId& frame_sink_id) final {
-    frame_sink_id_ = frame_sink_id;
+  void ChangeTarget(
+      const base::Optional<viz::FrameSinkId>& frame_sink_id) final {
+    frame_sink_id_ = frame_sink_id ? *frame_sink_id : viz::FrameSinkId();
     MockChangeTarget(frame_sink_id_);
   }
   MOCK_METHOD1(MockChangeTarget, void(const viz::FrameSinkId& frame_sink_id));
diff --git a/content/browser/dom_storage/session_storage_context_mojo.cc b/content/browser/dom_storage/session_storage_context_mojo.cc
index 73dfdf21f..889743c 100644
--- a/content/browser/dom_storage/session_storage_context_mojo.cc
+++ b/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -128,7 +128,10 @@
     return;
   }
   auto found = namespaces_.find(namespace_id);
-  DCHECK(found != namespaces_.end()) << namespace_id;
+  if (found == namespaces_.end()) {
+    mojo::ReportBadMessage("Namespace not found: " + namespace_id);
+    return;
+  }
 
   if (!found->second->IsPopulated() &&
       !found->second->waiting_on_clone_population()) {
@@ -137,8 +140,8 @@
         data_maps_);
   }
 
-  found->second->Bind(std::move(request), process_id);
   PurgeUnusedAreasIfNeeded();
+  found->second->Bind(std::move(request), process_id);
 
   size_t total_cache_size, unused_area_count;
   GetStatistics(&total_cache_size, &unused_area_count);
@@ -302,13 +305,8 @@
   GetStatistics(&total_cache_size, &unused_area_count);
 
   // Purge all areas that don't have bindings.
-  for (auto it = namespaces_.begin(); it != namespaces_.end();) {
-    if (!it->second->IsBound()) {
-      it = namespaces_.erase(it);
-      continue;
-    }
-    it->second->PurgeUnboundAreas();
-    ++it;
+  for (const auto& namespace_pair : namespaces_) {
+    namespace_pair.second->PurgeUnboundAreas();
   }
   // Purge memory from bound maps.
   for (const auto& data_map_pair : data_maps_) {
@@ -345,14 +343,9 @@
   if (purge_reason == SessionStorageCachePurgeReason::kNotNeeded)
     return;
 
-  // Purge all namespaces and areas that don't have bindings.
-  for (auto it = namespaces_.begin(); it != namespaces_.end();) {
-    if (!it->second->IsBound()) {
-      it = namespaces_.erase(it);
-      continue;
-    }
-    it->second->PurgeUnboundAreas();
-    ++it;
+  // Purge all areas that don't have bindings.
+  for (const auto& namespace_pair : namespaces_) {
+    namespace_pair.second->PurgeUnboundAreas();
   }
 
   size_t final_total_cache_size;
@@ -584,21 +577,24 @@
 }
 
 void SessionStorageContextMojo::RunWhenConnected(base::OnceClosure callback) {
-  DCHECK_NE(connection_state_, CONNECTION_SHUTDOWN);
-
-  // If we don't have a filesystem_connection_, we'll need to establish one.
-  if (connection_state_ == NO_CONNECTION) {
-    connection_state_ = CONNECTION_IN_PROGRESS;
-    InitiateConnection();
+  switch (connection_state_) {
+    case NO_CONNECTION:
+      // If we don't have a filesystem_connection_, we'll need to establish one.
+      connection_state_ = CONNECTION_IN_PROGRESS;
+      InitiateConnection();
+      FALLTHROUGH;
+    case CONNECTION_IN_PROGRESS:
+      // Queue this OpenSessionStorage call for when we have a level db pointer.
+      on_database_opened_callbacks_.push_back(std::move(callback));
+      return;
+    case CONNECTION_SHUTDOWN:
+      NOTREACHED();
+      return;
+    case CONNECTION_FINISHED:
+      std::move(callback).Run();
+      return;
   }
-
-  if (connection_state_ == CONNECTION_IN_PROGRESS) {
-    // Queue this OpenSessionStorage call for when we have a level db pointer.
-    on_database_opened_callbacks_.push_back(std::move(callback));
-    return;
-  }
-
-  std::move(callback).Run();
+  NOTREACHED();
 }
 
 void SessionStorageContextMojo::InitiateConnection(bool in_memory_only) {
@@ -726,7 +722,6 @@
         "SessionStorageContext.OpenResultAfterReadVersionError");
     return;
   }
-  connection_state_ = FETCHING_METADATA;
 
   base::RepeatingClosure barrier = base::BarrierClosure(
       2, base::BindOnce(&SessionStorageContextMojo::OnConnectionFinished,
@@ -753,7 +748,7 @@
     std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations,
     leveldb::mojom::DatabaseError status,
     std::vector<leveldb::mojom::KeyValuePtr> values) {
-  DCHECK(connection_state_ == FETCHING_METADATA);
+  DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
   bool parsing_failure =
       status == leveldb::mojom::DatabaseError::OK &&
       !metadata_.ParseNamespaces(std::move(values), &migration_operations);
@@ -780,7 +775,7 @@
     base::OnceClosure done,
     leveldb::mojom::DatabaseError status,
     const std::vector<uint8_t>& map_id) {
-  DCHECK(connection_state_ == FETCHING_METADATA);
+  DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
   if (status == leveldb::mojom::DatabaseError::NOT_FOUND) {
     std::move(done).Run();
     return;
@@ -801,7 +796,7 @@
 }
 
 void SessionStorageContextMojo::OnConnectionFinished() {
-  DCHECK(!database_ || connection_state_ == FETCHING_METADATA);
+  DCHECK(!database_ || connection_state_ == CONNECTION_IN_PROGRESS);
   if (!database_) {
     partition_directory_.reset();
     file_system_.reset();
diff --git a/content/browser/dom_storage/session_storage_context_mojo.h b/content/browser/dom_storage/session_storage_context_mojo.h
index a2d18d7..da97c9c 100644
--- a/content/browser/dom_storage/session_storage_context_mojo.h
+++ b/content/browser/dom_storage/session_storage_context_mojo.h
@@ -13,6 +13,7 @@
 
 #include "base/callback_forward.h"
 #include "base/files/file_path.h"
+#include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
@@ -126,6 +127,8 @@
 
  private:
   friend class DOMStorageBrowserTest;
+  FRIEND_TEST_ALL_PREFIXES(SessionStorageContextMojoTest,
+                           PurgeMemoryDoesNotCrashOrHang);
 
   // Object deletion is done through |ShutdownAndDelete()|.
   ~SessionStorageContextMojo() override;
@@ -200,7 +203,6 @@
 
   enum ConnectionState {
     NO_CONNECTION,
-    FETCHING_METADATA,
     CONNECTION_IN_PROGRESS,
     CONNECTION_FINISHED,
     CONNECTION_SHUTDOWN
diff --git a/content/browser/dom_storage/session_storage_context_mojo_unittest.cc b/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
index d4da904..9da9df4 100644
--- a/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
+++ b/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
@@ -439,6 +439,8 @@
   // This scavenge call should NOT delete the namespace, as we just created it.
   {
     base::RunLoop loop;
+    // Cause the connection to start loading, so we start scavenging mid-load.
+    context()->Flush();
     context()->ScavengeUnusedNamespaces(loop.QuitClosure());
     loop.Run();
   }
@@ -938,52 +940,6 @@
   EXPECT_EQ(0ul, data.size());
 }
 
-TEST_F(SessionStorageContextMojoTest, PurgeMemoryDoesNotCrashOrHang) {
-  std::string namespace_id1 = base::GenerateGUID();
-  std::string namespace_id2 = base::GenerateGUID();
-  url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
-
-  context()->CreateSessionNamespace(namespace_id1);
-  blink::mojom::SessionStorageNamespacePtr ss_namespace1;
-  context()->OpenSessionStorage(kTestProcessId, namespace_id1,
-                                mojo::MakeRequest(&ss_namespace1));
-  blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
-  ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
-
-  context()->CreateSessionNamespace(namespace_id2);
-  blink::mojom::SessionStorageNamespacePtr ss_namespace2;
-  context()->OpenSessionStorage(kTestProcessId, namespace_id2,
-                                mojo::MakeRequest(&ss_namespace2));
-  blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
-  ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
-
-  // Put some data in both.
-  EXPECT_TRUE(test::PutSync(
-      leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
-      leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
-  EXPECT_TRUE(test::PutSync(
-      leveldb_n2_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
-      leveldb::StringPieceToUint8Vector("value2"), base::nullopt, "source1"));
-
-  leveldb_n2_o1.reset();
-  ss_namespace2.reset();
-
-  base::RunLoop().RunUntilIdle();
-
-  // Verify this doesn't crash or hang.
-  context()->PurgeMemory();
-
-  // Test the values is still there.
-  std::vector<blink::mojom::KeyValuePtr> data;
-  EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
-  EXPECT_EQ(1ul, data.size());
-
-  base::Optional<std::vector<uint8_t>> opt_value2 =
-      DoTestGet(namespace_id2, origin1, "key1");
-  ASSERT_TRUE(opt_value2);
-  EXPECT_EQ(leveldb::StringPieceToUint8Vector("value2"), opt_value2.value());
-}
-
 TEST_F(SessionStorageContextMojoTest, PurgeInactiveWrappers) {
   std::string namespace_id1 = base::GenerateGUID();
   std::string namespace_id2 = base::GenerateGUID();
@@ -1039,4 +995,61 @@
 }
 
 }  // namespace
+
+TEST_F(SessionStorageContextMojoTest, PurgeMemoryDoesNotCrashOrHang) {
+  std::string namespace_id1 = base::GenerateGUID();
+  std::string namespace_id2 = base::GenerateGUID();
+  url::Origin origin1 = url::Origin::Create(GURL("http://foobar.com"));
+
+  context()->CreateSessionNamespace(namespace_id1);
+  blink::mojom::SessionStorageNamespacePtr ss_namespace1;
+  context()->OpenSessionStorage(kTestProcessId, namespace_id1,
+                                mojo::MakeRequest(&ss_namespace1));
+  blink::mojom::StorageAreaAssociatedPtr leveldb_n1_o1;
+  ss_namespace1->OpenArea(origin1, mojo::MakeRequest(&leveldb_n1_o1));
+
+  context()->CreateSessionNamespace(namespace_id2);
+  blink::mojom::SessionStorageNamespacePtr ss_namespace2;
+  context()->OpenSessionStorage(kTestProcessId, namespace_id2,
+                                mojo::MakeRequest(&ss_namespace2));
+  blink::mojom::StorageAreaAssociatedPtr leveldb_n2_o1;
+  ss_namespace2->OpenArea(origin1, mojo::MakeRequest(&leveldb_n2_o1));
+
+  // Put some data in both.
+  EXPECT_TRUE(test::PutSync(
+      leveldb_n1_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+      leveldb::StringPieceToUint8Vector("value1"), base::nullopt, "source1"));
+  EXPECT_TRUE(test::PutSync(
+      leveldb_n2_o1.get(), leveldb::StringPieceToUint8Vector("key1"),
+      leveldb::StringPieceToUint8Vector("value2"), base::nullopt, "source1"));
+
+  context()->FlushAreaForTesting(namespace_id1, origin1);
+
+  leveldb_n2_o1.reset();
+  ss_namespace2.reset();
+
+  base::RunLoop().RunUntilIdle();
+
+  // Verify this doesn't crash or hang.
+  context()->PurgeMemory();
+
+  size_t memory_used = context()
+                           ->namespaces_[namespace_id1]
+                           ->origin_areas_[origin1]
+                           ->data_map()
+                           ->storage_area()
+                           ->memory_used();
+  EXPECT_EQ(0ul, memory_used);
+
+  // Test the values is still there.
+  std::vector<blink::mojom::KeyValuePtr> data;
+  EXPECT_TRUE(test::GetAllSync(leveldb_n1_o1.get(), &data));
+  EXPECT_EQ(1ul, data.size());
+
+  base::Optional<std::vector<uint8_t>> opt_value2 =
+      DoTestGet(namespace_id2, origin1, "key1");
+  ASSERT_TRUE(opt_value2);
+  EXPECT_EQ(leveldb::StringPieceToUint8Vector("value2"), opt_value2.value());
+}
+
 }  // namespace content
diff --git a/content/browser/dom_storage/session_storage_namespace_impl_mojo.h b/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
index 95be8f3..eb70ad8d 100644
--- a/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
+++ b/content/browser/dom_storage/session_storage_namespace_impl_mojo.h
@@ -8,6 +8,7 @@
 
 #include "base/callback.h"
 #include "base/containers/flat_map.h"
+#include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
 #include "content/browser/dom_storage/session_storage_area_impl.h"
 #include "content/browser/dom_storage/session_storage_data_map.h"
@@ -134,6 +135,9 @@
   void FlushOriginForTesting(const url::Origin& origin);
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(SessionStorageContextMojoTest,
+                           PurgeMemoryDoesNotCrashOrHang);
+
   const std::string namespace_id_;
   SessionStorageMetadata::NamespaceEntry namespace_entry_;
   leveldb::mojom::LevelDBDatabase* database_;
diff --git a/content/browser/dom_storage/storage_area_impl.cc b/content/browser/dom_storage/storage_area_impl.cc
index f3bdee2..63930ec 100644
--- a/content/browser/dom_storage/storage_area_impl.cc
+++ b/content/browser/dom_storage/storage_area_impl.cc
@@ -202,6 +202,7 @@
   }
 
   map_state_ = MapState::UNLOADED;
+  memory_used_ = 0;
   keys_only_map_.clear();
   keys_values_map_.clear();
 }
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 279bed8..b2b60a1 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -3356,9 +3356,11 @@
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
 
   if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    registry_->AddInterface(base::BindRepeating(
-        &RenderFrameHostImpl::ConnectToPrefetchURLLoaderService,
-        base::Unretained(this)));
+    registry_->AddInterface(
+        base::BindRepeating(
+            &RenderFrameHostImpl::ConnectToPrefetchURLLoaderService,
+            base::Unretained(this)),
+        BrowserThread::GetTaskRunnerForThread(BrowserThread::UI));
   }
 }
 
@@ -3761,7 +3763,8 @@
       }
     }
 
-    SaveSubresourceFactories(std::move(subresource_loader_factories));
+    if (subresource_loader_factories)
+      SaveSubresourceFactories(std::move(subresource_loader_factories));
 
     if (IsPerNavigationMojoInterfaceEnabled() && navigation_request_ &&
         navigation_request_->GetCommitNavigationClient()) {
@@ -4650,6 +4653,8 @@
       static_cast<StoragePartitionImpl*>(BrowserContext::GetStoragePartition(
           GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
   auto subresource_factories = CloneSubresourceFactories();
+  // Temporary for https://crbug.com/849929.
+  CHECK(subresource_factories);
   // Make sure that file: URL is available only when the origin of the last
   // commited URL is for file:. This should be always true as far as
   // SaveSubresourceFactories() is called appropriately whenever the set of
@@ -5142,6 +5147,9 @@
 
 void RenderFrameHostImpl::SaveSubresourceFactories(
     std::unique_ptr<URLLoaderFactoryBundleInfo> bundle_info) {
+  // CHECK for https://crbug.com/849929.
+  CHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) ||
+        bundle_info);
   subresource_loader_factories_bundle_ = nullptr;
   if (bundle_info) {
     subresource_loader_factories_bundle_ =
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 3f460f52..128144c1 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -67,7 +67,6 @@
 #include "gpu/ipc/in_process_command_buffer.h"
 #include "media/base/media_switches.h"
 #include "media/media_buildflags.h"
-#include "mojo/edk/embedder/embedder.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index e0c9367..58142112 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -266,7 +266,6 @@
                    updated_resource_request.referrer_policy));
   new_common_params.method = updated_resource_request.method;
   new_common_params.post_data = updated_resource_request.request_body;
-  // TODO(shimazu): Set correct base url and history url for a data URL.
 
   mojom::BeginNavigationParamsPtr new_begin_params =
       previous_request_info.begin_params.Clone();
@@ -956,6 +955,8 @@
           subresource_loader_params_ = SubresourceLoaderParams();
           subresource_loader_params_->controller_service_worker_info =
               mojom::ControllerServiceWorkerInfo::New();
+          subresource_loader_params_->controller_service_worker_info->mode =
+              sw_provider_host->GetControllerMode();
           base::WeakPtr<ServiceWorkerObjectHost> sw_object_host =
               sw_provider_host->GetOrCreateServiceWorkerObjectHost(
                   sw_provider_host->controller());
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc
index 80ad28d5..e096bf8 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -41,7 +41,7 @@
     : public base::ScopedClosureRunner,
       public media::VideoCaptureDevice::Client::Buffer::ScopedAccessPermission {
  public:
-  ScopedFrameDoneHelper(base::OnceClosure done_callback)
+  explicit ScopedFrameDoneHelper(base::OnceClosure done_callback)
       : base::ScopedClosureRunner(std::move(done_callback)) {}
   ~ScopedFrameDoneHelper() final = default;
 };
@@ -258,12 +258,6 @@
       std::move(info));
 }
 
-void FrameSinkVideoCaptureDevice::OnTargetLost(
-    const viz::FrameSinkId& frame_sink_id) {
-  // This is ignored because FrameSinkVideoCaptureDevice subclasses always call
-  // OnTargetChanged() and OnTargetPermanentlyLost() to resolve lost targets.
-}
-
 void FrameSinkVideoCaptureDevice::OnStopped() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -279,19 +273,19 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   target_ = frame_sink_id;
-  // TODO(crbug.com/754872): When the frame sink is invalid, the capturer should
-  // be told there is no target. This will require a mojo API change; and will
-  // be addressed in a soon-upcoming CL.
-  if (capturer_ && frame_sink_id.is_valid()) {
-    capturer_->ChangeTarget(frame_sink_id);
+  if (capturer_) {
+    if (target_.is_valid()) {
+      capturer_->ChangeTarget(target_);
+    } else {
+      capturer_->ChangeTarget(base::nullopt);
+    }
   }
 }
 
 void FrameSinkVideoCaptureDevice::OnTargetPermanentlyLost() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  target_ = viz::FrameSinkId();
-
+  OnTargetChanged(viz::FrameSinkId());
   OnFatalError("Capture target has been permanently lost.");
 }
 
@@ -376,9 +370,9 @@
 FrameSinkVideoCaptureDevice::ConsumptionState::ConsumptionState() = default;
 FrameSinkVideoCaptureDevice::ConsumptionState::~ConsumptionState() = default;
 FrameSinkVideoCaptureDevice::ConsumptionState::ConsumptionState(
-    FrameSinkVideoCaptureDevice::ConsumptionState&& other) = default;
+    FrameSinkVideoCaptureDevice::ConsumptionState&& other) noexcept = default;
 FrameSinkVideoCaptureDevice::ConsumptionState&
 FrameSinkVideoCaptureDevice::ConsumptionState::operator=(
-    FrameSinkVideoCaptureDevice::ConsumptionState&& other) = default;
+    FrameSinkVideoCaptureDevice::ConsumptionState&& other) noexcept = default;
 
 }  // namespace content
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.h b/content/browser/media/capture/frame_sink_video_capture_device.h
index fefe7b9..3412484 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.h
+++ b/content/browser/media/capture/frame_sink_video_capture_device.h
@@ -6,6 +6,8 @@
 #define CONTENT_BROWSER_MEDIA_CAPTURE_FRAME_SINK_VIDEO_CAPTURE_DEVICE_H_
 
 #include <memory>
+#include <string>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
@@ -76,7 +78,6 @@
       const gfx::Rect& update_rect,
       const gfx::Rect& content_rect,
       viz::mojom::FrameSinkVideoConsumerFrameCallbacksPtr callbacks) final;
-  void OnTargetLost(const viz::FrameSinkId& frame_sink_id) final;
   void OnStopped() final;
 
   // These are called to notify when the capture target has changed or was
@@ -147,8 +148,8 @@
 
     ConsumptionState();
     ~ConsumptionState();
-    ConsumptionState(ConsumptionState&& other);
-    ConsumptionState& operator=(ConsumptionState&& other);
+    ConsumptionState(ConsumptionState&& other) noexcept;
+    ConsumptionState& operator=(ConsumptionState&& other) noexcept;
   };
   std::vector<ConsumptionState> slots_;
 
diff --git a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
index b9cc7f8..d8de88d 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -91,7 +91,12 @@
                     const gfx::Size& max_size,
                     bool use_fixed_aspect_ratio));
   MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool));
-  MOCK_METHOD1(ChangeTarget, void(const viz::FrameSinkId& frame_sink_id));
+  void ChangeTarget(
+      const base::Optional<viz::FrameSinkId>& frame_sink_id) final {
+    DCHECK_NOT_ON_DEVICE_THREAD();
+    MockChangeTarget(frame_sink_id ? *frame_sink_id : viz::FrameSinkId());
+  }
+  MOCK_METHOD1(MockChangeTarget, void(const viz::FrameSinkId& frame_sink_id));
   void Start(viz::mojom::FrameSinkVideoConsumerPtr consumer) final {
     DCHECK_NOT_ON_DEVICE_THREAD();
     consumer_ = std::move(consumer);
@@ -310,7 +315,7 @@
     EXPECT_CALL(capturer_,
                 SetResolutionConstraints(kResolution, kResolution, _));
     constexpr viz::FrameSinkId frame_sink_id(1, 1);
-    EXPECT_CALL(capturer_, ChangeTarget(frame_sink_id));
+    EXPECT_CALL(capturer_, MockChangeTarget(frame_sink_id));
     EXPECT_CALL(capturer_, MockStart(NotNull()));
 
     EXPECT_FALSE(capturer_.is_bound());
@@ -555,6 +560,7 @@
   // consumption, unbind the capturer, log an error with the VideoFrameReceiver,
   // and destroy the VideoFrameReceiver.
   {
+    EXPECT_CALL(capturer_, MockChangeTarget(viz::FrameSinkId()));
     EXPECT_CALL(capturer_, MockStop());
     POST_DEVICE_METHOD_CALL0(OnTargetPermanentlyLost);
     WAIT_FOR_DEVICE_TASKS();
diff --git a/content/browser/media/capture/lame_window_capturer_chromeos.cc b/content/browser/media/capture/lame_window_capturer_chromeos.cc
index 95e5e76..1086b27 100644
--- a/content/browser/media/capture/lame_window_capturer_chromeos.cc
+++ b/content/browser/media/capture/lame_window_capturer_chromeos.cc
@@ -4,6 +4,8 @@
 
 #include "content/browser/media/capture/lame_window_capturer_chromeos.h"
 
+#include <algorithm>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/location.h"
@@ -99,7 +101,7 @@
 }
 
 void LameWindowCapturerChromeOS::ChangeTarget(
-    const viz::FrameSinkId& frame_sink_id) {
+    const base::Optional<viz::FrameSinkId>& frame_sink_id) {
   // The LameWindowCapturerChromeOS does not capture from compositor frame
   // sinks.
 }
diff --git a/content/browser/media/capture/lame_window_capturer_chromeos.h b/content/browser/media/capture/lame_window_capturer_chromeos.h
index 6978f75..2a467ecc 100644
--- a/content/browser/media/capture/lame_window_capturer_chromeos.h
+++ b/content/browser/media/capture/lame_window_capturer_chromeos.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_BROWSER_MEDIA_CAPTURE_LAME_WINDOW_CAPTURER_CHROMEOS_H_
 #define CONTENT_BROWSER_MEDIA_CAPTURE_LAME_WINDOW_CAPTURER_CHROMEOS_H_
 
+#include <memory>
 #include <utility>
 #include <vector>
 
@@ -60,7 +61,8 @@
                                 const gfx::Size& max_size,
                                 bool use_fixed_aspect_ratio) final;
   void SetAutoThrottlingEnabled(bool enabled) final;
-  void ChangeTarget(const viz::FrameSinkId& frame_sink_id) final;
+  void ChangeTarget(
+      const base::Optional<viz::FrameSinkId>& frame_sink_id) final;
   void Start(viz::mojom::FrameSinkVideoConsumerPtr consumer) final;
   void Stop() final;
   void RequestRefreshFrame() final;
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc
index f2de22c..3cf4e5d1 100644
--- a/content/browser/ppapi_plugin_process_host.cc
+++ b/content/browser/ppapi_plugin_process_host.cc
@@ -29,7 +29,6 @@
 #include "content/public/common/process_type.h"
 #include "content/public/common/sandboxed_process_launcher_delegate.h"
 #include "content/public/common/service_names.mojom.h"
-#include "mojo/edk/embedder/embedder.h"
 #include "net/base/network_change_notifier.h"
 #include "ppapi/proxy/ppapi_messages.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h
index e64224a..ac6a5a5 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -196,7 +196,8 @@
 
   // Weak pointer to the layer supplied and reset via SetParentUiLayer. |this|
   // is an observer of |parent_ui_layer_|, to ensure that |parent_ui_layer_|
-  // always be valid when non-null.
+  // always be valid when non-null. The UpdateState function will re-parent
+  // |root_layer_| to be under |parent_ui_layer_|, if needed.
   ui::Layer* parent_ui_layer_ = nullptr;
   bool render_widget_host_is_hidden_ = true;
   bool ns_view_attached_to_window_ = false;
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index 2cac083..e23d2f9 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -407,9 +407,12 @@
   // Note that the state enum values represent the other through which
   // transitions must be done (see comments in State definition).
 
-  // Transition UseParentLayerCompositor -> HasNoCompositor.
+  // Transition UseParentLayerCompositor -> HasNoCompositor. Note that this
+  // transition will be made if we are already in UseParentLayerCompositor, but
+  // with a different parent layer.
   if (state_ == UseParentLayerCompositor &&
-      new_state < UseParentLayerCompositor) {
+      (new_state < UseParentLayerCompositor ||
+       parent_ui_layer_ != root_layer_->parent())) {
     DCHECK(root_layer_->parent());
     root_layer_->parent()->RemoveObserver(this);
     root_layer_->parent()->Remove(root_layer_.get());
@@ -582,16 +585,16 @@
 }
 
 void BrowserCompositorMac::SetParentUiLayer(ui::Layer* new_parent_ui_layer) {
-  if (new_parent_ui_layer) {
+  if (new_parent_ui_layer)
     DCHECK(new_parent_ui_layer->GetCompositor());
-    DCHECK(!parent_ui_layer_);
-    parent_ui_layer_ = new_parent_ui_layer;
-  } else if (parent_ui_layer_) {
-    DCHECK(root_layer_->parent());
-    DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
-    parent_ui_layer_ = nullptr;
-  }
+
+  // Set |parent_ui_layer_| to the new value, which potentially not match the
+  // value of |root_layer_->parent()|. The call to UpdateState will re-parent
+  // |root_layer_|.
+  DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
+  parent_ui_layer_ = new_parent_ui_layer;
   UpdateState();
+  DCHECK_EQ(root_layer_->parent(), parent_ui_layer_);
 }
 
 bool BrowserCompositorMac::ForceNewSurfaceForTesting() {
diff --git a/content/browser/renderer_host/input/fling_controller.cc b/content/browser/renderer_host/input/fling_controller.cc
index 42a5c34..19b1497 100644
--- a/content/browser/renderer_host/input/fling_controller.cc
+++ b/content/browser/renderer_host/input/fling_controller.cc
@@ -6,6 +6,8 @@
 
 #include "base/trace_event/trace_event.h"
 #include "content/browser/renderer_host/input/gesture_event_queue.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/blink/fling_booster.h"
@@ -420,7 +422,8 @@
       ui::WebGestureCurveImpl::CreateFromDefaultPlatformCurve(
           current_fling_parameters_.source_device,
           current_fling_parameters_.velocity,
-          gfx::Vector2dF() /*initial_offset*/, false /*on_main_thread*/));
+          gfx::Vector2dF() /*initial_offset*/, false /*on_main_thread*/,
+          GetContentClient()->browser()->ShouldUseMobileFlingCurve()));
   return true;
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm b/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
similarity index 83%
rename from content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
rename to content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
index 54b1c71b..47338f7 100644
--- a/content/browser/renderer_host/render_widget_host_ns_view_bridge.mm
+++ b/content/browser/renderer_host/render_widget_host_ns_view_bridge_local.mm
@@ -27,13 +27,12 @@
 // Bridge to a locally-hosted NSView -- this is always instantiated in the same
 // process as the NSView. The caller of this interface may exist in another
 // process.
-class RenderWidgetHostViewNSViewBridgeLocal
-    : public RenderWidgetHostNSViewBridge,
-      public display::DisplayObserver {
+class RenderWidgetHostNSViewBridgeLocal : public RenderWidgetHostNSViewBridge,
+                                          public display::DisplayObserver {
  public:
-  explicit RenderWidgetHostViewNSViewBridgeLocal(
+  explicit RenderWidgetHostNSViewBridgeLocal(
       RenderWidgetHostNSViewClient* client);
-  ~RenderWidgetHostViewNSViewBridgeLocal() override;
+  ~RenderWidgetHostNSViewBridgeLocal() override;
   RenderWidgetHostViewCocoa* GetRenderWidgetHostViewCocoa() override;
 
   void InitAsPopup(const gfx::Rect& content_rect,
@@ -91,10 +90,10 @@
   // Cached copy of the tooltip text, to avoid redundant calls.
   base::string16 tooltip_text_;
 
-  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewNSViewBridgeLocal);
+  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostNSViewBridgeLocal);
 };
 
-RenderWidgetHostViewNSViewBridgeLocal::RenderWidgetHostViewNSViewBridgeLocal(
+RenderWidgetHostNSViewBridgeLocal::RenderWidgetHostNSViewBridgeLocal(
     RenderWidgetHostNSViewClient* client) {
   display::Screen::GetScreen()->AddObserver(this);
 
@@ -107,8 +106,7 @@
   [cocoa_view_ setWantsLayer:YES];
 }
 
-RenderWidgetHostViewNSViewBridgeLocal::
-    ~RenderWidgetHostViewNSViewBridgeLocal() {
+RenderWidgetHostNSViewBridgeLocal::~RenderWidgetHostNSViewBridgeLocal() {
   [cocoa_view_ setClientDisconnected];
   // Do not immediately remove |cocoa_view_| from the NSView heirarchy, because
   // the call to -[NSView removeFromSuperview] may cause use to call into the
@@ -123,11 +121,11 @@
 }
 
 RenderWidgetHostViewCocoa*
-RenderWidgetHostViewNSViewBridgeLocal::GetRenderWidgetHostViewCocoa() {
+RenderWidgetHostNSViewBridgeLocal::GetRenderWidgetHostViewCocoa() {
   return cocoa_view_;
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::InitAsPopup(
+void RenderWidgetHostNSViewBridgeLocal::InitAsPopup(
     const gfx::Rect& content_rect,
     blink::WebPopupType popup_type) {
   popup_type_ = popup_type;
@@ -135,11 +133,11 @@
       std::make_unique<PopupWindowMac>(content_rect, popup_type_, cocoa_view_);
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::MakeFirstResponder() {
+void RenderWidgetHostNSViewBridgeLocal::MakeFirstResponder() {
   [[cocoa_view_ window] makeFirstResponder:cocoa_view_];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::DisableDisplay() {
+void RenderWidgetHostNSViewBridgeLocal::DisableDisplay() {
   if (display_disabled_)
     return;
   SetBackgroundColor(SK_ColorTRANSPARENT);
@@ -147,7 +145,7 @@
   display_disabled_ = true;
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetBounds(const gfx::Rect& rect) {
+void RenderWidgetHostNSViewBridgeLocal::SetBounds(const gfx::Rect& rect) {
   // |rect.size()| is view coordinates, |rect.origin| is screen coordinates,
   // TODO(thakis): fix, http://crbug.com/73362
 
@@ -188,14 +186,14 @@
   }
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetCALayerParams(
+void RenderWidgetHostNSViewBridgeLocal::SetCALayerParams(
     const gfx::CALayerParams& ca_layer_params) {
   if (display_disabled_)
     return;
   display_ca_layer_tree_->UpdateCALayerTree(ca_layer_params);
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetBackgroundColor(SkColor color) {
+void RenderWidgetHostNSViewBridgeLocal::SetBackgroundColor(SkColor color) {
   if (display_disabled_)
     return;
   ScopedCAActionDisabler disabler;
@@ -204,12 +202,12 @@
   [background_layer_ setBackgroundColor:cg_color];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetVisible(bool visible) {
+void RenderWidgetHostNSViewBridgeLocal::SetVisible(bool visible) {
   ScopedCAActionDisabler disabler;
   [cocoa_view_ setHidden:!visible];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetTooltipText(
+void RenderWidgetHostNSViewBridgeLocal::SetTooltipText(
     const base::string16& tooltip_text) {
   // Called from the renderer to tell us what the tooltip text should be. It
   // calls us frequently so we need to cache the value to prevent doing a lot
@@ -233,22 +231,22 @@
   [cocoa_view_ setToolTipAtMousePoint:tooltip_nsstring];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetCompositionRangeInfo(
+void RenderWidgetHostNSViewBridgeLocal::SetCompositionRangeInfo(
     const gfx::Range& range) {
   [cocoa_view_ setCompositionRange:range];
   [cocoa_view_ setMarkedRange:range.ToNSRange()];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::CancelComposition() {
+void RenderWidgetHostNSViewBridgeLocal::CancelComposition() {
   [cocoa_view_ cancelComposition];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetTextInputType(
+void RenderWidgetHostNSViewBridgeLocal::SetTextInputType(
     ui::TextInputType text_input_type) {
   [cocoa_view_ setTextInputType:text_input_type];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetTextSelection(
+void RenderWidgetHostNSViewBridgeLocal::SetTextSelection(
     const base::string16& text,
     size_t offset,
     const gfx::Range& range) {
@@ -261,12 +259,11 @@
   }
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetShowingContextMenu(
-    bool showing) {
+void RenderWidgetHostNSViewBridgeLocal::SetShowingContextMenu(bool showing) {
   [cocoa_view_ setShowingContextMenu:showing];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::OnDisplayMetricsChanged(
+void RenderWidgetHostNSViewBridgeLocal::OnDisplayMetricsChanged(
     const display::Display& display,
     uint32_t changed_metrics) {
   // Note that -updateScreenProperties is also be called by the notification
@@ -275,13 +272,12 @@
   [cocoa_view_ updateScreenProperties];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::DisplayCursor(
-    const WebCursor& cursor) {
+void RenderWidgetHostNSViewBridgeLocal::DisplayCursor(const WebCursor& cursor) {
   WebCursor non_const_cursor = cursor;
   [cocoa_view_ updateCursor:non_const_cursor.GetNativeCursor()];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::SetCursorLocked(bool locked) {
+void RenderWidgetHostNSViewBridgeLocal::SetCursorLocked(bool locked) {
   if (locked) {
     CGAssociateMouseAndMouseCursorPosition(NO);
     [NSCursor hide];
@@ -292,13 +288,12 @@
   }
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::
-    ShowDictionaryOverlayForSelection() {
+void RenderWidgetHostNSViewBridgeLocal::ShowDictionaryOverlayForSelection() {
   NSRange selection_range = [cocoa_view_ selectedRange];
   [cocoa_view_ showLookUpDictionaryOverlayFromRange:selection_range];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::ShowDictionaryOverlay(
+void RenderWidgetHostNSViewBridgeLocal::ShowDictionaryOverlay(
     const mac::AttributedStringCoder::EncodedString& encoded_string,
     gfx::Point baseline_point) {
   NSAttributedString* string =
@@ -312,12 +307,12 @@
                                          atPoint:flipped_baseline_point];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::LockKeyboard(
+void RenderWidgetHostNSViewBridgeLocal::LockKeyboard(
     base::Optional<base::flat_set<ui::DomCode>> dom_codes) {
   [cocoa_view_ lockKeyboard:std::move(dom_codes)];
 }
 
-void RenderWidgetHostViewNSViewBridgeLocal::UnlockKeyboard() {
+void RenderWidgetHostNSViewBridgeLocal::UnlockKeyboard() {
   [cocoa_view_ unlockKeyboard];
 }
 
@@ -326,7 +321,7 @@
 // static
 std::unique_ptr<RenderWidgetHostNSViewBridge>
 RenderWidgetHostNSViewBridge::Create(RenderWidgetHostNSViewClient* client) {
-  return std::make_unique<RenderWidgetHostViewNSViewBridgeLocal>(client);
+  return std::make_unique<RenderWidgetHostNSViewBridgeLocal>(client);
 }
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
index df4cc74..1c6240d 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -260,6 +260,7 @@
   // with the navigation commit.
   SubresourceLoaderParams params;
   auto controller_info = mojom::ControllerServiceWorkerInfo::New();
+  controller_info->mode = provider_host_->GetControllerMode();
   // Note that |controller_info->endpoint| is null if the controller has no
   // fetch event handler. In that case the renderer frame won't get the
   // controller pointer upon the navigation commit, and subresource loading will
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 86bd226..dd95aa10 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -301,6 +301,24 @@
   return schemes.find(document_url().scheme()) != schemes.end();
 }
 
+blink::mojom::ControllerServiceWorkerMode
+ServiceWorkerProviderHost::GetControllerMode() const {
+  if (!controller_)
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  switch (controller_->fetch_handler_existence()) {
+    case ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST:
+      return blink::mojom::ControllerServiceWorkerMode::kNoFetchEventHandler;
+    case ServiceWorkerVersion::FetchHandlerExistence::EXISTS:
+      return blink::mojom::ControllerServiceWorkerMode::kControlled;
+    case ServiceWorkerVersion::FetchHandlerExistence::UNKNOWN:
+      // UNKNOWN means the controller is still installing. It's not possible to
+      // have a controller that hasn't finished installing.
+      NOTREACHED();
+  }
+  NOTREACHED();
+  return blink::mojom::ControllerServiceWorkerMode::kNoController;
+}
+
 void ServiceWorkerProviderHost::OnVersionAttributesChanged(
     ServiceWorkerRegistration* registration,
     ChangedVersionAttributesMask changed_mask,
@@ -778,6 +796,13 @@
   DCHECK(associated_registration_);
   DCHECK_EQ(associated_registration_->active_version(), controller_.get());
 
+  controller_info->mode = GetControllerMode();
+
+  // S13nServiceWorker: Pass an endpoint for the client to talk to this
+  // controller.
+  if (ServiceWorkerUtils::IsServicificationEnabled())
+    controller_info->endpoint = GetControllerServiceWorkerPtr().PassInterface();
+
   // Set the info for the JavaScript ServiceWorkerContainer#controller object.
   base::WeakPtr<ServiceWorkerObjectHost> object_host =
       GetOrCreateServiceWorkerObjectHost(controller_);
@@ -790,10 +815,6 @@
   for (const blink::mojom::WebFeature feature : controller_->used_features())
     used_features.push_back(feature);
 
-  // S13nServiceWorker: Pass an endpoint for the client to talk to this
-  // controller.
-  if (ServiceWorkerUtils::IsServicificationEnabled())
-    controller_info->endpoint = GetControllerServiceWorkerPtr().PassInterface();
 
   container_->SetController(std::move(controller_info), used_features,
                             notify_controllerchange);
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 2cc0106..13ba29d 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -194,6 +194,10 @@
   // security, so they must be set properly before calling this function.
   bool IsContextSecureForServiceWorker() const;
 
+  // For service worker clients. Describes whether the client has a controller
+  // and if it has a fetch event handler.
+  blink::mojom::ControllerServiceWorkerMode GetControllerMode() const;
+
   // Returns this provider's controller. The controller is typically the same as
   // active_version() but can differ in the following cases:
   // (1) The client was created before the registration existed or had an active
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index c6b85e19..977e047 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -442,6 +442,9 @@
   scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
       registration1_.get(), GURL("https://www.example.com/sw.js"),
       1 /* version_id */, helper_->context()->AsWeakPtr());
+  version->set_fetch_handler_existence(
+      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+  version->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration1_->SetActiveVersion(version);
 
   // Finish the navigation.
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index af56cc5..6c40b5e 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -191,7 +191,7 @@
 
   // This status is set to EXISTS or DOES_NOT_EXIST when the install event has
   // been executed in a new version or when an installed version is loaded from
-  // the storage. When a new version is not installed yet, it is  UNKNOW.
+  // the storage. When a new version is not installed yet, it is UNKNOWN.
   FetchHandlerExistence fetch_handler_existence() const {
     return fetch_handler_existence_;
   }
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index c98f421..7dc950d 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -6,6 +6,7 @@
 
 #include <stdint.h>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/android/callback_android.h"
@@ -643,7 +644,7 @@
           overscroll_refresh_handler));
 }
 
-void WebContentsAndroid::GetContentBitmap(
+void WebContentsAndroid::WriteContentBitmapToDisk(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj,
     jint width,
@@ -768,7 +769,6 @@
     const std::string& path,
     const SkBitmap& bitmap) {
   JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> java_bitmap;
   if (!bitmap.drawsNothing()) {
     auto task_runner = base::CreateSequencedTaskRunnerWithTraits(
         {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
diff --git a/content/browser/web_contents/web_contents_android.h b/content/browser/web_contents/web_contents_android.h
index ed24f73..aff5c38 100644
--- a/content/browser/web_contents/web_contents_android.h
+++ b/content/browser/web_contents/web_contents_android.h
@@ -178,12 +178,13 @@
       const base::android::JavaParamRef<jobject>& overscroll_refresh_handler);
 
   // Relay the access from Java layer to RWHV::CopyFromSurface() through JNI.
-  void GetContentBitmap(JNIEnv* env,
-                        const base::android::JavaParamRef<jobject>& obj,
-                        jint width,
-                        jint height,
-                        const base::android::JavaParamRef<jstring>& jpath,
-                        const base::android::JavaParamRef<jobject>& jcallback);
+  void WriteContentBitmapToDisk(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint width,
+      jint height,
+      const base::android::JavaParamRef<jstring>& jpath,
+      const base::android::JavaParamRef<jobject>& jcallback);
 
   void ReloadLoFiImages(JNIEnv* env,
                         const base::android::JavaParamRef<jobject>& obj);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 661ca89..1f30c885 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1603,10 +1603,6 @@
   return last_active_time_;
 }
 
-void WebContentsImpl::SetLastActiveTime(base::TimeTicks last_active_time) {
-  last_active_time_ = last_active_time;
-}
-
 void WebContentsImpl::WasShown() {
   controller_.SetActive(true);
 
@@ -1879,6 +1875,9 @@
   visibility_ =
       params.initially_hidden ? Visibility::HIDDEN : Visibility::VISIBLE;
 
+  if (!params.last_active_time.is_null())
+    last_active_time_ = params.last_active_time;
+
   // The routing ids must either all be set or all be unset.
   DCHECK((params.routing_id == MSG_ROUTING_NONE &&
           params.main_frame_routing_id == MSG_ROUTING_NONE &&
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 0b541ff..06aa9549 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -359,7 +359,6 @@
   void NotifyNavigationStateChanged(InvalidateTypes changed_flags) override;
   void OnAudioStateChanged() override;
   base::TimeTicks GetLastActiveTime() const override;
-  void SetLastActiveTime(base::TimeTicks last_active_time) override;
   void WasShown() override;
   void WasHidden() override;
   void WasOccluded() override;
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc
index 2ff424d..678ab07 100644
--- a/content/browser/webauth/authenticator_impl.cc
+++ b/content/browser/webauth/authenticator_impl.cc
@@ -815,7 +815,8 @@
   if (base::FeatureList::IsEnabled(features::kWebAuthTouchId)) {
     if (__builtin_available(macOS 10.12.2, *)) {
       return device::fido::mac::TouchIdAuthenticator::CreateIfAvailable(
-          request_delegate_->TouchIdAuthenticatorKeychainAccessGroup());
+          request_delegate_->TouchIdAuthenticatorKeychainAccessGroup(),
+          request_delegate_->TouchIdMetadataSecret());
     }
   }
 #endif
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index 1cc94be..ed5e362 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -672,7 +672,7 @@
   return ui::WebGestureCurveImpl::CreateFromDefaultPlatformCurve(
       device_source, gfx::Vector2dF(velocity.x, velocity.y),
       gfx::Vector2dF(cumulative_scroll.width, cumulative_scroll.height),
-      IsMainThread());
+      IsMainThread(), false /*use_mobile_fling_curve*/);
 }
 
 bool BlinkPlatformImpl::AllowScriptExtensionForServiceWorker(
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 729ec6fb..871ebc1 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -352,7 +352,6 @@
     "//media/gpu/ipc/common",
     "//media/midi",
     "//media/midi:mojo",
-    "//mojo/edk",
     "//mojo/public/cpp/system",
     "//net",
     "//ppapi/buildflags",
diff --git a/content/common/service_manager/DEPS b/content/common/service_manager/DEPS
index b583263..c610d2e 100644
--- a/content/common/service_manager/DEPS
+++ b/content/common/service_manager/DEPS
@@ -1,5 +1,3 @@
 include_rules = [
-  "+mojo/converters/network",
-  "+mojo/edk/embedder",
   "+services/service_manager",
 ]
diff --git a/content/common/service_worker/controller_service_worker.mojom b/content/common/service_worker/controller_service_worker.mojom
index 3bb0792865..9affb8e 100644
--- a/content/common/service_worker/controller_service_worker.mojom
+++ b/content/common/service_worker/controller_service_worker.mojom
@@ -54,9 +54,14 @@
 // information from the browser process to the renderer process on navigation
 // commit, and also as a parameter of ServiceWorkerContainer.SetController().
 struct ControllerServiceWorkerInfo {
-  // S13nServiceWorker:
-  // Non-null iff the controller has a fetch event handler.
+  // Describes whether there is a controller and it has a fetch event handler.
+  blink.mojom.ControllerServiceWorkerMode mode =
+      blink.mojom.ControllerServiceWorkerMode.kNoController;
+
+  // S13nServiceWorker only:
+  // Non-null iff there is a controller and it has a fetch event handler.
   ControllerServiceWorker? endpoint;
+
   // S13nServiceWorker:
   // The client being controlled, used for FetchEvent#clientId. The ID is
   // issued by the browser process for this receiving client, and would
diff --git a/content/common/service_worker/service_worker_provider.mojom b/content/common/service_worker/service_worker_provider.mojom
index e41681a..a423fb39 100644
--- a/content/common/service_worker/service_worker_provider.mojom
+++ b/content/common/service_worker/service_worker_provider.mojom
@@ -7,6 +7,7 @@
 import "content/common/service_worker/service_worker_container.mojom";
 import "services/network/public/mojom/url_loader_factory.mojom";
 import "services/service_manager/public/mojom/interface_provider.mojom";
+import "third_party/blink/public/mojom/service_worker/service_worker_object.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom";
 
@@ -67,5 +68,5 @@
   // Called when the worker is controlled by a new service worker. This is only
   // used to let the worker know that we now have a service worker (while there
   // may or may not have been one previously), but not the other way around.
-  OnControllerChanged();
+  OnControllerChanged(blink.mojom.ControllerServiceWorkerMode mode);
 };
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
index 45e41e9..7e004a6 100644
--- a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
+++ b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
@@ -184,7 +184,7 @@
 
     @Override
     public void runMain() {
-        ContentMain.start();
+        ContentMain.start(false);
     }
 
     // Return a Linker instance. If testing, the Linker needs special setup.
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentMain.java b/content/public/android/java/src/org/chromium/content/app/ContentMain.java
index 06ed50d3..523a9ee 100644
--- a/content/public/android/java/src/org/chromium/content/app/ContentMain.java
+++ b/content/public/android/java/src/org/chromium/content/app/ContentMain.java
@@ -22,10 +22,12 @@
 public class ContentMain {
     /**
      * Start the ContentMainRunner in native side.
+     *
+     * @param startServiceManagerOnly Whether to start only the ServiceManager.
      **/
-    public static int start() {
-        return nativeStart();
+    public static int start(boolean startServiceManagerOnly) {
+        return nativeStart(startServiceManagerOnly);
     }
 
-    private static native int nativeStart();
+    private static native int nativeStart(boolean startServiceManagerOnly);
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
index c5032b5f6..92901c19 100644
--- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.StrictMode;
+import android.support.annotation.IntDef;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -23,6 +24,8 @@
 import org.chromium.content_public.browser.BrowserStartupController.StartupCallback;
 import org.chromium.ui.resources.ResourceExtractor;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -40,6 +43,12 @@
     @VisibleForTesting
     static final int STARTUP_FAILURE = 1;
 
+    @IntDef({BROWSER_START_TYPE_FULL_BROWSER, BROWSER_START_TYPE_SERVICE_MANAGER_ONLY})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BrowserStartType {}
+    private static final int BROWSER_START_TYPE_FULL_BROWSER = 0;
+    private static final int BROWSER_START_TYPE_SERVICE_MANAGER_ONLY = 1;
+
     private static BrowserStartupControllerImpl sInstance;
 
     private static boolean sShouldStartGpuProcessOnBrowserStartup;
@@ -57,6 +66,13 @@
     }
 
     @CalledByNative
+    static void serviceManagerStartupComplete() {
+        if (sInstance != null) {
+            sInstance.serviceManagerStarted();
+        }
+    }
+
+    @CalledByNative
     static boolean shouldStartGpuProcessOnBrowserStartup() {
         return sShouldStartGpuProcessOnBrowserStartup;
     }
@@ -65,6 +81,13 @@
     // complete.
     private final List<StartupCallback> mAsyncStartupCallbacks;
 
+    // A list of callbacks that should be called when the ServiceManager is started. These callbacks
+    // will be called once all the ongoing requests to start ServiceManager or full browser process
+    // are completed. For example, if there is no outstanding request to start full browser process,
+    // the callbacks will be executed once ServiceManager starts. On the other hand, the callbacks
+    // will be defered until full browser starts.
+    private final List<StartupCallback> mServiceManagerCallbacks;
+
     // Whether the async startup of the browser process has started.
     private boolean mHasStartedInitializingBrowserProcess;
 
@@ -74,7 +97,7 @@
     private boolean mHasCalledContentStart;
 
     // Whether the async startup of the browser process is complete.
-    private boolean mStartupDone;
+    private boolean mFullBrowserStartupDone;
 
     // This field is set after startup has been completed based on whether the startup was a success
     // or not. It is used when later requests to startup come in that happen after the initial set
@@ -83,10 +106,26 @@
 
     private int mLibraryProcessType;
 
+    // Browser start up type. If the type is |BROWSER_START_TYPE_SERVICE_MANAGER_ONLY|, start up
+    // will be paused after ServiceManager is launched. Additional request to launch the full
+    // browser process is needed to fully complete the startup process. Callbacks will executed
+    // once the browser is fully started, or when the ServiceManager is started and there is no
+    // outstanding requests to start the full browser.
+    @BrowserStartType
+    private int mCurrentBrowserStartType = BROWSER_START_TYPE_FULL_BROWSER;
+
+    // If the app is only started with the ServiceManager, whether it needs to launch full browser
+    // funcionalities now.
+    private boolean mLaunchFullBrowserAfterServiceManagerStart;
+
+    // Whether ServiceManager is started.
+    private boolean mServiceManagerStarted;
+
     private TracingControllerAndroid mTracingController;
 
     BrowserStartupControllerImpl(int libraryProcessType) {
         mAsyncStartupCallbacks = new ArrayList<>();
+        mServiceManagerCallbacks = new ArrayList<>();
         mLibraryProcessType = libraryProcessType;
         ThreadUtils.postOnUiThread(new Runnable() {
             @Override
@@ -135,10 +174,10 @@
     }
 
     @Override
-    public void startBrowserProcessesAsync(boolean startGpuProcess, final StartupCallback callback)
-            throws ProcessInitException {
+    public void startBrowserProcessesAsync(boolean startGpuProcess, boolean startServiceManagerOnly,
+            final StartupCallback callback) throws ProcessInitException {
         assert ThreadUtils.runningOnUiThread() : "Tried to start the browser on the wrong thread.";
-        if (mStartupDone) {
+        if (mFullBrowserStartupDone || (startServiceManagerOnly && mServiceManagerStarted)) {
             // Browser process initialization has already been completed, so we can immediately post
             // the callback.
             postStartupCompleted(callback);
@@ -146,43 +185,67 @@
         }
 
         // Browser process has not been fully started yet, so we defer executing the callback.
-        mAsyncStartupCallbacks.add(callback);
-
+        if (startServiceManagerOnly) {
+            mServiceManagerCallbacks.add(callback);
+        } else {
+            mAsyncStartupCallbacks.add(callback);
+        }
+        // If the browser process is launched with ServiceManager only, we need to relaunch the full
+        // process in serviceManagerStarted() if such a request was received.
+        mLaunchFullBrowserAfterServiceManagerStart |=
+                (mCurrentBrowserStartType == BROWSER_START_TYPE_SERVICE_MANAGER_ONLY)
+                && !startServiceManagerOnly;
         if (!mHasStartedInitializingBrowserProcess) {
             // This is the first time we have been asked to start the browser process. We set the
             // flag that indicates that we have kicked off starting the browser process.
             mHasStartedInitializingBrowserProcess = true;
 
             setShouldStartGpuProcessOnBrowserStartup(startGpuProcess);
+
             prepareToStartBrowserProcess(false, new Runnable() {
                 @Override
                 public void run() {
                     ThreadUtils.assertOnUiThread();
                     if (mHasCalledContentStart) return;
+                    mCurrentBrowserStartType = startServiceManagerOnly
+                            ? BROWSER_START_TYPE_SERVICE_MANAGER_ONLY
+                            : BROWSER_START_TYPE_FULL_BROWSER;
                     if (contentStart() > 0) {
                         // Failed. The callbacks may not have run, so run them.
                         enqueueCallbackExecution(STARTUP_FAILURE);
                     }
                 }
             });
+        } else if (mServiceManagerStarted && mLaunchFullBrowserAfterServiceManagerStart) {
+            // If we missed the serviceManagerStarted() call, launch the full browser now if needed.
+            // Otherwise, serviceManagerStarted() will handle the full browser launch.
+            mCurrentBrowserStartType = BROWSER_START_TYPE_FULL_BROWSER;
+            if (contentStart() > 0) enqueueCallbackExecution(STARTUP_FAILURE);
         }
     }
 
     @Override
     public void startBrowserProcessesSync(boolean singleProcess) throws ProcessInitException {
         // If already started skip to checking the result
-        if (!mStartupDone) {
+        if (!mFullBrowserStartupDone) {
             if (!mHasStartedInitializingBrowserProcess || !mPostResourceExtractionTasksCompleted) {
                 prepareToStartBrowserProcess(singleProcess, null);
             }
 
             boolean startedSuccessfully = true;
             if (!mHasCalledContentStart) {
+                mCurrentBrowserStartType = BROWSER_START_TYPE_FULL_BROWSER;
                 if (contentStart() > 0) {
                     // Failed. The callbacks may not have run, so run them.
                     enqueueCallbackExecution(STARTUP_FAILURE);
                     startedSuccessfully = false;
                 }
+            } else if (mCurrentBrowserStartType == BROWSER_START_TYPE_SERVICE_MANAGER_ONLY) {
+                mCurrentBrowserStartType = BROWSER_START_TYPE_FULL_BROWSER;
+                if (contentStart() > 0) {
+                    enqueueCallbackExecution(STARTUP_FAILURE);
+                    startedSuccessfully = false;
+                }
             }
             if (startedSuccessfully) {
                 flushStartupTasks();
@@ -190,20 +253,31 @@
         }
 
         // Startup should now be complete
-        assert mStartupDone;
+        assert mFullBrowserStartupDone;
         if (!mStartupSuccess) {
             throw new ProcessInitException(LoaderErrors.LOADER_ERROR_NATIVE_STARTUP_FAILED);
         }
     }
 
     /**
+     * Start the browser process by calling ContentMain.start().
+     */
+    int contentStart() {
+        boolean startServiceManagerOnly =
+                mCurrentBrowserStartType == BROWSER_START_TYPE_SERVICE_MANAGER_ONLY;
+        int result = contentMainStart(startServiceManagerOnly);
+        mHasCalledContentStart = true;
+        // No need to launch the full browser again if we are launching full browser now.
+        if (!startServiceManagerOnly) mLaunchFullBrowserAfterServiceManagerStart = false;
+        return result;
+    }
+
+    /**
      * Wrap ContentMain.start() for testing.
      */
     @VisibleForTesting
-    int contentStart() {
-        assert !mHasCalledContentStart;
-        mHasCalledContentStart = true;
-        return ContentMain.start();
+    int contentMainStart(boolean startServiceManagerOnly) {
+        return ContentMain.start(startServiceManagerOnly);
     }
 
     @VisibleForTesting
@@ -214,32 +288,63 @@
     @Override
     public boolean isStartupSuccessfullyCompleted() {
         ThreadUtils.assertOnUiThread();
-        return mStartupDone && mStartupSuccess;
+        return mFullBrowserStartupDone && mStartupSuccess;
     }
 
     @Override
     public void addStartupCompletedObserver(StartupCallback callback) {
         ThreadUtils.assertOnUiThread();
-        if (mStartupDone) {
+        if (mFullBrowserStartupDone) {
             postStartupCompleted(callback);
         } else {
             mAsyncStartupCallbacks.add(callback);
         }
     }
 
+    /**
+     * Called when ServiceManager is launched.
+     */
+    private void serviceManagerStarted() {
+        mServiceManagerStarted = true;
+        if (mLaunchFullBrowserAfterServiceManagerStart) {
+            // If startFullBrowser() fails, execute the callbacks right away. Otherwise,
+            // callbacks will be deferred until browser startup completes.
+            mCurrentBrowserStartType = BROWSER_START_TYPE_FULL_BROWSER;
+            if (contentStart() > 0) enqueueCallbackExecution(STARTUP_FAILURE);
+        } else if (mCurrentBrowserStartType == BROWSER_START_TYPE_SERVICE_MANAGER_ONLY) {
+            // If full browser startup is not needed, execute all the callbacks now.
+            executeEnqueuedCallbacks(STARTUP_SUCCESS);
+        }
+    }
+
     private void executeEnqueuedCallbacks(int startupResult) {
         assert ThreadUtils.runningOnUiThread() : "Callback from browser startup from wrong thread.";
-        mStartupDone = true;
+        // If only ServiceManager is launched, don't set mFullBrowserStartupDone, wait for the full
+        // browser launch to set this variable.
+        mFullBrowserStartupDone = mCurrentBrowserStartType == BROWSER_START_TYPE_FULL_BROWSER;
         mStartupSuccess = (startupResult <= 0);
-        for (StartupCallback asyncStartupCallback : mAsyncStartupCallbacks) {
+        if (mFullBrowserStartupDone) {
+            for (StartupCallback asyncStartupCallback : mAsyncStartupCallbacks) {
+                if (mStartupSuccess) {
+                    asyncStartupCallback.onSuccess();
+                } else {
+                    asyncStartupCallback.onFailure();
+                }
+            }
+            // We don't want to hold on to any objects after we do not need them anymore.
+            mAsyncStartupCallbacks.clear();
+        }
+        // The ServiceManager should have been started, call the callbacks now.
+        // TODO(qinmin): Handle mServiceManagerCallbacks in serviceManagerStarted() instead of
+        // here once http://crbug.com/854231 is fixed.
+        for (StartupCallback serviceMangerCallback : mServiceManagerCallbacks) {
             if (mStartupSuccess) {
-                asyncStartupCallback.onSuccess();
+                serviceMangerCallback.onSuccess();
             } else {
-                asyncStartupCallback.onFailure();
+                serviceMangerCallback.onFailure();
             }
         }
-        // We don't want to hold on to any objects after we do not need them anymore.
-        mAsyncStartupCallbacks.clear();
+        mServiceManagerCallbacks.clear();
     }
 
     // Queue the callbacks to run. Since running the callbacks clears the list it is safe to call
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java
index feba7a5..3319eda 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java
@@ -14,7 +14,7 @@
 import org.chromium.content.browser.input.ImeAdapterImpl;
 import org.chromium.content.browser.webcontents.WebContentsImpl;
 import org.chromium.content.browser.webcontents.WebContentsUserData;
-import org.chromium.content_public.browser.ContentViewCore;
+import org.chromium.content_public.browser.ViewEventSink.InternalAccessDelegate;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContents.UserDataFactory;
 import org.chromium.device.gamepad.GamepadList;
@@ -27,7 +27,7 @@
 @JNINamespace("content")
 public class ContentUiEventHandler {
     private final WebContentsImpl mWebContents;
-    private ContentViewCore.InternalAccessDelegate mEventDelegate;
+    private InternalAccessDelegate mEventDelegate;
     private long mNativeContentUiEventHandler;
 
     private static final class UserDataFactoryLazyHolder {
@@ -45,7 +45,7 @@
         mNativeContentUiEventHandler = nativeInit(webContents);
     }
 
-    public void setEventDelegate(ContentViewCore.InternalAccessDelegate delegate) {
+    public void setEventDelegate(InternalAccessDelegate delegate) {
         mEventDelegate = delegate;
     }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
index b1b58f18..407f89ca 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCoreImpl.java
@@ -14,7 +14,7 @@
 import org.chromium.content.browser.selection.SelectionPopupControllerImpl;
 import org.chromium.content.browser.webcontents.WebContentsImpl;
 import org.chromium.content_public.browser.ContentViewCore;
-import org.chromium.content_public.browser.ContentViewCore.InternalAccessDelegate;
+import org.chromium.content_public.browser.ViewEventSink.InternalAccessDelegate;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContents.UserDataFactory;
 import org.chromium.ui.base.ViewAndroidDelegate;
@@ -84,7 +84,7 @@
         SelectPopup.create(context, mWebContents);
         Gamepad.create(context, mWebContents);
 
-        setContainerViewInternals(internalDispatcher);
+        ViewEventSinkImpl.from(mWebContents).setAccessDelegate(internalDispatcher);
         mWebContents.getRenderCoordinates().setDeviceScaleFactor(
                 windowAndroid.getDisplay().getDipScale());
 
@@ -96,13 +96,6 @@
     }
 
     @Override
-    public void setContainerViewInternals(InternalAccessDelegate internalDispatcher) {
-        GestureListenerManagerImpl.fromWebContents(mWebContents)
-                .setScrollDelegate(internalDispatcher);
-        ContentUiEventHandler.fromWebContents(mWebContents).setEventDelegate(internalDispatcher);
-    }
-
-    @Override
     public void destroy() {
         // This is called to fix crash. See https://crbug.com/803244
         // TODO(jinsukkim): Use an observer to let the manager handle it on its own.
diff --git a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
index 0930635..43180afd 100644
--- a/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/GestureListenerManagerImpl.java
@@ -17,9 +17,9 @@
 import org.chromium.content.browser.selection.SelectionPopupControllerImpl;
 import org.chromium.content.browser.webcontents.WebContentsImpl;
 import org.chromium.content.browser.webcontents.WebContentsUserData;
-import org.chromium.content_public.browser.ContentViewCore.InternalAccessDelegate;
 import org.chromium.content_public.browser.GestureListenerManager;
 import org.chromium.content_public.browser.GestureStateListener;
+import org.chromium.content_public.browser.ViewEventSink.InternalAccessDelegate;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContents.UserDataFactory;
 import org.chromium.ui.base.GestureEventType;
diff --git a/content/public/android/java/src/org/chromium/content/browser/ViewEventSinkImpl.java b/content/public/android/java/src/org/chromium/content/browser/ViewEventSinkImpl.java
index a9476c6..bd053e1 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ViewEventSinkImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ViewEventSinkImpl.java
@@ -70,6 +70,12 @@
     }
 
     @Override
+    public void setAccessDelegate(ViewEventSink.InternalAccessDelegate accessDelegate) {
+        GestureListenerManagerImpl.fromWebContents(mWebContents).setScrollDelegate(accessDelegate);
+        ContentUiEventHandler.fromWebContents(mWebContents).setEventDelegate(accessDelegate);
+    }
+
+    @Override
     public void onAttachedToWindow() {
         WindowEventObserverManager.from(mWebContents).onAttachedToWindow();
     }
diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
index 03f91c5..4772080 100644
--- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java
@@ -672,9 +672,9 @@
     }
 
     @Override
-    public void getContentBitmapAsync(
+    public void writeContentBitmapToDiskAsync(
             int width, int height, String path, Callback<String> callback) {
-        nativeGetContentBitmap(mNativeWebContentsAndroid, width, height, path, callback);
+        nativeWriteContentBitmapToDisk(mNativeWebContentsAndroid, width, height, path, callback);
     }
 
     @Override
@@ -912,8 +912,8 @@
             long nativeWebContentsAndroid, AccessibilitySnapshotCallback callback);
     private native void nativeSetOverscrollRefreshHandler(
             long nativeWebContentsAndroid, OverscrollRefreshHandler nativeOverscrollRefreshHandler);
-    private native void nativeGetContentBitmap(long nativeWebContentsAndroid, int width, int height,
-            String path, Callback<String> callback);
+    private native void nativeWriteContentBitmapToDisk(long nativeWebContentsAndroid, int width,
+            int height, String path, Callback<String> callback);
     private native void nativeReloadLoFiImages(long nativeWebContentsAndroid);
     private native int nativeDownloadImage(long nativeWebContentsAndroid,
             String url, boolean isFavicon, int maxBitmapSize,
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/BrowserStartupController.java b/content/public/android/java/src/org/chromium/content_public/browser/BrowserStartupController.java
index e13cc10d..a8f195d 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/BrowserStartupController.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/BrowserStartupController.java
@@ -46,10 +46,12 @@
      * Note that this can only be called on the UI thread.
      *
      * @param startGpuProcess Whether to start the GPU process if it is not started.
+     * @param startServiceManagerOnly Whether browser startup will be paused after ServiceManager
+     *                                is started.
      * @param callback the callback to be called when browser startup is complete.
      */
-    void startBrowserProcessesAsync(boolean startGpuProcess, final StartupCallback callback)
-            throws ProcessInitException;
+    void startBrowserProcessesAsync(boolean startGpuProcess, boolean startServiceManagerOnly,
+            final StartupCallback callback) throws ProcessInitException;
 
     /**
      * Start the browser process synchronously. If the browser is already being started
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java
index ac3bd17..bbf8e31 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/ContentViewCore.java
@@ -5,11 +5,9 @@
 package org.chromium.content_public.browser;
 
 import android.content.Context;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
 
 import org.chromium.content.browser.ContentViewCoreImpl;
+import org.chromium.content_public.browser.ViewEventSink.InternalAccessDelegate;
 import org.chromium.ui.base.ViewAndroidDelegate;
 import org.chromium.ui.base.WindowAndroid;
 
@@ -44,44 +42,6 @@
     }
 
     /**
-     * Interface that consumers of {@link ContentViewCore} must implement to allow the proper
-     * dispatching of view methods through the containing view.
-     *
-     * <p>
-     * All methods with the "super_" prefix should be routed to the parent of the
-     * implementing container view.
-     */
-    @SuppressWarnings("javadoc")
-    public interface InternalAccessDelegate {
-        /**
-         * @see View#onKeyUp(keyCode, KeyEvent)
-         */
-        boolean super_onKeyUp(int keyCode, KeyEvent event);
-
-        /**
-         * @see View#dispatchKeyEvent(KeyEvent)
-         */
-        boolean super_dispatchKeyEvent(KeyEvent event);
-
-        /**
-         * @see View#onGenericMotionEvent(MotionEvent)
-         */
-        boolean super_onGenericMotionEvent(MotionEvent event);
-
-        /**
-         * @see View#onScrollChanged(int, int, int, int)
-         */
-        void onScrollChanged(int lPix, int tPix, int oldlPix, int oldtPix);
-    }
-
-    /**
-     * Set the Container view Internals.
-     * @param internalDispatcher Handles dispatching all hidden or super methods to the
-     *                           containerView.
-     */
-    void setContainerViewInternals(InternalAccessDelegate internalDispatcher);
-
-    /**
      * Destroy the internal state of the ContentView. This method may only be
      * called after the ContentView has been removed from the view system. No
      * other methods may be called on this ContentView after this method has
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ViewEventSink.java b/content/public/android/java/src/org/chromium/content_public/browser/ViewEventSink.java
index 3664740..1dd9350 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/ViewEventSink.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/ViewEventSink.java
@@ -5,6 +5,8 @@
 package org.chromium.content_public.browser;
 
 import android.content.res.Configuration;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
 
 import org.chromium.content.browser.ViewEventSinkImpl;
 
@@ -13,6 +15,37 @@
  */
 public interface ViewEventSink {
     /**
+     * Interface that consumers of WebContents must implement to allow the proper
+     * dispatching of view methods through the containing view.
+     *
+     * <p>
+     * All methods with the "super_" prefix should be routed to the parent of the
+     * implementing container view.
+     */
+    @SuppressWarnings("javadoc")
+    public interface InternalAccessDelegate {
+        /**
+         * @see View#onKeyUp(keyCode, KeyEvent)
+         */
+        boolean super_onKeyUp(int keyCode, KeyEvent event);
+
+        /**
+         * @see View#dispatchKeyEvent(KeyEvent)
+         */
+        boolean super_dispatchKeyEvent(KeyEvent event);
+
+        /**
+         * @see View#onGenericMotionEvent(MotionEvent)
+         */
+        boolean super_onGenericMotionEvent(MotionEvent event);
+
+        /**
+         * @see View#onScrollChanged(int, int, int, int)
+         */
+        void onScrollChanged(int lPix, int tPix, int oldlPix, int oldtPix);
+    }
+
+    /**
      * @return {@link ViewEventSink} instance for a given {@link WebContents}.
      */
     public static ViewEventSink from(WebContents webContents) {
@@ -51,6 +84,13 @@
      */
     void onConfigurationChanged(Configuration newConfig);
 
+    /**
+     * Set the Container view Internals.
+     * @param internalDispatcher Handles dispatching all hidden or super methods to the
+     *                           containerView.
+     */
+    void setAccessDelegate(InternalAccessDelegate internalDispatcher);
+
     void onPauseForTesting();
     void onResumeForTesting();
 }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
index 45dcf83..b3057979 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java
@@ -396,7 +396,7 @@
     void setOverscrollRefreshHandler(OverscrollRefreshHandler handler);
 
     /**
-     * Requests an image snapshot of the content.
+     * Requests an image snapshot of the content and stores it in the specified folder.
      *
      * @param width The width of the resulting bitmap, or 0 for "auto."
      * @param height The height of the resulting bitmap, or 0 for "auto."
@@ -404,7 +404,8 @@
      * @param callback May be called synchronously, or at a later point, to deliver the bitmap
      *                 result (or a failure code).
      */
-    void getContentBitmapAsync(int width, int height, String path, Callback<String> callback);
+    void writeContentBitmapToDiskAsync(
+            int width, int height, String path, Callback<String> callback);
 
     /**
      * Reloads all the Lo-Fi images in this WebContents.
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java
index f18dfd3..bbed8b7 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java
@@ -29,8 +29,9 @@
     private static class TestBrowserStartupController extends BrowserStartupControllerImpl {
         private int mStartupResult;
         private boolean mLibraryLoadSucceeds;
-        private int mInitializedCounter = 0;
-        private boolean mStartupCompleteCalled;
+        private int mServiceManagerLaunchCounter;
+        private int mFullBrowserLaunchCounter;
+        private boolean mServiceManagerStarted;
 
         @Override
         void prepareToStartBrowserProcess(boolean singleProcess, Runnable completionCallback)
@@ -48,28 +49,44 @@
         }
 
         @Override
-        int contentStart() {
-            mInitializedCounter++;
+        int contentMainStart(boolean startServiceManagerOnly) {
+            if (startServiceManagerOnly) {
+                mServiceManagerLaunchCounter++;
+            } else {
+                mFullBrowserLaunchCounter++;
+            }
+            return kickOffStartup(startServiceManagerOnly);
+        }
+
+        @Override
+        void flushStartupTasks() {
+            assert mFullBrowserLaunchCounter > 0;
+            BrowserStartupControllerImpl.browserStartupComplete(mStartupResult);
+        }
+
+        private int kickOffStartup(boolean startServiceManagerOnly) {
             // Post to the UI thread to emulate what would happen in a real scenario.
             ThreadUtils.postOnUiThread(new Runnable() {
                 @Override
                 public void run() {
-                    if (mStartupCompleteCalled) return;
-                    BrowserStartupControllerImpl.browserStartupComplete(mStartupResult);
+                    if (!mServiceManagerStarted) {
+                        BrowserStartupControllerImpl.serviceManagerStartupComplete();
+                        mServiceManagerStarted = true;
+                    }
+                    if (!startServiceManagerOnly) {
+                        BrowserStartupControllerImpl.browserStartupComplete(mStartupResult);
+                    }
                 }
             });
             return mStartupResult;
         }
 
-        @Override
-        void flushStartupTasks() {
-            assert mInitializedCounter > 0;
-            if (mStartupCompleteCalled) return;
-            BrowserStartupControllerImpl.browserStartupComplete(mStartupResult);
+        private int serviceManagerLaunchCounter() {
+            return mServiceManagerLaunchCounter;
         }
 
-        private int initializedCounter() {
-            return mInitializedCounter;
+        private int fullBrowserLaunchCounter() {
+            return mFullBrowserLaunchCounter;
         }
     }
 
@@ -114,15 +131,15 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback);
+                    mController.startBrowserProcessesAsync(true, false, callback);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized one time.", 1,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
 
         // Wait for callbacks to complete.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -145,7 +162,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback1);
+                    mController.startBrowserProcessesAsync(true, false, callback1);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
@@ -155,7 +172,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback2);
+                    mController.startBrowserProcessesAsync(true, false, callback2);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
@@ -168,8 +185,8 @@
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized one time.", 1,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
 
         // Wait for callbacks to complete.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -195,7 +212,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback1);
+                    mController.startBrowserProcessesAsync(true, false, callback1);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
@@ -208,8 +225,8 @@
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized one time.", 1,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
 
         // Wait for callbacks to complete.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -227,7 +244,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback3);
+                    mController.startBrowserProcessesAsync(true, false, callback3);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
@@ -261,15 +278,15 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback);
+                    mController.startBrowserProcessesAsync(true, false, callback);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized one time.", 1,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been lauched once.", 1,
+                mController.fullBrowserLaunchCounter());
 
         // Wait for callbacks to complete.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -291,7 +308,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback1);
+                    mController.startBrowserProcessesAsync(true, false, callback1);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
@@ -304,8 +321,8 @@
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized one time.", 1,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
 
         // Wait for callbacks to complete.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -323,7 +340,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback3);
+                    mController.startBrowserProcessesAsync(true, false, callback3);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
@@ -362,8 +379,8 @@
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized one time.", 1,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
     }
 
     @Test
@@ -378,7 +395,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback);
+                    mController.startBrowserProcessesAsync(true, false, callback);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
@@ -393,8 +410,8 @@
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized twice.", 2,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
 
         Assert.assertTrue("Callback should have been executed.", callback.mHasStartupResult);
         Assert.assertTrue("Callback should have been a success.", callback.mWasSuccess);
@@ -419,23 +436,23 @@
             }
         });
 
-        Assert.assertEquals("The browser process should have been initialized once.", 1,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
 
         // Kick off the asynchronous startup request. This should just queue the callback.
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback);
+                    mController.startBrowserProcessesAsync(true, false, callback);
                 } catch (Exception e) {
                     Assert.fail("Browser should have started successfully");
                 }
             }
         });
 
-        Assert.assertEquals("The browser process should not have been initialized a second time.",
-                1, mController.initializedCounter());
+        Assert.assertEquals("The browser process should not have been launched a second time.", 1,
+                mController.fullBrowserLaunchCounter());
 
         // Wait for callbacks to complete.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -455,7 +472,7 @@
             @Override
             public void run() {
                 try {
-                    mController.startBrowserProcessesAsync(true, callback);
+                    mController.startBrowserProcessesAsync(true, false, callback);
                     Assert.fail("Browser should not have started successfully");
                 } catch (Exception e) {
                     // Exception expected, ignore.
@@ -463,11 +480,320 @@
             }
         });
 
-        Assert.assertEquals("The browser process should not have been initialized.", 0,
-                mController.initializedCounter());
+        Assert.assertEquals("The browser process should not have been launched.", 0,
+                mController.fullBrowserLaunchCounter());
 
         // Wait for callbacks to complete.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
+    @Test
+    @SmallTest
+    public void testAsynchronousStartServiceManagerThenStartFullBrowser() {
+        mController.mStartupResult = BrowserStartupControllerImpl.STARTUP_SUCCESS;
+        mController.mLibraryLoadSucceeds = true;
+        final TestStartupCallback callback1 = new TestStartupCallback();
+        final TestStartupCallback callback2 = new TestStartupCallback();
+
+        // Kick off the asynchronous startup requests to start ServiceManagerOnly.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback1);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // Callback2 will only be run when full browser is started.
+            mController.addStartupCompletedObserver(callback2);
+        });
+
+        Assert.assertEquals("The service manager should have been launched once.", 1,
+                mController.serviceManagerLaunchCounter());
+
+        // Wait for callbacks to complete.
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        Assert.assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
+        Assert.assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
+        Assert.assertFalse("Callback 2 should not be executed.", callback2.mHasStartupResult);
+
+        Assert.assertEquals("The browser process should not have been launched.", 0,
+                mController.fullBrowserLaunchCounter());
+
+        final TestStartupCallback callback3 = new TestStartupCallback();
+        final TestStartupCallback callback4 = new TestStartupCallback();
+
+        // Kick off another asynchronous startup requests to start full browser.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, false, callback3);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> { mController.addStartupCompletedObserver(callback4); });
+
+        // Wait for callbacks to complete.
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
+
+        Assert.assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
+        Assert.assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
+        Assert.assertTrue("Callback 3 should have been executed.", callback3.mHasStartupResult);
+        Assert.assertTrue("Callback 3 should have been a success.", callback3.mWasSuccess);
+        Assert.assertTrue("Callback 4 should have been executed.", callback4.mHasStartupResult);
+        Assert.assertTrue("Callback 4 should have been a success.", callback4.mWasSuccess);
+    }
+
+    @Test
+    @SmallTest
+    public void testMultipleAsynchronousStartServiceManagerRequests() {
+        mController.mStartupResult = BrowserStartupControllerImpl.STARTUP_SUCCESS;
+        mController.mLibraryLoadSucceeds = true;
+        final TestStartupCallback callback1 = new TestStartupCallback();
+        final TestStartupCallback callback2 = new TestStartupCallback();
+        final TestStartupCallback callback3 = new TestStartupCallback();
+
+        // Kick off the asynchronous startup requests.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback1);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback2);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // Callback3 will only be run when full browser is started.
+            mController.addStartupCompletedObserver(callback3);
+        });
+
+        Assert.assertEquals("The service manager should have been launched once.", 1,
+                mController.serviceManagerLaunchCounter());
+
+        // Wait for callbacks to complete.
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        Assert.assertEquals("The browser process should not have been launched.", 0,
+                mController.fullBrowserLaunchCounter());
+
+        Assert.assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
+        Assert.assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
+        Assert.assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
+        Assert.assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
+        Assert.assertFalse("Callback 3 should not be executed.", callback3.mHasStartupResult);
+    }
+
+    @Test
+    @SmallTest
+    public void testConsecutiveAsynchronousStartServiceManagerRequests() {
+        mController.mStartupResult = BrowserStartupControllerImpl.STARTUP_SUCCESS;
+        mController.mLibraryLoadSucceeds = true;
+        final TestStartupCallback callback1 = new TestStartupCallback();
+        final TestStartupCallback callback2 = new TestStartupCallback();
+        final TestStartupCallback callback3 = new TestStartupCallback();
+
+        // Kick off the asynchronous startup requests.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback1);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback2);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // Callback3 will only be run when full browser is started.
+            mController.addStartupCompletedObserver(callback3);
+        });
+
+        Assert.assertEquals("The service manager should have been launched once.", 1,
+                mController.serviceManagerLaunchCounter());
+
+        // Wait for callbacks to complete.
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        Assert.assertEquals("The browser process should not have been launched.", 0,
+                mController.fullBrowserLaunchCounter());
+
+        Assert.assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
+        Assert.assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
+        Assert.assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
+        Assert.assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
+        Assert.assertFalse("Callback 3 should not be executed.", callback3.mHasStartupResult);
+    }
+
+    @Test
+    @SmallTest
+    public void testMultipleAsynchronousStartServiceManagerAndFullBrowserRequests() {
+        mController.mStartupResult = BrowserStartupControllerImpl.STARTUP_SUCCESS;
+        mController.mLibraryLoadSucceeds = true;
+        final TestStartupCallback callback1 = new TestStartupCallback();
+        final TestStartupCallback callback2 = new TestStartupCallback();
+        final TestStartupCallback callback3 = new TestStartupCallback();
+
+        // Kick off the asynchronous startup requests.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback1);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+            try {
+                mController.startBrowserProcessesAsync(true, false, callback2);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // Callback3 will only be run when full browser is started.
+            mController.addStartupCompletedObserver(callback3);
+        });
+
+        Assert.assertEquals("The service manager should have been launched once.", 1,
+                mController.serviceManagerLaunchCounter());
+
+        // Wait for callbacks to complete.
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
+
+        Assert.assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
+        Assert.assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
+        Assert.assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
+        Assert.assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
+        Assert.assertTrue("Callback 3 should have been executed.", callback3.mHasStartupResult);
+        Assert.assertTrue("Callback 3 should have been a success.", callback3.mWasSuccess);
+    }
+
+    @Test
+    @SmallTest
+    public void testAsynchronousStartServiceManagerThenSynchronousStartFullBrowser() {
+        mController.mStartupResult = BrowserStartupControllerImpl.STARTUP_SUCCESS;
+        mController.mLibraryLoadSucceeds = true;
+        final TestStartupCallback callback1 = new TestStartupCallback();
+        final TestStartupCallback callback2 = new TestStartupCallback();
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // Callback2 will only be run when full browser is started.
+            mController.addStartupCompletedObserver(callback2);
+        });
+
+        // Kick off the asynchronous startup requests.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback1);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesSync(false);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        // Wait for callbacks to complete.
+        Assert.assertEquals("The service manager should have been launched once.", 1,
+                mController.serviceManagerLaunchCounter());
+
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
+
+        Assert.assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
+        Assert.assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
+        Assert.assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
+        Assert.assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
+    }
+
+    @Test
+    @SmallTest
+    public void testAsynchronousStartServiceManagerAlongWithSynchronousStartFullBrowser() {
+        mController.mStartupResult = BrowserStartupControllerImpl.STARTUP_SUCCESS;
+        mController.mLibraryLoadSucceeds = true;
+        final TestStartupCallback callback1 = new TestStartupCallback();
+        final TestStartupCallback callback2 = new TestStartupCallback();
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // Callback2 will only be run when full browser is started.
+            mController.addStartupCompletedObserver(callback2);
+        });
+        // Kick off the asynchronous startup requests.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback1);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+
+            try {
+                mController.startBrowserProcessesSync(false);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        // Wait for callbacks to complete.
+        Assert.assertEquals("The service manager should have been launched once.", 1,
+                mController.serviceManagerLaunchCounter());
+
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
+
+        Assert.assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
+        Assert.assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
+        Assert.assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
+        Assert.assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
+    }
+
+    @Test
+    @SmallTest
+    public void testSynchronousStartFullBrowserThenAsynchronousStartServiceManager() {
+        mController.mStartupResult = BrowserStartupControllerImpl.STARTUP_SUCCESS;
+        mController.mLibraryLoadSucceeds = true;
+        final TestStartupCallback callback1 = new TestStartupCallback();
+        final TestStartupCallback callback2 = new TestStartupCallback();
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            // Callback2 will only be run when full browser is started.
+            mController.addStartupCompletedObserver(callback2);
+        });
+        // Kick off the asynchronous startup requests.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            try {
+                mController.startBrowserProcessesSync(false);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+            try {
+                mController.startBrowserProcessesAsync(true, true, callback1);
+            } catch (Exception e) {
+                Assert.fail("Browser should have started successfully");
+            }
+        });
+        // Wait for callbacks to complete.
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        Assert.assertEquals("The service manager should not have been launched.", 0,
+                mController.serviceManagerLaunchCounter());
+
+        Assert.assertEquals("The browser process should have been launched once.", 1,
+                mController.fullBrowserLaunchCounter());
+
+        Assert.assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
+        Assert.assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
+        Assert.assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
+        Assert.assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
+    }
 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
index 577b644..881cc70 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
@@ -23,7 +23,7 @@
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.content.browser.test.util.Criteria;
 import org.chromium.content.browser.test.util.CriteriaHelper;
-import org.chromium.content_public.browser.ContentViewCore.InternalAccessDelegate;
+import org.chromium.content_public.browser.ViewEventSink.InternalAccessDelegate;
 import org.chromium.content_shell_apk.ContentShellActivityTestRule;
 import org.chromium.content_shell_apk.ContentShellActivityTestRule.RerunWithUpdatedContainerView;
 
@@ -334,12 +334,11 @@
     public void testOnScrollChanged() throws Throwable {
         final int scrollToX = mCoordinates.getScrollXPixInt() + 2500;
         final int scrollToY = mCoordinates.getScrollYPixInt() + 2500;
-        final TestInternalAccessDelegate containerViewInternals = new TestInternalAccessDelegate();
+        final TestInternalAccessDelegate accessDelegate = new TestInternalAccessDelegate();
         InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
-                mActivityTestRule.getContentViewCore().setContainerViewInternals(
-                        containerViewInternals);
+                mActivityTestRule.getViewEventSink().setAccessDelegate(accessDelegate);
             }
         });
         scrollTo(scrollToX, scrollToY);
@@ -347,7 +346,7 @@
         CriteriaHelper.pollInstrumentationThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                return containerViewInternals.isScrollChanged();
+                return accessDelegate.isScrollChanged();
             }
         });
     }
diff --git a/content/public/browser/authenticator_request_client_delegate.cc b/content/public/browser/authenticator_request_client_delegate.cc
index d1d877d3..03b08a5a 100644
--- a/content/public/browser/authenticator_request_client_delegate.cc
+++ b/content/public/browser/authenticator_request_client_delegate.cc
@@ -32,10 +32,17 @@
 }
 
 #if defined(OS_MACOSX)
-base::StringPiece
+std::string
 AuthenticatorRequestClientDelegate::TouchIdAuthenticatorKeychainAccessGroup() {
-  static const char* access_group = "not-implemented";
-  return access_group;
+  NOTREACHED();
+  return std::string();
+}
+#endif
+
+#if defined(OS_MACOSX)
+std::string AuthenticatorRequestClientDelegate::TouchIdMetadataSecret() {
+  NOTREACHED();
+  return std::string();
 }
 #endif
 
diff --git a/content/public/browser/authenticator_request_client_delegate.h b/content/public/browser/authenticator_request_client_delegate.h
index 71d9706..f10cb72 100644
--- a/content/public/browser/authenticator_request_client_delegate.h
+++ b/content/public/browser/authenticator_request_client_delegate.h
@@ -9,7 +9,6 @@
 
 #include "base/callback_forward.h"
 #include "base/macros.h"
-#include "base/strings/string_piece_forward.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 
@@ -61,7 +60,15 @@
   // more information on this, refer to |device::fido::TouchIdAuthenticator|.
   // This method may to return empty string or some other placeholder value on
   // platforms where |TouchIdAuthenticator| is not used.
-  virtual base::StringPiece TouchIdAuthenticatorKeychainAccessGroup();
+  virtual std::string TouchIdAuthenticatorKeychainAccessGroup();
+
+  // Returns the secret used to derive key material when encrypting WebAuthn
+  // credential metadata for storage in the macOS keychain. Chrome returns
+  // different secrets for each user profile in order to logically separate
+  // credentials per profile. This method may to return empty string or some
+  // other placeholder value on platforms where |TouchIdAuthenticator| is not
+  // used.
+  virtual std::string TouchIdMetadataSecret();
 #endif
 
  private:
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 8098a6d3..2581636 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -80,6 +80,10 @@
   return url;
 }
 
+bool ContentBrowserClient::ShouldUseMobileFlingCurve() const {
+  return false;
+}
+
 bool ContentBrowserClient::ShouldUseProcessPerSite(
     BrowserContext* browser_context, const GURL& effective_url) {
   return false;
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index e7bf4fb..6319f7004 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -242,6 +242,10 @@
   virtual GURL GetEffectiveURL(BrowserContext* browser_context,
                                const GURL& url);
 
+  // Returns whether gesture fling events should use the mobile-behavior gesture
+  // curve for scrolling.
+  virtual bool ShouldUseMobileFlingCurve() const;
+
   // Returns whether all instances of the specified effective URL should be
   // rendered by the same process, rather than using process-per-site-instance.
   virtual bool ShouldUseProcessPerSite(BrowserContext* browser_context,
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index edd94aa..d6945dc 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -17,6 +17,7 @@
 #include "base/process/kill.h"
 #include "base/strings/string16.h"
 #include "base/supports_user_data.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/invalidate_type.h"
@@ -216,6 +217,12 @@
 
     // Sandboxing flags set on the new WebContents.
     blink::WebSandboxFlags starting_sandbox_flags;
+
+    // Value used to set the last time the WebContents was made active, this is
+    // the value that'll be returned by GetLastActiveTime(). If this is left
+    // default initialized then the value is not passed on to the WebContents
+    // and GetLastActiveTime() will return the WebContents' creation time.
+    base::TimeTicks last_active_time;
   };
 
   // Creates a new WebContents.
@@ -465,7 +472,7 @@
 
   // Indicates whether this tab should be considered crashed. The setter will
   // also notify the delegate when the flag is changed.
-  virtual bool IsCrashed() const  = 0;
+  virtual bool IsCrashed() const = 0;
   virtual void SetIsCrashed(base::TerminationStatus status, int error_code) = 0;
 
   virtual base::TerminationStatus GetCrashedStatus() const = 0;
@@ -486,7 +493,6 @@
   // Get/Set the last time that the WebContents was made active (either when it
   // was created or shown with WasShown()).
   virtual base::TimeTicks GetLastActiveTime() const = 0;
-  virtual void SetLastActiveTime(base::TimeTicks last_active_time) = 0;
 
   // Invoked when the WebContents becomes shown/hidden. A hidden WebContents
   // isn't painted on the screen.
diff --git a/content/public/common/BUILD.gn b/content/public/common/BUILD.gn
index d7dca40..9f590bb 100644
--- a/content/public/common/BUILD.gn
+++ b/content/public/common/BUILD.gn
@@ -245,7 +245,6 @@
     "//content/common",
     "//ipc",
     "//media/capture:capture_base",
-    "//mojo/edk",
     "//mojo/public/cpp/bindings",
     "//net",
     "//services/network:network_service",
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java
index e12e265..488e364 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/mock/MockWebContents.java
@@ -219,7 +219,7 @@
     public void setOverscrollRefreshHandler(OverscrollRefreshHandler handler) {}
 
     @Override
-    public void getContentBitmapAsync(
+    public void writeContentBitmapToDiskAsync(
             int width, int height, String path, Callback<String> callback) {}
 
     @Override
diff --git a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
index 01352ddb..f91e6a34f 100644
--- a/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
+++ b/content/public/test/android/javatests/src/org/chromium/content/browser/test/util/TestContentViewCore.java
@@ -7,7 +7,6 @@
 import android.content.Context;
 
 import org.chromium.content_public.browser.ContentViewCore;
-import org.chromium.content_public.browser.ContentViewCore.InternalAccessDelegate;
 
 /**
  * A dummy {@link ContentViewCore} implementation that can be overriden by tests
@@ -17,8 +16,5 @@
     public TestContentViewCore(Context context, String productVersion) {}
 
     @Override
-    public void setContainerViewInternals(InternalAccessDelegate internalDispatcher) {}
-
-    @Override
     public void destroy() {}
 }
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h
index 8cc9d3d4..f223a3b8 100644
--- a/content/public/test/web_contents_tester.h
+++ b/content/public/test/web_contents_tester.h
@@ -159,6 +159,9 @@
 
   // Sets the return value of GetPageImportanceSignals().
   virtual void SetPageImportanceSignals(PageImportanceSignals signals) = 0;
+
+  // Sets the last active time.
+  virtual void SetLastActiveTime(base::TimeTicks last_active_time) = 0;
 };
 
 }  // namespace content
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
index eb85960..44dac7b 100644
--- a/content/renderer/media/webrtc/media_stream_remote_video_source.cc
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -71,6 +71,7 @@
 
   // Timestamp of the first received frame.
   base::TimeDelta start_timestamp_;
+
   // WebRTC Chromium timestamp diff
   const base::TimeDelta time_diff_;
 };
@@ -117,16 +118,16 @@
   scoped_refptr<media::VideoFrame> video_frame;
   scoped_refptr<webrtc::VideoFrameBuffer> buffer(
       incoming_frame.video_frame_buffer());
+  const gfx::Size size(buffer->width(), buffer->height());
 
-  if (buffer->type() == webrtc::VideoFrameBuffer::Type::kNative) {
-    video_frame = static_cast<WebRtcVideoFrameAdapter*>(buffer.get())
-                      ->getMediaVideoFrame();
-    video_frame->set_timestamp(elapsed_timestamp);
-  } else {
-    const gfx::Size size(buffer->width(), buffer->height());
-    const bool has_alpha =
-        buffer->type() == webrtc::VideoFrameBuffer::Type::kI420A;
-    if (has_alpha) {
+  switch (buffer->type()) {
+    case webrtc::VideoFrameBuffer::Type::kNative: {
+      video_frame = static_cast<WebRtcVideoFrameAdapter*>(buffer.get())
+                        ->getMediaVideoFrame();
+      video_frame->set_timestamp(elapsed_timestamp);
+      break;
+    }
+    case webrtc::VideoFrameBuffer::Type::kI420A: {
       const webrtc::I420ABufferInterface* yuva_buffer = buffer->GetI420A();
       video_frame = media::VideoFrame::WrapExternalYuvaData(
           media::PIXEL_FORMAT_I420A, size, gfx::Rect(size), size,
@@ -136,36 +137,47 @@
           const_cast<uint8_t*>(yuva_buffer->DataU()),
           const_cast<uint8_t*>(yuva_buffer->DataV()),
           const_cast<uint8_t*>(yuva_buffer->DataA()), elapsed_timestamp);
-    } else {
-      scoped_refptr<webrtc::PlanarYuvBuffer> yuv_buffer;
-      media::VideoPixelFormat pixel_format;
-      if (buffer->type() == webrtc::VideoFrameBuffer::Type::kI444) {
-        yuv_buffer = buffer->GetI444();
-        pixel_format = media::PIXEL_FORMAT_I444;
-      } else {
-        yuv_buffer = buffer->ToI420();
-        pixel_format = media::PIXEL_FORMAT_I420;
-      }
-      // Make a shallow copy. Both |frame| and |video_frame| will share a single
-      // reference counted frame buffer. Const cast and hope no one will
-      // overwrite the data.
+      break;
+    }
+    case webrtc::VideoFrameBuffer::Type::kI420: {
+      rtc::scoped_refptr<webrtc::I420BufferInterface> yuv_buffer =
+          buffer->ToI420();
       video_frame = media::VideoFrame::WrapExternalYuvData(
-          pixel_format, size, gfx::Rect(size), size, yuv_buffer->StrideY(),
-          yuv_buffer->StrideU(), yuv_buffer->StrideV(),
+          media::PIXEL_FORMAT_I420, size, gfx::Rect(size), size,
+          yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(),
           const_cast<uint8_t*>(yuv_buffer->DataY()),
           const_cast<uint8_t*>(yuv_buffer->DataU()),
           const_cast<uint8_t*>(yuv_buffer->DataV()), elapsed_timestamp);
+      break;
     }
-    if (!video_frame)
-      return;
-    // The bind ensures that we keep a reference to the underlying buffer.
-    video_frame->AddDestructionObserver(base::BindOnce(&DoNothing, buffer));
+    case webrtc::VideoFrameBuffer::Type::kI444: {
+      webrtc::I444BufferInterface* yuv_buffer = buffer->GetI444();
+      video_frame = media::VideoFrame::WrapExternalYuvData(
+          media::PIXEL_FORMAT_I444, size, gfx::Rect(size), size,
+          yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(),
+          const_cast<uint8_t*>(yuv_buffer->DataY()),
+          const_cast<uint8_t*>(yuv_buffer->DataU()),
+          const_cast<uint8_t*>(yuv_buffer->DataV()), elapsed_timestamp);
+      break;
+    }
+    default:
+      NOTREACHED();
   }
+
+  if (!video_frame)
+    return;
+
+  // The bind ensures that we keep a reference to the underlying buffer.
+  if (buffer->type() != webrtc::VideoFrameBuffer::Type::kNative)
+    video_frame->AddDestructionObserver(base::BindOnce(&DoNothing, buffer));
+
+  // Rotation may be explicitly set sometimes.
   if (incoming_frame.rotation() != webrtc::kVideoRotation_0) {
     video_frame->metadata()->SetRotation(
         media::VideoFrameMetadata::ROTATION,
         WebRTCToMediaVideoRotation(incoming_frame.rotation()));
   }
+
   // Run render smoothness algorithm only when we don't have to render
   // immediately.
   if (!render_immediately) {
@@ -235,7 +247,7 @@
 }
 
 rtc::VideoSinkInterface<webrtc::VideoFrame>*
-MediaStreamRemoteVideoSource::SinkInterfaceForTest() {
+MediaStreamRemoteVideoSource::SinkInterfaceForTesting() {
   return delegate_.get();
 }
 
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source.h b/content/renderer/media/webrtc/media_stream_remote_video_source.h
index 494b11b..f07b411 100644
--- a/content/renderer/media/webrtc/media_stream_remote_video_source.h
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source.h
@@ -24,7 +24,7 @@
 // to make sure there is no difference between a video track where the source is
 // a local source and a video track where the source is a remote video track.
 class CONTENT_EXPORT MediaStreamRemoteVideoSource
-     : public MediaStreamVideoSource {
+    : public MediaStreamVideoSource {
  public:
   explicit MediaStreamRemoteVideoSource(
       std::unique_ptr<TrackObserver> observer);
@@ -44,7 +44,7 @@
 
   // Used by tests to test that a frame can be received and that the
   // MediaStreamRemoteVideoSource behaves as expected.
-  rtc::VideoSinkInterface<webrtc::VideoFrame>* SinkInterfaceForTest();
+  rtc::VideoSinkInterface<webrtc::VideoFrame>* SinkInterfaceForTesting();
 
  private:
   void OnChanged(webrtc::MediaStreamTrackInterface::TrackState state);
diff --git a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
index 34db57b..e721651 100644
--- a/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ b/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -36,7 +36,7 @@
   explicit MediaStreamRemoteVideoSourceUnderTest(
       std::unique_ptr<TrackObserver> observer)
       : MediaStreamRemoteVideoSource(std::move(observer)) {}
-  using MediaStreamRemoteVideoSource::SinkInterfaceForTest;
+  using MediaStreamRemoteVideoSource::SinkInterfaceForTesting;
 };
 
 class MediaStreamRemoteVideoSourceTest
@@ -171,7 +171,7 @@
 
   webrtc::I420Buffer::SetBlack(buffer);
 
-  source()->SinkInterfaceForTest()->OnFrame(
+  source()->SinkInterfaceForTesting()->OnFrame(
       webrtc::VideoFrame(buffer, webrtc::kVideoRotation_0, 1000));
   run_loop.Run();
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 749d935..b81daf2 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -4338,7 +4338,10 @@
     return;
   RecordSuffixedRendererMemoryMetrics(memory_metrics,
                                       ".MainFrameDidFinishLoad");
-  if (!IsControlledByServiceWorker())
+  // TODO(falken): Filter out no fetch controllers. This UMA probably didn't
+  // intend to log them.
+  if (IsControlledByServiceWorker() ==
+      blink::mojom::ControllerServiceWorkerMode::kNoController)
     return;
   RecordSuffixedRendererMemoryMetrics(
       memory_metrics, ".ServiceWorkerControlledMainFrameDidFinishLoad");
@@ -7182,11 +7185,12 @@
          base::FeatureList::IsEnabled(kConsumeGestureOnNavigation);
 }
 
-bool RenderFrameImpl::IsControlledByServiceWorker() {
+blink::mojom::ControllerServiceWorkerMode
+RenderFrameImpl::IsControlledByServiceWorker() {
   blink::WebServiceWorkerNetworkProvider* web_provider =
       frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider();
   if (!web_provider)
-    return false;
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
   ServiceWorkerNetworkProvider* provider =
       ServiceWorkerNetworkProvider::FromWebServiceWorkerNetworkProvider(
           web_provider);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 64606449..542343e 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -73,6 +73,7 @@
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
 #include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
 #include "third_party/blink/public/platform/autoplay.mojom.h"
 #include "third_party/blink/public/platform/site_engagement.mojom.h"
 #include "third_party/blink/public/platform/web_effective_connection_type.h"
@@ -1245,8 +1246,8 @@
   // Whether or not a navigation in this frame consumes user gestures.
   bool ConsumeGestureOnNavigation() const;
 
-  // Whether or not the frame is controlled by a service worker.
-  bool IsControlledByServiceWorker();
+  // Whether the frame is controlled by a service worker.
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker();
 
   // Build DidCommitProvisionalLoad_Params based on the frame internal state.
   std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index 156ec21..3d75091 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -95,8 +95,9 @@
   request.SetExtraData(std::move(extra_data));
 }
 
-bool ServiceWorkerFetchContextImpl::IsControlledByServiceWorker() const {
-  return false;
+blink::mojom::ControllerServiceWorkerMode
+ServiceWorkerFetchContextImpl::IsControlledByServiceWorker() const {
+  return blink::mojom::ControllerServiceWorkerMode::kNoController;
 }
 
 blink::WebURL ServiceWorkerFetchContextImpl::SiteForCookies() const {
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h
index 42573eb..d5129ea 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -44,7 +44,8 @@
   std::unique_ptr<blink::WebURLLoaderFactory> CreateScriptLoaderFactory()
       override;
   void WillSendRequest(blink::WebURLRequest&) override;
-  bool IsControlledByServiceWorker() const override;
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+      const override;
   blink::WebURL SiteForCookies() const override;
   std::unique_ptr<blink::WebSocketHandshakeThrottle>
   CreateWebSocketHandshakeThrottle() override;
diff --git a/content/renderer/service_worker/service_worker_network_provider.cc b/content/renderer/service_worker/service_worker_network_provider.cc
index 7b64c47..be05b89 100644
--- a/content/renderer/service_worker/service_worker_network_provider.cc
+++ b/content/renderer/service_worker/service_worker_network_provider.cc
@@ -74,14 +74,16 @@
             network::mojom::RequestContextFrameType::kTopLevel &&
         request.GetFrameType() !=
             network::mojom::RequestContextFrameType::kNested &&
-        !provider_->IsControlledByServiceWorker()) {
+        provider_->IsControlledByServiceWorker() ==
+            blink::mojom::ControllerServiceWorkerMode::kNoController) {
       request.SetSkipServiceWorker(true);
     }
   }
 
   int ProviderID() const override { return provider_->provider_id(); }
 
-  bool HasControllerServiceWorker() override {
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+      override {
     return provider_->IsControlledByServiceWorker();
   }
 
@@ -251,9 +253,11 @@
   return context()->provider_id();
 }
 
-bool ServiceWorkerNetworkProvider::IsControlledByServiceWorker() const {
-  return context() && context()->GetControllerVersionId() !=
-                          blink::mojom::kInvalidServiceWorkerVersionId;
+blink::mojom::ControllerServiceWorkerMode
+ServiceWorkerNetworkProvider::IsControlledByServiceWorker() const {
+  if (!context())
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  return context()->IsControlledByServiceWorker();
 }
 
 // Creates an invalid instance (provider_id() returns
diff --git a/content/renderer/service_worker/service_worker_network_provider.h b/content/renderer/service_worker/service_worker_network_provider.h
index 120b71c..902ce40 100644
--- a/content/renderer/service_worker/service_worker_network_provider.h
+++ b/content/renderer/service_worker/service_worker_network_provider.h
@@ -103,7 +103,9 @@
     return script_loader_factory_.get();
   }
 
-  bool IsControlledByServiceWorker() const;
+  // Returns whether the context this provider is for is controlled by a service
+  // worker. Can be called only for providers for service worker clients.
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const;
 
  private:
   // Creates an invalid instance (provider_id() returns
diff --git a/content/renderer/service_worker/service_worker_provider_context.cc b/content/renderer/service_worker/service_worker_provider_context.cc
index 017d8781..efb3de6 100644
--- a/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/content/renderer/service_worker/service_worker_provider_context.cc
@@ -57,10 +57,8 @@
   // The Client#id value of the client.
   std::string client_id;
 
-  // S13nServiceWorker:
-  // True when the controller has a fetch event handler. If false,
-  // ServiceWorkerSubresourceLoader will be bypassed.
-  bool controller_has_fetch_event_handler = false;
+  blink::mojom::ControllerServiceWorkerMode controller_mode =
+      blink::mojom::ControllerServiceWorkerMode::kNoController;
 
   // Tracks feature usage for UseCounter.
   std::set<blink::mojom::WebFeature> used_features;
@@ -144,14 +142,24 @@
   return std::move(state_for_client_->controller);
 }
 
-int64_t ServiceWorkerProviderContext::GetControllerVersionId() {
+int64_t ServiceWorkerProviderContext::GetControllerVersionId() const {
   DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
   DCHECK(state_for_client_);
   return state_for_client_->controller_version_id;
 }
 
+blink::mojom::ControllerServiceWorkerMode
+ServiceWorkerProviderContext::IsControlledByServiceWorker() const {
+  DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(state_for_client_);
+  return state_for_client_->controller_mode;
+}
+
 network::mojom::URLLoaderFactory*
 ServiceWorkerProviderContext::GetSubresourceLoaderFactory() {
+  if (!ServiceWorkerUtils::IsServicificationEnabled())
+    return nullptr;
+
   DCHECK(state_for_client_);
   auto* state = state_for_client_.get();
   if (!state->controller_connector ||
@@ -160,9 +168,13 @@
     // No controller is attached.
     return nullptr;
   }
-  if (!state->controller_has_fetch_event_handler)
+
+  if (state->controller_mode !=
+      blink::mojom::ControllerServiceWorkerMode::kControlled) {
+    // The controller does not exist or has no fetch event handler.
     return nullptr;
-  DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
+  }
+
   if (!state->subresource_loader_factory) {
     ServiceWorkerSubresourceLoaderFactory::Create(
         state->controller_connector, state->fallback_loader_factory,
@@ -292,8 +304,14 @@
   DCHECK(state->client_id.empty() ||
          state->client_id == controller_info->client_id);
   state->client_id = controller_info->client_id;
-  // |endpoint| is set only when the controller has a fetch event handler.
-  state->controller_has_fetch_event_handler = !!controller_info->endpoint;
+
+  DCHECK((controller_info->mode ==
+              blink::mojom::ControllerServiceWorkerMode::kNoController &&
+          !state->controller) ||
+         (controller_info->mode !=
+              blink::mojom::ControllerServiceWorkerMode::kNoController &&
+          state->controller));
+  state->controller_mode = controller_info->mode;
 
   // Propagate the controller to workers related to this provider.
   if (state->controller) {
@@ -302,7 +320,7 @@
     for (const auto& worker : state->worker_clients) {
       // This is a Mojo interface call to the (dedicated or shared) worker
       // thread.
-      worker->OnControllerChanged();
+      worker->OnControllerChanged(state->controller_mode);
     }
   }
   for (blink::mojom::WebFeature feature : used_features)
diff --git a/content/renderer/service_worker/service_worker_provider_context.h b/content/renderer/service_worker/service_worker_provider_context.h
index 19fec077..bc566e20 100644
--- a/content/renderer/service_worker/service_worker_provider_context.h
+++ b/content/renderer/service_worker/service_worker_provider_context.h
@@ -108,7 +108,9 @@
 
   // For service worker clients. Returns version id of the controller service
   // worker object (ServiceWorkerContainer#controller).
-  int64_t GetControllerVersionId();
+  int64_t GetControllerVersionId() const;
+
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const;
 
   // For service worker clients. Takes the controller service worker object info
   // set by SetController() if any, otherwise returns nullptr.
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
index 61e3b0d..5b96245 100644
--- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc
+++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -329,6 +329,7 @@
         nullptr /* controller_info */, nullptr /* loader_factory*/);
 
     auto info = mojom::ControllerServiceWorkerInfo::New();
+    info->mode = blink::mojom::ControllerServiceWorkerMode::kControlled;
     info->object_info = std::move(object_info);
     container_ptr->SetController(std::move(info),
                                  std::vector<blink::mojom::WebFeature>(), true);
@@ -373,6 +374,7 @@
     ASSERT_FALSE(client->was_set_controller_called());
 
     auto info = mojom::ControllerServiceWorkerInfo::New();
+    info->mode = blink::mojom::ControllerServiceWorkerMode::kControlled;
     info->object_info = std::move(object_info);
     container_ptr->SetController(std::move(info),
                                  std::vector<blink::mojom::WebFeature>(), true);
@@ -430,6 +432,8 @@
   auto controller_info1 = mojom::ControllerServiceWorkerInfo::New();
   mojom::ControllerServiceWorkerPtr controller_ptr1;
   fake_controller1.Clone(mojo::MakeRequest(&controller_ptr1));
+  controller_info1->mode =
+      blink::mojom::ControllerServiceWorkerMode::kControlled;
   controller_info1->object_info = std::move(object_info1);
   controller_info1->endpoint = controller_ptr1.PassInterface();
 
@@ -465,6 +469,8 @@
   auto controller_info2 = mojom::ControllerServiceWorkerInfo::New();
   mojom::ControllerServiceWorkerPtr controller_ptr2;
   fake_controller2.Clone(mojo::MakeRequest(&controller_ptr2));
+  controller_info2->mode =
+      blink::mojom::ControllerServiceWorkerMode::kControlled;
   controller_info2->object_info = std::move(object_info2);
   controller_info2->endpoint = controller_ptr2.PassInterface();
   container_ptr->SetController(std::move(controller_info2),
@@ -526,6 +532,8 @@
   auto controller_info4 = mojom::ControllerServiceWorkerInfo::New();
   mojom::ControllerServiceWorkerPtr controller_ptr4;
   fake_controller4.Clone(mojo::MakeRequest(&controller_ptr4));
+  controller_info4->mode =
+      blink::mojom::ControllerServiceWorkerMode::kControlled;
   controller_info4->object_info = std::move(object_info4);
   controller_info4->endpoint = controller_ptr4.PassInterface();
   container_ptr->SetController(std::move(controller_info4),
@@ -562,6 +570,8 @@
       object_host->CreateObjectInfo();
   auto controller_info = mojom::ControllerServiceWorkerInfo::New();
   mojom::ControllerServiceWorkerPtr controller_ptr;
+  controller_info->mode =
+      blink::mojom::ControllerServiceWorkerMode::kNoFetchEventHandler;
   controller_info->object_info = std::move(object_info);
 
   mojom::ServiceWorkerContainerAssociatedPtr container_ptr;
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.cc b/content/renderer/service_worker/worker_fetch_context_impl.cc
index 0c6778eec..da6ba12 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/worker_fetch_context_impl.cc
@@ -249,7 +249,8 @@
   request.SetExtraData(std::move(extra_data));
   request.SetAppCacheHostID(appcache_host_id_);
 
-  if (!IsControlledByServiceWorker()) {
+  if (IsControlledByServiceWorker() ==
+      blink::mojom::ControllerServiceWorkerMode::kNoController) {
     // TODO(falken): Is still this needed? It used to set kForeign for foreign
     // fetch.
     request.SetSkipServiceWorker(true);
@@ -259,7 +260,8 @@
     request.SetURL(g_rewrite_url(request.Url().GetString().Utf8(), false));
 }
 
-bool WorkerFetchContextImpl::IsControlledByServiceWorker() const {
+blink::mojom::ControllerServiceWorkerMode
+WorkerFetchContextImpl::IsControlledByServiceWorker() const {
   return is_controlled_by_service_worker_;
 }
 
@@ -316,8 +318,9 @@
   service_worker_provider_id_ = id;
 }
 
-void WorkerFetchContextImpl::set_is_controlled_by_service_worker(bool flag) {
-  is_controlled_by_service_worker_ = flag;
+void WorkerFetchContextImpl::set_is_controlled_by_service_worker(
+    blink::mojom::ControllerServiceWorkerMode mode) {
+  is_controlled_by_service_worker_ = mode;
 }
 
 void WorkerFetchContextImpl::set_parent_frame_id(int id) {
@@ -349,10 +352,9 @@
   return appcache_host_id_;
 }
 
-void WorkerFetchContextImpl::OnControllerChanged() {
-  // This function is called if we transition from (no controller) to
-  // (controller), or if the controller changed.
-  set_is_controlled_by_service_worker(true);
+void WorkerFetchContextImpl::OnControllerChanged(
+    blink::mojom::ControllerServiceWorkerMode mode) {
+  set_is_controlled_by_service_worker(mode);
 
   if (ServiceWorkerUtils::IsServicificationEnabled())
     ResetServiceWorkerURLLoaderFactory();
@@ -366,7 +368,8 @@
   DCHECK(ServiceWorkerUtils::IsServicificationEnabled());
   if (!web_loader_factory_)
     return;
-  if (!IsControlledByServiceWorker()) {
+  if (IsControlledByServiceWorker() ==
+      blink::mojom::ControllerServiceWorkerMode::kNoController) {
     web_loader_factory_->SetServiceWorkerURLLoaderFactory(nullptr);
     return;
   }
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.h b/content/renderer/service_worker/worker_fetch_context_impl.h
index 89b3222..8857872 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/worker_fetch_context_impl.h
@@ -75,7 +75,8 @@
   std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory(
       mojo::ScopedMessagePipeHandle url_loader_factory_handle) override;
   void WillSendRequest(blink::WebURLRequest&) override;
-  bool IsControlledByServiceWorker() const override;
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+      const override;
   void SetIsOnSubframe(bool) override;
   bool IsOnSubframe() const override;
   blink::WebURL SiteForCookies() const override;
@@ -93,12 +94,13 @@
   CreateWebSocketHandshakeThrottle() override;
 
   // mojom::ServiceWorkerWorkerClient implementation:
-  void OnControllerChanged() override;
+  void OnControllerChanged(blink::mojom::ControllerServiceWorkerMode) override;
 
   // Sets the fetch context status copied from the frame; the parent frame for a
   // dedicated worker, the main frame of the shadow page for a shared worker.
   void set_service_worker_provider_id(int id);
-  void set_is_controlled_by_service_worker(bool flag);
+  void set_is_controlled_by_service_worker(
+      blink::mojom::ControllerServiceWorkerMode mode);
   void set_parent_frame_id(int id);
   void set_site_for_cookies(const blink::WebURL& site_for_cookies);
   // Sets whether the worker context is a secure context.
@@ -134,7 +136,9 @@
   std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info_;
 
   int service_worker_provider_id_ = kInvalidServiceWorkerProviderId;
-  bool is_controlled_by_service_worker_ = false;
+  blink::mojom::ControllerServiceWorkerMode is_controlled_by_service_worker_ =
+      blink::mojom::ControllerServiceWorkerMode::kNoController;
+
   // S13nServiceWorker:
   // Initialized on the worker thread when InitializeOnWorkerThread() is called.
   mojom::ServiceWorkerContainerHostPtr service_worker_container_host_;
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 7bc2aac2..88aef23 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -103,14 +103,16 @@
     // request and break the assumptions of the renderer.
     if (request.GetRequestContext() !=
             blink::WebURLRequest::kRequestContextSharedWorker &&
-        !provider_->IsControlledByServiceWorker()) {
+        provider_->IsControlledByServiceWorker() ==
+            blink::mojom::ControllerServiceWorkerMode::kNoController) {
       request.SetSkipServiceWorker(true);
     }
   }
 
   int ProviderID() const override { return provider_->provider_id(); }
 
-  bool HasControllerServiceWorker() override {
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+      override {
     return provider_->IsControlledByServiceWorker();
   }
 
@@ -396,13 +398,11 @@
   // https://w3c.github.io/webappsec-secure-contexts/#examples-shared-workers
   worker_fetch_context->set_is_secure_context(IsOriginSecure(url_));
   worker_fetch_context->set_origin_url(url_.GetOrigin());
-  if (web_network_provider) {
-    worker_fetch_context->set_service_worker_provider_id(
-        web_network_provider->ProviderID());
-    worker_fetch_context->set_is_controlled_by_service_worker(
-        web_network_provider->HasControllerServiceWorker());
-  }
+  worker_fetch_context->set_service_worker_provider_id(context->provider_id());
+  worker_fetch_context->set_is_controlled_by_service_worker(
+      context->IsControlledByServiceWorker());
   worker_fetch_context->set_client_id(context->client_id());
+
   return std::move(worker_fetch_context);
 }
 
diff --git a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellActivityTestRule.java b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellActivityTestRule.java
index 9584c55a..ca7dc7f 100644
--- a/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellActivityTestRule.java
+++ b/content/shell/android/javatests/src/org/chromium/content_shell_apk/ContentShellActivityTestRule.java
@@ -33,6 +33,7 @@
 import org.chromium.content_public.browser.JavascriptInjector;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.NavigationController;
+import org.chromium.content_public.browser.ViewEventSink;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_shell.Shell;
 import org.chromium.content_shell.ShellViewAndroidDelegate.OnCursorUpdateHelper;
@@ -144,6 +145,19 @@
     }
 
     /**
+     * Returns the current {@link ViewEventSink} or null if there is none;
+     */
+    public ViewEventSink getViewEventSink() {
+        try {
+            return ThreadUtils.runOnUiThreadBlocking(() -> {
+                return ViewEventSink.from(getActivity().getActiveShell().getWebContents());
+            });
+        } catch (ExecutionException e) {
+            return null;
+        }
+    }
+
+    /**
      * Returns the WebContents of this Shell.
      */
     public WebContents getWebContents() {
diff --git a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
index 896bd7c..cfc937d 100644
--- a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
+++ b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
@@ -110,7 +110,7 @@
         try {
             BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
                     .startBrowserProcessesAsync(
-                            true, new BrowserStartupController.StartupCallback() {
+                            true, false, new BrowserStartupController.StartupCallback() {
                                 @Override
                                 public void onSuccess() {
                                     finishInitialization(savedInstanceState);
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
index a0ac197..8baed72 100644
--- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
+++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
@@ -95,7 +95,7 @@
             try {
                 BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
                         .startBrowserProcessesAsync(
-                                true, new BrowserStartupController.StartupCallback() {
+                                true, false, new BrowserStartupController.StartupCallback() {
                                     @Override
                                     public void onSuccess() {
                                         finishInitialization(savedInstanceState);
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index 9904c75..a2aab2f 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -333,7 +333,7 @@
     # Mark ANGLE's OpenGL as flaky on Windows Amd
     self.Flaky('conformance/*', ['win', 'amd', 'opengl'], bug=582083)
 
-    # Win / OpenGL / Intel HD 530 failures
+    # Win / OpenGL / Intel HD 530 / 630 failures
     self.Fail('conformance/canvas/draw-webgl-to-canvas-test.html',
         ['win10', 'intel', 'opengl'], bug=680797)
     self.Fail('conformance/extensions/angle-instanced-arrays.html',
@@ -358,6 +358,8 @@
         ['win10', 'intel', 'opengl'], bug=680797)
     self.Fail('conformance/glsl/matrices/matrix-compound-multiply.html',
         ['win10', 'intel', 'opengl'], bug=680797)
+    self.Flaky('conformance/glsl/variables/gl-pointcoord.html',
+        ['win10', 'intel', 'opengl'], bug=854100)
     self.Fail('conformance/more/conformance/webGLArrays.html',
         ['win10', 'intel', 'opengl'], bug=680797)
     self.Fail('conformance/ogles/GL/struct/struct_049_to_056.html',
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 5beda77..26bcf23 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -451,4 +451,8 @@
   page_importance_signals_ = signals;
 }
 
+void TestWebContents::SetLastActiveTime(base::TimeTicks last_active_time) {
+  last_active_time_ = last_active_time;
+}
+
 }  // namespace content
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 6549f0fb..63f9033 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -152,6 +152,8 @@
 
   void SetPageImportanceSignals(PageImportanceSignals signals) override;
 
+  void SetLastActiveTime(base::TimeTicks last_active_time) override;
+
  protected:
   // The deprecated WebContentsTester still needs to subclass this.
   explicit TestWebContents(BrowserContext* browser_context);
diff --git a/device/fido/mac/authenticator.h b/device/fido/mac/authenticator.h
index 04e1c33..f4bd756 100644
--- a/device/fido/mac/authenticator.h
+++ b/device/fido/mac/authenticator.h
@@ -26,7 +26,8 @@
   // CreateIfAvailable returns a TouchIdAuthenticator if IsAvailable() returns
   // true and nullptr otherwise.
   static std::unique_ptr<TouchIdAuthenticator> CreateIfAvailable(
-      base::StringPiece keychain_access_group);
+      std::string keychain_access_group,
+      std::string metadata_secret);
 
   ~TouchIdAuthenticator() override;
 
@@ -42,12 +43,8 @@
   std::string GetId() const override;
 
  private:
-  TouchIdAuthenticator(base::StringPiece keychain_access_group);
-
-  // The profile ID identifies the user profile from which the request
-  // originates. It is used to scope credentials to the profile under which they
-  // were created.
-  base::StringPiece GetOrInitializeProfileId();
+  TouchIdAuthenticator(std::string keychain_access_group,
+                       std::string metadata_secret);
 
   // The keychain access group under which credentials are stored in the macOS
   // keychain for access control. The set of all access groups that the
@@ -56,6 +53,8 @@
   // https://developer.apple.com/documentation/security/ksecattraccessgroup?language=objc.
   std::string keychain_access_group_;
 
+  std::string metadata_secret_;
+
   std::unique_ptr<Operation> operation_;
 
  private:
diff --git a/device/fido/mac/authenticator.mm b/device/fido/mac/authenticator.mm
index 704808f..b818a556 100644
--- a/device/fido/mac/authenticator.mm
+++ b/device/fido/mac/authenticator.mm
@@ -34,10 +34,12 @@
 
 // static
 std::unique_ptr<TouchIdAuthenticator> TouchIdAuthenticator::CreateIfAvailable(
-    base::StringPiece keychain_access_group) {
-  return IsAvailable()
-             ? base::WrapUnique(new TouchIdAuthenticator(keychain_access_group))
-             : nullptr;
+    std::string keychain_access_group,
+    std::string metadata_secret) {
+  return IsAvailable() ? base::WrapUnique(new TouchIdAuthenticator(
+                             std::move(keychain_access_group),
+                             std::move(metadata_secret)))
+                       : nullptr;
 }
 
 TouchIdAuthenticator::~TouchIdAuthenticator() = default;
@@ -48,8 +50,8 @@
     MakeCredentialCallback callback) {
   DCHECK(!operation_);
   operation_ = std::make_unique<MakeCredentialOperation>(
-      std::move(request), GetOrInitializeProfileId().as_string(),
-      keychain_access_group_, std::move(callback));
+      std::move(request), metadata_secret_, keychain_access_group_,
+      std::move(callback));
   operation_->Run();
 }
 
@@ -57,8 +59,8 @@
                                         GetAssertionCallback callback) {
   DCHECK(!operation_);
   operation_ = std::make_unique<GetAssertionOperation>(
-      std::move(request), GetOrInitializeProfileId().as_string(),
-      keychain_access_group_, std::move(callback));
+      std::move(request), metadata_secret_, keychain_access_group_,
+      std::move(callback));
   operation_->Run();
 }
 
@@ -74,14 +76,10 @@
   return "TouchIdAuthenticator";
 }
 
-TouchIdAuthenticator::TouchIdAuthenticator(
-    base::StringPiece keychain_access_group)
-    : keychain_access_group_(keychain_access_group.as_string()) {}
-
-base::StringPiece TouchIdAuthenticator::GetOrInitializeProfileId() {
-  // TODO(martinkr): Implement.
-  return "12345678901234567890123456789012";
-}
+TouchIdAuthenticator::TouchIdAuthenticator(std::string keychain_access_group,
+                                           std::string metadata_secret)
+    : keychain_access_group_(std::move(keychain_access_group)),
+      metadata_secret_(std::move(metadata_secret)) {}
 
 }  // namespace mac
 }  // namespace fido
diff --git a/device/fido/mac/credential_metadata.cc b/device/fido/mac/credential_metadata.cc
index 6c987e8..dbc5683 100644
--- a/device/fido/mac/credential_metadata.cc
+++ b/device/fido/mac/credential_metadata.cc
@@ -10,6 +10,7 @@
 #include "components/cbor/cbor_reader.h"
 #include "components/cbor/cbor_values.h"
 #include "components/cbor/cbor_writer.h"
+#include "device/fido/public_key_credential_user_entity.h"
 #include "third_party/boringssl/src/include/openssl/digest.h"
 #include "third_party/boringssl/src/include/openssl/hkdf.h"
 #include "third_party/boringssl/src/include/openssl/rand.h"
@@ -45,10 +46,41 @@
 
 }  // namespace
 
-CredentialMetadata::CredentialMetadata(const std::string& profile_id)
-    : profile_id_(profile_id) {}
+// static
+std::string CredentialMetadata::GenerateRandomSecret() {
+  static constexpr size_t kSecretSize = 32u;
+  std::string secret;
+  RAND_bytes(
+      reinterpret_cast<uint8_t*>(base::WriteInto(&secret, kSecretSize + 1)),
+      kSecretSize);
+  return secret;
+}
+
+CredentialMetadata::CredentialMetadata(const std::string& secret)
+    : secret_(secret) {}
 CredentialMetadata::~CredentialMetadata() = default;
 
+// static
+CredentialMetadata::UserEntity
+CredentialMetadata::UserEntity::FromPublicKeyCredentialUserEntity(
+    const PublicKeyCredentialUserEntity& user) {
+  return CredentialMetadata::UserEntity(user.user_id(),
+                                        user.user_name().value_or(""),
+                                        user.user_display_name().value_or(""));
+}
+
+PublicKeyCredentialUserEntity
+CredentialMetadata::UserEntity::ToPublicKeyCredentialUserEntity() {
+  auto user_entity = PublicKeyCredentialUserEntity(id);
+  if (!name.empty()) {
+    user_entity.SetUserName(name);
+  }
+  if (!display_name.empty()) {
+    user_entity.SetDisplayName(display_name);
+  }
+  return user_entity;
+}
+
 CredentialMetadata::UserEntity::UserEntity(std::vector<uint8_t> id_,
                                            std::string name_,
                                            std::string display_name_)
@@ -67,10 +99,10 @@
 
 // static
 base::Optional<std::vector<uint8_t>> CredentialMetadata::SealCredentialId(
-    const std::string& profile_id,
+    const std::string& secret,
     const std::string& rp_id,
     const UserEntity& user) {
-  CredentialMetadata cryptor(profile_id);
+  CredentialMetadata cryptor(secret);
 
   // The first 13 bytes are the version and nonce.
   std::vector<uint8_t> result(1 + kNonceLength);
@@ -108,10 +140,10 @@
 // static
 base::Optional<CredentialMetadata::UserEntity>
 CredentialMetadata::UnsealCredentialId(
-    const std::string& profile_id,
+    const std::string& secret,
     const std::string& rp_id,
     base::span<const uint8_t> credential_id) {
-  CredentialMetadata cryptor(profile_id);
+  CredentialMetadata cryptor(secret);
 
   // Recover the nonce and check for the correct version byte. Then try to
   // decrypt the remaining bytes.
@@ -145,22 +177,21 @@
 
 // static
 base::Optional<std::string> CredentialMetadata::EncodeRpIdAndUserId(
-    const std::string& profile_id,
+    const std::string& secret,
     const std::string& rp_id,
     base::span<const uint8_t> user_id) {
   // Encoding RP ID along with the user ID hides whether the same user ID was
   // reused on different RPs.
   const auto* user_id_data = reinterpret_cast<const char*>(user_id.data());
-  return CredentialMetadata(profile_id)
-      .HmacForStorage(rp_id + "/" +
-                      std::string(user_id_data, user_id_data + user_id.size()));
+  return CredentialMetadata(secret).HmacForStorage(
+      rp_id + "/" + std::string(user_id_data, user_id_data + user_id.size()));
 }
 
 // static
 base::Optional<std::string> CredentialMetadata::EncodeRpId(
-    const std::string& profile_id,
+    const std::string& secret,
     const std::string& rp_id) {
-  return CredentialMetadata(profile_id).HmacForStorage(rp_id);
+  return CredentialMetadata(secret).HmacForStorage(rp_id);
 }
 
 // static
@@ -172,7 +203,7 @@
     base::span<const uint8_t> nonce,
     base::span<const uint8_t> plaintext,
     base::StringPiece authenticated_data) const {
-  const std::string key = DeriveKey(profile_id_, Algorithm::kAes256Gcm);
+  const std::string key = DeriveKey(secret_, Algorithm::kAes256Gcm);
   crypto::Aead aead(crypto::Aead::AES_256_GCM);
   aead.Init(&key);
   std::string ciphertext;
@@ -191,7 +222,7 @@
     base::span<const uint8_t> nonce,
     base::span<const uint8_t> ciphertext,
     base::StringPiece authenticated_data) const {
-  const std::string key = DeriveKey(profile_id_, Algorithm::kAes256Gcm);
+  const std::string key = DeriveKey(secret_, Algorithm::kAes256Gcm);
   crypto::Aead aead(crypto::Aead::AES_256_GCM);
   aead.Init(&key);
   std::string plaintext;
@@ -209,7 +240,7 @@
 base::Optional<std::string> CredentialMetadata::HmacForStorage(
     base::StringPiece data) const {
   crypto::HMAC hmac(crypto::HMAC::SHA256);
-  const std::string key = DeriveKey(profile_id_, Algorithm::kHmacSha256);
+  const std::string key = DeriveKey(secret_, Algorithm::kHmacSha256);
   std::vector<uint8_t> digest(hmac.DigestLength());
   if (!hmac.Init(key) || !hmac.Sign(data, digest.data(), hmac.DigestLength())) {
     return base::nullopt;
diff --git a/device/fido/mac/credential_metadata.h b/device/fido/mac/credential_metadata.h
index 48e7860..4e23c70 100644
--- a/device/fido/mac/credential_metadata.h
+++ b/device/fido/mac/credential_metadata.h
@@ -19,6 +19,9 @@
 #include "crypto/symmetric_key.h"
 
 namespace device {
+
+class PublicKeyCredentialUserEntity;
+
 namespace fido {
 namespace mac {
 
@@ -43,11 +46,18 @@
 // TODO(martinkr): We currently do not store profile icon URLs.
 class COMPONENT_EXPORT(DEVICE_FIDO) CredentialMetadata {
  public:
+  // Generate a new random secret to use with the public interface of
+  // CredentialMetadata. Chrome stores this secret in the Profile Prefs.
+  static std::string GenerateRandomSecret();
+
   // UserEntity loosely corresponds to a PublicKeyCredentialUserEntity
   // (https://www.w3.org/TR/webauthn/#sctn-user-credential-params). Values of
   // this type should be moved whenever possible.
   struct UserEntity {
    public:
+    static UserEntity FromPublicKeyCredentialUserEntity(
+        const PublicKeyCredentialUserEntity&);
+
     UserEntity(std::vector<uint8_t> id_,
                std::string name_,
                std::string display_);
@@ -56,6 +66,8 @@
     UserEntity& operator=(UserEntity&&);
     ~UserEntity();
 
+    PublicKeyCredentialUserEntity ToPublicKeyCredentialUserEntity();
+
     std::vector<uint8_t> id;
     std::string name;
     std::string display_name;
@@ -63,26 +75,26 @@
 
   // SealCredentialId encrypts the given UserEntity into a credential id.
   static base::Optional<std::vector<uint8_t>> SealCredentialId(
-      const std::string& profile_id,
+      const std::string& secret,
       const std::string& rp_id,
       const UserEntity& user);
 
   // UnsealCredentialId attempts to decrypt a UserEntity from a given credential
   // id.
   static base::Optional<UserEntity> UnsealCredentialId(
-      const std::string& profile_id,
+      const std::string& secret,
       const std::string& rp_id,
       base::span<const uint8_t> credential_id);
 
   // EncodeRpIdAndUserId encodes the concatenation of RP ID and user ID for
   // storage in the macOS keychain.
   static base::Optional<std::string> EncodeRpIdAndUserId(
-      const std::string& profile_id,
+      const std::string& secret,
       const std::string& rp_id,
       base::span<const uint8_t> user_id);
 
   // EncodeRpId encodes the given RP ID for storage in the macOS keychain.
-  static base::Optional<std::string> EncodeRpId(const std::string& profile_id,
+  static base::Optional<std::string> EncodeRpId(const std::string& secret,
                                                 const std::string& rp_id);
 
  private:
@@ -92,7 +104,7 @@
   // which is used as the additional authenticated data (AAD) input to the AEAD.
   static std::string MakeAad(const std::string& rp_id);
 
-  CredentialMetadata(const std::string& profile_id);
+  CredentialMetadata(const std::string& secret);
   ~CredentialMetadata();
 
   base::Optional<std::string> Seal(base::span<const uint8_t> nonce,
@@ -104,11 +116,10 @@
       base::StringPiece authenticated_data) const;
   base::Optional<std::string> HmacForStorage(base::StringPiece data) const;
 
-  // profile_id_ is a randomly generated string identifying the current Chrome
-  // user profile. It is used to derive the key material for AEAD and HMAC.
-  // This ensures that credentials are logically tied to the Chrome user
-  // profile under which they were created.
-  const std::string& profile_id_;
+  // Used to derive keys for the HMAC and AEAD operations. Chrome picks
+  // different secrets for each user profile. This ensures that credentials are
+  // logically tied to the Chrome user profile under which they were created.
+  const std::string& secret_;
 
   DISALLOW_COPY_AND_ASSIGN(CredentialMetadata);
 };
diff --git a/device/fido/mac/credential_metadata_unittest.cc b/device/fido/mac/credential_metadata_unittest.cc
index f170b77a..574d34f 100644
--- a/device/fido/mac/credential_metadata_unittest.cc
+++ b/device/fido/mac/credential_metadata_unittest.cc
@@ -4,7 +4,9 @@
 
 #include "device/fido/mac/credential_metadata.h"
 
+#include "device/fido/public_key_credential_user_entity.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
 
 namespace device {
 namespace fido {
@@ -102,6 +104,38 @@
   EXPECT_NE(EncodeRpId(), *CredentialMetadata::EncodeRpId(wrong_key_, rp_id_));
 }
 
+TEST(CredentialMetadata, GenerateRandomSecret) {
+  std::string s1 = CredentialMetadata::GenerateRandomSecret();
+  EXPECT_EQ(32u, s1.size());
+  std::string s2 = CredentialMetadata::GenerateRandomSecret();
+  EXPECT_EQ(32u, s2.size());
+  EXPECT_NE(s1, s2);
+}
+
+TEST(CredentialMetadata, FromPublicKeyCredentialUserEntity) {
+  std::vector<uint8_t> user_id = {{1, 2, 3}};
+  PublicKeyCredentialUserEntity in(user_id);
+  in.SetUserName("username");
+  in.SetDisplayName("display name");
+  in.SetIconUrl(GURL("http://rp.foo/user.png"));
+  CredentialMetadata::UserEntity out =
+      CredentialMetadata::UserEntity::FromPublicKeyCredentialUserEntity(
+          std::move(in));
+  EXPECT_EQ(user_id, out.id);
+  EXPECT_EQ("username", out.name);
+  EXPECT_EQ("display name", out.display_name);
+}
+
+TEST(CredentialMetadata, ToPublicKeyCredentialUserEntity) {
+  std::vector<uint8_t> user_id = {{1, 2, 3}};
+  CredentialMetadata::UserEntity in(user_id, "username", "display name");
+  PublicKeyCredentialUserEntity out = in.ToPublicKeyCredentialUserEntity();
+  EXPECT_EQ(user_id, out.user_id());
+  EXPECT_EQ("username", out.user_name().value());
+  EXPECT_EQ("display name", out.user_display_name().value());
+  EXPECT_FALSE(out.user_icon_url().has_value());
+}
+
 }  // namespace
 }  // namespace mac
 }  // namespace fido
diff --git a/device/fido/mac/get_assertion_operation.h b/device/fido/mac/get_assertion_operation.h
index a36e2dd..3b4efd5 100644
--- a/device/fido/mac/get_assertion_operation.h
+++ b/device/fido/mac/get_assertion_operation.h
@@ -31,7 +31,7 @@
                            AuthenticatorGetAssertionResponse> {
  public:
   GetAssertionOperation(CtapGetAssertionRequest request,
-                        std::string profile_id,
+                        std::string metadata_secret,
                         std::string keychain_access_group,
                         Callback callback);
   ~GetAssertionOperation() override;
diff --git a/device/fido/mac/get_assertion_operation.mm b/device/fido/mac/get_assertion_operation.mm
index 2d5a94c..ff78d224 100644
--- a/device/fido/mac/get_assertion_operation.mm
+++ b/device/fido/mac/get_assertion_operation.mm
@@ -16,6 +16,8 @@
 #include "device/fido/fido_constants.h"
 #include "device/fido/mac/keychain.h"
 #include "device/fido/mac/util.h"
+#include "device/fido/public_key_credential_descriptor.h"
+#include "device/fido/public_key_credential_user_entity.h"
 
 namespace device {
 namespace fido {
@@ -24,12 +26,12 @@
 using base::ScopedCFTypeRef;
 
 GetAssertionOperation::GetAssertionOperation(CtapGetAssertionRequest request,
-                                             std::string profile_id,
+                                             std::string metadata_secret,
                                              std::string keychain_access_group,
                                              Callback callback)
     : OperationBase<CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>(
           std::move(request),
-          std::move(profile_id),
+          std::move(metadata_secret),
           std::move(keychain_access_group),
           std::move(callback)) {}
 GetAssertionOperation::~GetAssertionOperation() = default;
@@ -126,6 +128,21 @@
         .Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, base::nullopt);
     return;
   }
+
+  // Decrypt the user entity from the credential ID.
+  base::Optional<CredentialMetadata::UserEntity> credential_user =
+      CredentialMetadata::UnsealCredentialId(metadata_secret(), RpId(),
+                                             credential_id);
+  if (!credential_user) {
+    // The keychain query already filtered for the RP ID encoded under this
+    // operation's metadata secret, so the credential id really should have
+    // been decryptable.
+    DVLOG(1) << "UnsealCredentialId failed";
+    std::move(callback())
+        .Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, base::nullopt);
+    return;
+  }
+
   base::ScopedCFTypeRef<SecKeyRef> public_key(
       Keychain::GetInstance().KeyCopyPublicKey(private_key));
   if (!public_key) {
@@ -137,7 +154,7 @@
   }
 
   base::Optional<AuthenticatorData> authenticator_data =
-      MakeAuthenticatorData(RpId(), std::move(credential_id), public_key);
+      MakeAuthenticatorData(RpId(), credential_id, public_key);
   if (!authenticator_data) {
     DLOG(ERROR) << "MakeAuthenticatorData failed";
     std::move(callback())
@@ -152,10 +169,14 @@
         .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
     return;
   }
+  auto response = AuthenticatorGetAssertionResponse(
+      std::move(*authenticator_data), std::move(*signature));
+  response.SetCredential(PublicKeyCredentialDescriptor(
+      CredentialType::kPublicKey, std::move(credential_id)));
+  response.SetUserEntity(credential_user->ToPublicKeyCredentialUserEntity());
+
   std::move(callback())
-      .Run(CtapDeviceResponseCode::kSuccess,
-           AuthenticatorGetAssertionResponse(std::move(*authenticator_data),
-                                             std::move(*signature)));
+      .Run(CtapDeviceResponseCode::kSuccess, std::move(response));
 }
 
 }  // namespace mac
diff --git a/device/fido/mac/get_assertion_operation_unittest_mac.mm b/device/fido/mac/get_assertion_operation_unittest_mac.mm
index b6d11ca..62457f7 100644
--- a/device/fido/mac/get_assertion_operation_unittest_mac.mm
+++ b/device/fido/mac/get_assertion_operation_unittest_mac.mm
@@ -78,6 +78,8 @@
   EXPECT_EQ(CtapDeviceResponseCode::kSuccess, error);
   auto opt_response = std::move(std::get<1>(result));
   ASSERT_TRUE(opt_response);
+  ASSERT_TRUE(opt_response->credential());
+  EXPECT_FALSE(opt_response->credential()->id().empty());
 };
 }
 }  // namespace mac
diff --git a/device/fido/mac/make_credential_operation.mm b/device/fido/mac/make_credential_operation.mm
index f6b630c2..ba9c234 100644
--- a/device/fido/mac/make_credential_operation.mm
+++ b/device/fido/mac/make_credential_operation.mm
@@ -26,13 +26,13 @@
 
 MakeCredentialOperation::MakeCredentialOperation(
     CtapMakeCredentialRequest request,
-    std::string profile_id,
+    std::string metadata_secret,
     std::string keychain_access_group,
     Callback callback)
     : OperationBase<CtapMakeCredentialRequest,
                     AuthenticatorMakeCredentialResponse>(
           std::move(request),
-          std::move(profile_id),
+          std::move(metadata_secret),
           std::move(keychain_access_group),
           std::move(callback)) {}
 MakeCredentialOperation::~MakeCredentialOperation() = default;
@@ -110,7 +110,7 @@
 
   // Delete the key pair for this RP + user handle if one already exists.
   base::Optional<std::string> encoded_rp_id_user_id =
-      CredentialMetadata::EncodeRpIdAndUserId(profile_id(), RpId(),
+      CredentialMetadata::EncodeRpIdAndUserId(metadata_secret(), RpId(),
                                               request().user().user_id());
   if (!encoded_rp_id_user_id) {
     // Internal error.
@@ -214,10 +214,9 @@
 base::Optional<std::vector<uint8_t>>
 MakeCredentialOperation::GenerateCredentialIdForRequest() const {
   return CredentialMetadata::SealCredentialId(
-      profile_id(), RpId(),
-      CredentialMetadata::UserEntity(
-          request().user().user_id(), request().user().user_name().value_or(""),
-          request().user().user_display_name().value_or("")));
+      metadata_secret(), RpId(),
+      CredentialMetadata::UserEntity::FromPublicKeyCredentialUserEntity(
+          request().user()));
 }
 
 }  // namespace mac
diff --git a/device/fido/mac/operation_base.h b/device/fido/mac/operation_base.h
index 5a9fd84..8ed8018 100644
--- a/device/fido/mac/operation_base.h
+++ b/device/fido/mac/operation_base.h
@@ -30,11 +30,11 @@
                                            base::Optional<Response>)>;
 
   OperationBase(Request request,
-                std::string profile_id,
+                std::string metadata_secret,
                 std::string keychain_access_group,
                 Callback callback)
       : request_(std::move(request)),
-        profile_id_(std::move(profile_id)),
+        metadata_secret_(std::move(metadata_secret)),
         keychain_access_group_(std::move(keychain_access_group)),
         callback_(std::move(callback)),
         touch_id_context_(std::make_unique<TouchIdContext>()) {}
@@ -45,7 +45,7 @@
   // Subclasses must call Init() at the beginning of Run().
   bool Init() {
     base::Optional<std::string> rp_id =
-        CredentialMetadata::EncodeRpId(profile_id(), RpId());
+        CredentialMetadata::EncodeRpId(metadata_secret(), RpId());
     if (!rp_id)
       return false;
 
@@ -80,9 +80,9 @@
   }
 
   // DefaultKeychainQuery returns a default keychain query dictionary that has
-  // the keychain item class, profile ID and RP ID filled out (but not the
-  // credential ID). More fields can be set on the return value to refine the
-  // query.
+  // the keychain item class, keychain access group and RP ID filled out (but
+  // not the credential ID). More fields can be set on the return value to
+  // refine the query.
   base::ScopedCFTypeRef<CFMutableDictionaryRef> DefaultKeychainQuery() const {
     base::ScopedCFTypeRef<CFMutableDictionaryRef> query(
         CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr));
@@ -95,14 +95,16 @@
     return query;
   }
 
-  const std::string& profile_id() const { return profile_id_; }
+  const std::string& metadata_secret() const { return metadata_secret_; }
 
   const Request& request() const { return request_; }
   Callback& callback() { return callback_; }
 
  private:
   Request request_;
-  std::string profile_id_;
+  // The secret parameter passed to |CredentialMetadata| operations to encrypt
+  // or encode credential metadata for storage in the macOS keychain.
+  std::string metadata_secret_;
   std::string keychain_access_group_;
   std::string encoded_rp_id_ = "";
   Callback callback_;
diff --git a/device/fido/mac/util.mm b/device/fido/mac/util.mm
index afced59..53b545bb 100644
--- a/device/fido/mac/util.mm
+++ b/device/fido/mac/util.mm
@@ -83,7 +83,8 @@
   constexpr uint8_t flags =
       static_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserVerification) |
       static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
-  std::array<uint8_t, 4> counter = {0, 0, 0, 0};  // implement
+  // TODO(martinkr): Implement signature counters.
+  std::array<uint8_t, 4> counter = {0, 0, 0, 1};
   auto ec_public_key = MakeECPublicKey(public_key);
   if (!ec_public_key) {
     LOG(ERROR) << "MakeECPublicKey failed";
diff --git a/device/geolocation/BUILD.gn b/device/geolocation/BUILD.gn
index b321a72..9243907 100644
--- a/device/geolocation/BUILD.gn
+++ b/device/geolocation/BUILD.gn
@@ -56,7 +56,6 @@
 
   deps = [
     "//base",
-    "//mojo/edk",
     "//mojo/public/cpp/bindings",
     "//net",
     "//ui/gfx",
diff --git a/docs/android_build_instructions.md b/docs/android_build_instructions.md
index 69e23865..da788ade 100644
--- a/docs/android_build_instructions.md
+++ b/docs/android_build_instructions.md
@@ -355,7 +355,7 @@
 ## Installing and Running Chromium on an Emulator
 
 Running on an emulator is the same as on a device. Refer to
-[android_emulators.md](android_emulators.md) for setting up emulators.
+[android_emulator.md](android_emulator.md) for setting up emulators.
 
 
 ## Tips, tricks, and troubleshooting
diff --git a/docs/android_test_instructions.md b/docs/android_test_instructions.md
index 9e10a69..6fc4649 100644
--- a/docs/android_test_instructions.md
+++ b/docs/android_test_instructions.md
@@ -54,7 +54,7 @@
 ### Using Emulators
 
 Running tests on emulators is the same as on device. Refer to
-[android_emulators.md](android_emulators.md) for setting up emulators.
+[android_emulator.md](android_emulator.md) for setting up emulators.
 
 ## Building Tests
 
diff --git a/docs/memory/README.md b/docs/memory/README.md
index e8ee0c85..c64253d 100644
--- a/docs/memory/README.md
+++ b/docs/memory/README.md
@@ -68,15 +68,15 @@
 ## Key knowledge areas and contacts
 | Knowledge Area | Contact points |
 |----------------|----------------|
-| Chrome on Android | mariakhomenko, dskiba, ssid |
-| Browser Process | mariakhomenko, dskiba, ssid |
+| Chrome on Android | lizeb, pasko, ssid |
+| Browser Process | ssid, erikchen, etienneb |
 | GPU/cc | ericrk |
-| Memory metrics | erikchen, primano, ajwong, wez |
-| Native Heap Profiling | primiano, dskiba, ajwong |
+| Memory metrics | ssid, erikchen, primano, ajwong, wez |
+| Native Heap Profiling | primiano, ajwong |
 | Net Stack | mmenke, rsleevi, xunjieli |
 | Renderer Process | haraken, tasak, hajimehoshi, keishi, hiroshige |
 | V8 | hpayer, ulan, verwaest, mlippautz |
-| Out of Process Heap Profiling | erikchen, ajwong, brettw, etienneb
+| Out of Process Heap Profiling | erikchen, ajwong, brettw, etienneb |
 
 
 ## Other docs
diff --git a/extensions/renderer/DEPS b/extensions/renderer/DEPS
index 2171c3a..d11f4ab 100644
--- a/extensions/renderer/DEPS
+++ b/extensions/renderer/DEPS
@@ -4,7 +4,6 @@
   "+content/public/renderer",
 
   "+gin",
-  "+mojo/edk/js",
 
   "+third_party/skia/include/core",
   "+third_party/cld_3",
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 34ea6010..b19629b 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -377,9 +377,9 @@
 builder_mixins {
   name: "xcode-10-caches"
   caches: {
-    # Cache for Xcode 10.0 beta 1 (build version 10l176w) needed for iOS builds.
-    name: "xcode_ios_10l176w"
-    path: "xcode_ios_10l176w.app"
+    # Cache for Xcode 10.0 beta 2 (build version 10L177m) needed for iOS builds.
+    name: "xcode_ios_10l177m"
+    path: "xcode_ios_10l177m.app"
   }
 }
 
diff --git a/ios/build/bots/chromium.fyi/ios11-beta-simulator.json b/ios/build/bots/chromium.fyi/ios11-beta-simulator.json
index 389ee8f..77f4505c 100644
--- a/ios/build/bots/chromium.fyi/ios11-beta-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios11-beta-simulator.json
@@ -52,77 +52,37 @@
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
-      "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "os": "11.4",
+      "host os": "Mac-10.13",
+      "xcode build version": "9q1019a"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 5s",
-      "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "os": "11.4",
+      "host os": "Mac-10.13",
+      "xcode build version": "9q1019a"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s",
-      "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "os": "11.4",
+      "host os": "Mac-10.13",
+      "xcode build version": "9q1019a"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
-      "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "os": "11.4",
+      "host os": "Mac-10.13",
+      "xcode build version": "9q1019a"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone X",
-      "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "os": "11.4",
+      "host os": "Mac-10.13",
+      "xcode build version": "9q1019a"
     }
   ]
 }
diff --git a/ios/build/bots/chromium.fyi/ios12-sdk-device.json b/ios/build/bots/chromium.fyi/ios12-sdk-device.json
index 0db8698..fe425c8 100644
--- a/ios/build/bots/chromium.fyi/ios12-sdk-device.json
+++ b/ios/build/bots/chromium.fyi/ios12-sdk-device.json
@@ -4,7 +4,7 @@
     "Build is performed with gn+ninja.",
     "If modified, please change chromium.fyi/ios-device-goma-canary-clobber.json too."
   ],
-  "xcode build version": "10l176w",
+  "xcode build version": "10l177m",
   "gn_args": [
     "additional_target_cpus=[ \"arm64\" ]",
     "goma_dir=\"$(goma_dir)\"",
diff --git a/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json b/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json
index d477a4f..5830d7d 100644
--- a/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios12-sdk-simulator.json
@@ -4,7 +4,7 @@
     "on iPad, iPhone, @3x, and @2x on main and CQ ios12-beta-simulator.",
     "Note: Xcode 10.3 requires Mac OS 10.13.X or higher, hence 'host os'."
   ],
-  "xcode build version": "10l176w",
+  "xcode build version": "10l177m",
   "gn_args": [
     "additional_target_cpus=[\"x86\"]",
     "goma_dir=\"$(goma_dir)\"",
@@ -25,328 +25,115 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPad Air 2",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
-    },
-    {
-      "include": "common_tests.json",
-      "device type": "iPhone 6s",
-      "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "common_tests.json",
       "device type": "iPhone 6s",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
-    },
-    {
-      "include": "common_tests.json",
-      "device type": "iPad Air 2",
-      "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPhone 6s",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPhone 6s",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     }
   ]
 }
diff --git a/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json b/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json
index ed8ea406..c0f9e02 100644
--- a/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json
+++ b/ios/build/bots/chromium.fyi/ios12-sdk-xcode-clang.json
@@ -3,7 +3,7 @@
     "Tests for super-fat iOS 12.0.",
     "Build is performed with gn+ninja."
   ],
-  "xcode build version": "10l176w",
+  "xcode build version": "10l177m",
   "use xcode build version": true,
   "gn_args": [
     "additional_target_cpus=[\"x86\"]",
diff --git a/ios/build/bots/chromium.mac/ios12-sdk-simulator.json b/ios/build/bots/chromium.mac/ios12-sdk-simulator.json
index d477a4f..5830d7d 100644
--- a/ios/build/bots/chromium.mac/ios12-sdk-simulator.json
+++ b/ios/build/bots/chromium.mac/ios12-sdk-simulator.json
@@ -4,7 +4,7 @@
     "on iPad, iPhone, @3x, and @2x on main and CQ ios12-beta-simulator.",
     "Note: Xcode 10.3 requires Mac OS 10.13.X or higher, hence 'host os'."
   ],
-  "xcode build version": "10l176w",
+  "xcode build version": "10l177m",
   "gn_args": [
     "additional_target_cpus=[\"x86\"]",
     "goma_dir=\"$(goma_dir)\"",
@@ -25,328 +25,115 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone 7",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPad Air 2",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPad Air 2",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
-    },
-    {
-      "include": "common_tests.json",
-      "device type": "iPhone 6s",
-      "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "common_tests.json",
       "device type": "iPhone 6s",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
-    },
-    {
-      "include": "common_tests.json",
-      "device type": "iPad Air 2",
-      "os": "10.3",
-      "xcode build version": "8E3004b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPhone 6s",
       "os": "12.0",
-      "dimensions": [
-        {
-          "os": "Mac-10.13.4",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13.5",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     },
     {
       "include": "eg_cq_tests.json",
       "device type": "iPhone 6s",
       "os": "11.2",
-      "xcode build version": "9C40b",
-      "dimensions": [
-        {
-          "os": "Mac-10.12",
-          "pool": "Chrome"
-        },
-        {
-          "os": "Mac-10.13",
-          "pool": "Chrome"
-        }
-      ]
+      "host os": "Mac-10.13.5"
     }
   ]
 }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index fa933322..86d1aed 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -958,6 +958,10 @@
 
   [_mainCoordinator stop];
 
+  ios::GetChromeBrowserProvider()
+      ->GetMailtoHandlerProvider()
+      ->RemoveMailtoHandling();
+
   _chromeMain.reset();
 }
 
@@ -1152,14 +1156,13 @@
         enqueueBlockNamed:kMailtoHandlingInitialization
                     block:^{
                       __strong __typeof(weakSelf) strongSelf = weakSelf;
-                      if (!strongSelf) {
+                      if (!strongSelf || !strongSelf->_mainBrowserState) {
                         return;
                       }
-                      MailtoHandlerProvider* provider =
-                          ios::GetChromeBrowserProvider()
-                              ->GetMailtoHandlerProvider();
-                      provider->PrepareMailtoHandling(
-                          strongSelf->_mainBrowserState);
+                      ios::GetChromeBrowserProvider()
+                          ->GetMailtoHandlerProvider()
+                          ->PrepareMailtoHandling(
+                              strongSelf->_mainBrowserState);
                     }];
   }
 }
diff --git a/ios/chrome/browser/autofill/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/autofill_controller_unittest.mm
index 2ba97c5..ff581e6 100644
--- a/ios/chrome/browser/autofill/autofill_controller_unittest.mm
+++ b/ios/chrome/browser/autofill/autofill_controller_unittest.mm
@@ -263,11 +263,11 @@
 TEST_F(AutofillControllerTest, ReadForm) {
   AutofillManager* autofill_manager =
       AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
-  EXPECT_TRUE(autofill_manager->GetFormStructures().empty())
+  EXPECT_TRUE(autofill_manager->form_structures().empty())
       << "Forms are registered at beginning";
   LoadHtml(kProfileFormHtml);
   const std::vector<std::unique_ptr<FormStructure>>& forms =
-      autofill_manager->GetFormStructures();
+      autofill_manager->form_structures();
   ASSERT_EQ(1U, forms.size());
   CheckField(*forms[0], NAME_FULL, "name_1");
   CheckField(*forms[0], ADDRESS_HOME_LINE1, "address_1");
@@ -286,7 +286,7 @@
       AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
   LoadHtml(kMinimalFormWithNameHtml);
   const std::vector<std::unique_ptr<FormStructure>>& forms =
-      autofill_manager->GetFormStructures();
+      autofill_manager->form_structures();
   ASSERT_EQ(1U, forms.size());
   EXPECT_EQ(base::UTF8ToUTF16("form1"), forms[0]->ToFormData().name);
 };
diff --git a/ios/chrome/browser/autofill/form_structure_browsertest.mm b/ios/chrome/browser/autofill/form_structure_browsertest.mm
index 5cefbee..aabc3dbef 100644
--- a/ios/chrome/browser/autofill/form_structure_browsertest.mm
+++ b/ios/chrome/browser/autofill/form_structure_browsertest.mm
@@ -172,7 +172,7 @@
       AutofillDriverIOS::FromWebState(web_state())->autofill_manager();
   ASSERT_NE(nullptr, autofill_manager);
   const std::vector<std::unique_ptr<FormStructure>>& forms =
-      autofill_manager->form_structures_;
+      autofill_manager->form_structures();
   *output = FormStructureBrowserTest::FormStructuresToString(forms);
 }
 
diff --git a/ios/chrome/browser/passwords/OWNERS b/ios/chrome/browser/passwords/OWNERS
index 6576ef6..70725e2b 100644
--- a/ios/chrome/browser/passwords/OWNERS
+++ b/ios/chrome/browser/passwords/OWNERS
@@ -1,4 +1,5 @@
 dvadym@chromium.org
+ioanap@chromium.org
 vabr@chromium.org
 vasilii@chromium.org
 
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
index a2e4a9d..cc4840b 100644
--- a/ios/chrome/browser/ui/bubble/bubble_presenter.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
@@ -17,6 +17,7 @@
 #import "ios/chrome/browser/ui/bubble/bubble_util.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h"
 #import "ios/chrome/browser/ui/commands/toolbar_commands.h"
+#include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
 #import "ios/chrome/browser/ui/util/named_guide_util.h"
@@ -30,6 +31,10 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+const CGFloat kBubblePresentationDelay = 1;
+}  // namespace
+
 @interface BubblePresenter ()
 
 // Used to display the bottom toolbar tip in-product help promotion bubble.
@@ -84,7 +89,16 @@
   void (^onInitializedBlock)(bool) = ^(bool successfullyLoaded) {
     if (!successfullyLoaded)
       return;
-    [weakSelf presentBubbles];
+    if (IsUIRefreshPhase1Enabled()) {
+      dispatch_after(
+          dispatch_time(DISPATCH_TIME_NOW,
+                        (int64_t)(kBubblePresentationDelay * NSEC_PER_SEC)),
+          dispatch_get_main_queue(), ^{
+            [weakSelf presentBubbles];
+          });
+    } else {
+      [weakSelf presentBubbles];
+    }
   };
 
   // Because the new tab tip occurs on startup, the feature engagement
diff --git a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
index 11ed70fe..6eb9900 100644
--- a/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
+++ b/ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.mm
@@ -9,6 +9,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "ios/chrome/browser/ui/bubble/bubble_util.h"
 #import "ios/chrome/browser/ui/bubble/bubble_view_controller.h"
+#include "ios/chrome/browser/ui/ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -17,7 +18,8 @@
 namespace {
 
 // How long, in seconds, the bubble is visible on the screen.
-const NSTimeInterval kBubbleVisibilityDuration = 4.0;
+const NSTimeInterval kBubbleVisibilityDurationLegacy = 4.0;
+const NSTimeInterval kBubbleVisibilityDuration = 5.0;
 // How long, in seconds, the user should be considered engaged with the bubble
 // after the bubble first becomes visible.
 const NSTimeInterval kBubbleEngagementDuration = 30.0;
@@ -150,8 +152,12 @@
       addGestureRecognizer:self.insideBubbleTapRecognizer];
   [parentView addGestureRecognizer:self.outsideBubbleTapRecognizer];
 
+  CGFloat duration = IsUIRefreshPhase1Enabled()
+                         ? kBubbleVisibilityDuration
+                         : kBubbleVisibilityDurationLegacy;
+
   self.bubbleDismissalTimer = [NSTimer
-      scheduledTimerWithTimeInterval:kBubbleVisibilityDuration
+      scheduledTimerWithTimeInterval:duration
                               target:self
                             selector:@selector(bubbleDismissalTimerFired:)
                             userInfo:nil
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
index 286a457..c6c012f 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
@@ -20,6 +20,9 @@
 
 const CGFloat kButtonTrailingSpacing = 10;
 
+// Font size used in the omnibox.
+const CGFloat kFontSize = 17.0f;
+
 }  // namespace
 
 @interface LocationBarSteadyView ()
@@ -101,7 +104,7 @@
     [_locationLabel
         setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
                                         forAxis:UILayoutConstraintAxisVertical];
-    _locationLabel.font = [UIFont systemFontOfSize:19.0];
+    _locationLabel.font = [UIFont systemFontOfSize:kFontSize];
 
     // Container for location label and icon.
     UIView* container = [[UIView alloc] init];
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
index feaec7e..c21a59c 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -159,7 +159,7 @@
 
 - (void)updateForFullscreenProgress:(CGFloat)progress {
   CGFloat alphaValue = fmax((progress - 0.85) / 0.15, 0);
-  CGFloat scaleValue = 0.75 + 0.25 * progress;
+  CGFloat scaleValue = 0.79 + 0.21 * progress;
   self.locationBarSteadyView.trailingButton.alpha = alphaValue;
   self.locationBarSteadyView.transform =
       CGAffineTransformMakeScale(scaleValue, scaleValue);
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
index c3850e6..2d70b5d 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
index cdce49c..d0f9899 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
index bbabcd87..d869872 100644
--- a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm b/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm
index 32d2ee1..fe9ea7f0 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_container_view.mm
@@ -26,6 +26,9 @@
 const CGFloat kTextFieldLeadingOffsetNoImage = 16;
 // Space between the leading button and the textfield when a button is shown.
 const CGFloat kTextFieldLeadingOffsetImage = 6;
+// Space between the clear button and the edge of the omnibox.
+const CGFloat kTextFieldClearButtonTrailingOffset = 4;
+
 }  // namespace
 
 #pragma mark - OmniboxContainerView
@@ -74,11 +77,10 @@
 
     [NSLayoutConstraint activateConstraints:@[
       [_textField.trailingAnchor
-          constraintEqualToAnchor:self.layoutMarginsGuide.trailingAnchor],
-      [_textField.topAnchor
-          constraintEqualToAnchor:self.layoutMarginsGuide.topAnchor],
-      [_textField.bottomAnchor
-          constraintEqualToAnchor:self.layoutMarginsGuide.bottomAnchor],
+          constraintEqualToAnchor:self.trailingAnchor
+                         constant:-kTextFieldClearButtonTrailingOffset],
+      [_textField.topAnchor constraintEqualToAnchor:self.topAnchor],
+      [_textField.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
       _leadingTextfieldConstraint,
     ]];
 
@@ -101,10 +103,9 @@
   } else {
     [self addSubview:_leadingImageView];
     self.leadingTextfieldConstraint.active = NO;
-    self.leadingImageViewLeadingConstraint =
-        [self.layoutMarginsGuide.leadingAnchor
-            constraintEqualToAnchor:self.leadingImageView.leadingAnchor
-                           constant:-kleadingImageViewEdgeOffset];
+    self.leadingImageViewLeadingConstraint = [self.leadingAnchor
+        constraintEqualToAnchor:self.leadingImageView.leadingAnchor
+                       constant:-kleadingImageViewEdgeOffset];
 
     NSLayoutConstraint* leadingImageViewToTextField = nil;
     leadingImageViewToTextField = [self.leadingImageView.trailingAnchor
@@ -113,7 +114,7 @@
 
     [NSLayoutConstraint activateConstraints:@[
       [_leadingImageView.centerYAnchor
-          constraintEqualToAnchor:self.layoutMarginsGuide.centerYAnchor],
+          constraintEqualToAnchor:self.centerYAnchor],
       self.leadingImageViewLeadingConstraint,
       leadingImageViewToTextField,
     ]];
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
index 384bf40..66b26b3 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -925,11 +925,18 @@
 }
 
 - (UIColor*)selectedTextBackgroundColor {
-  return _selectedTextBackgroundColor ? _selectedTextBackgroundColor
-                                      : [UIColor colorWithRed:204.0 / 255
-                                                        green:221.0 / 255
-                                                         blue:237.0 / 255
-                                                        alpha:1.0];
+  if (!_selectedTextBackgroundColor) {
+    if (IsUIRefreshPhase1Enabled()) {
+      _selectedTextBackgroundColor =
+          [self.tintColor colorWithAlphaComponent:0.2];
+    } else {
+      _selectedTextBackgroundColor = [UIColor colorWithRed:204.0 / 255
+                                                     green:221.0 / 255
+                                                      blue:237.0 / 255
+                                                     alpha:1.0];
+    }
+  }
+  return _selectedTextBackgroundColor;
 }
 
 - (BOOL)isColorHidden:(UIColor*)color {
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
index ad09204..150c5e0 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
@@ -6,6 +6,7 @@
 
 #include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_container_view.h"
+#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #include "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
@@ -15,13 +16,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
-// Font size used in the omnibox.
-const CGFloat kFontSize = 19.0f;
-
-}  // namespace
-
 @interface OmniboxViewController ()
 
 // Override of UIViewController's view with a different type.
@@ -48,15 +42,16 @@
 - (void)loadView {
   UIColor* textColor = self.incognito ? [UIColor whiteColor]
                                       : [UIColor colorWithWhite:0 alpha:0.7];
-  UIColor* textFieldTintColor =
-      self.incognito ? [UIColor whiteColor] : [UIColor blackColor];
+  UIColor* textFieldTintColor = self.incognito
+                                    ? [UIColor whiteColor]
+                                    : UIColorFromRGB(kLocationBarTintBlue);
   UIColor* iconTintColor = self.incognito
                                ? [UIColor whiteColor]
                                : [UIColor colorWithWhite:0 alpha:0.7];
 
   self.view = [[OmniboxContainerView alloc]
       initWithFrame:CGRectZero
-               font:[UIFont systemFontOfSize:kFontSize]
+               font:[UIFont systemFontOfSize:kLocationBarFontSize]
           textColor:textColor
       textFieldTint:textFieldTintColor
            iconTint:iconTintColor];
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_positioner.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_positioner.h
index c7dd1680..54ba8af 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_positioner.h
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_positioner.h
@@ -13,6 +13,9 @@
 // View to which the popup view should be added as subview.
 - (UIView*)popupParentView;
 
+// The view controller that will parent the popup.
+- (UIViewController*)popupParentViewController;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_POSITIONER_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
index f2eb3c6..d31a0902 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.mm
@@ -86,7 +86,11 @@
 - (void)updateHeightAndAnimateAppearanceIfNecessary {
   UIView* popup = self.popupContainerView;
   if (!popup.superview) {
+    UIViewController* parentVC = [self.positioner popupParentViewController];
+    [parentVC addChildViewController:self.viewController];
     [[self.positioner popupParentView] addSubview:popup];
+    [self.viewController didMoveToParentViewController:parentVC];
+
     [self initialLayout];
   }
 
@@ -108,6 +112,7 @@
 
 - (void)animateCollapse {
   UIView* retainedPopupView = self.popupContainerView;
+  UIViewController* retainedViewController = self.viewController;
   if (!IsIPadIdiom()) {
     self.bottomConstraint.active = NO;
   }
@@ -119,7 +124,9 @@
         [[self.popupContainerView superview] layoutIfNeeded];
       }
       completion:^(BOOL) {
+        [retainedViewController willMoveToParentViewController:nil];
         [retainedPopupView removeFromSuperview];
+        [retainedViewController removeFromParentViewController];
       }];
 }
 
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
index 517808e..fc03a5c 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
@@ -171,6 +171,17 @@
   [self layoutRows];
 }
 
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:
+           (id<UIViewControllerTransitionCoordinator>)coordinator {
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+  [coordinator animateAlongsideTransition:^(
+                   id<UIViewControllerTransitionCoordinatorContext> context) {
+    [self layoutRows];
+  }
+                               completion:nil];
+}
+
 #pragma mark - Properties accessors
 
 - (void)setIncognito:(BOOL)incognito {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
index 26251333..9fa85b9 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
@@ -165,6 +165,10 @@
   return self.viewController.view.superview;
 }
 
+- (UIViewController*)popupParentViewController {
+  return self.viewController.parentViewController;
+}
+
 #pragma mark - Protected override
 
 - (void)updateToolbarForSideSwipeSnapshot:(web::WebState*)webState {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
index 62eb092..c80ae84a 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
@@ -135,6 +135,8 @@
       (kAdaptiveToolbarHeight - 2 * kAdaptiveLocationBarVerticalMargin -
        kToolbarHeightFullscreen) *
           progress);
+  self.view.locationBarBottomConstraint.constant =
+      -AlignValueToPixel(kAdaptiveLocationBarVerticalMargin * progress);
   self.view.locationBarContainer.backgroundColor =
       [self.buttonFactory.toolbarConfiguration
           locationBarBackgroundColorWithVisibility:alphaValue];
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
index 1afe3af..239860a 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.mm
@@ -447,6 +447,10 @@
 
 - (UIButton*)cancelButton {
   UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  cancelButton.titleLabel.font = [UIFont systemFontOfSize:kLocationBarFontSize];
+  cancelButton.tintColor = self.style == NORMAL
+                               ? UIColorFromRGB(kLocationBarTintBlue)
+                               : [UIColor whiteColor];
   [cancelButton setTitle:l10n_util::GetNSString(IDS_CANCEL)
                 forState:UIControlStateNormal];
   [cancelButton setContentHuggingPriority:UILayoutPriorityDefaultHigh
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h
index 786ff14..561f3b7 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h
@@ -136,4 +136,10 @@
   ToolbarControllerStyleMaxStyles
 };
 
+// Tint color for location bar and omnibox.
+extern const CGFloat kLocationBarTintBlue;
+
+// Font size used in omnibox and location bar.
+extern const CGFloat kLocationBarFontSize;
+
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_BUTTONS_TOOLBAR_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm
index 1d4f6364..83c23de 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.mm
@@ -64,7 +64,7 @@
 const CGFloat kExpandedLocationBarHorizontalMargin = 8;
 const CGFloat kContractedLocationBarHorizontalMargin = 19;
 
-const CGFloat kAdaptiveLocationBarCornerRadius = 11;
+const CGFloat kAdaptiveLocationBarCornerRadius = 18;
 const CGFloat kAdaptiveLocationBarBackgroundAlpha = 0.12;
 const CGFloat kAdaptiveLocationBarVerticalMargin = 6.0f;
 
@@ -93,3 +93,6 @@
 
 const CGFloat kToolbarShadowHeight = 2;
 const CGFloat kToolbarFullBleedShadowHeight = 10;
+
+const CGFloat kLocationBarTintBlue = 0x1A73E8;
+const CGFloat kLocationBarFontSize = 17.0f;
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
index 3758bf9..6c495b7 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
@@ -295,6 +295,10 @@
   return self.toolbarViewController.view.superview;
 }
 
+- (UIViewController*)popupParentViewController {
+  return self.toolbarViewController.parentViewController;
+}
+
 #pragma mark - ToolsMenuPresentationStateProvider
 
 - (BOOL)isShowingToolsMenu {
diff --git a/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h b/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h
index 2cfcff0..3980168 100644
--- a/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h
+++ b/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h
@@ -23,8 +23,11 @@
   MailtoHandlerProvider();
   virtual ~MailtoHandlerProvider();
 
-  // Set up mailto handling for the current browser state.
-  virtual void PrepareMailtoHandling(ios::ChromeBrowserState* browserState);
+  // Sets up mailto handling for |browser_state|.
+  virtual void PrepareMailtoHandling(ios::ChromeBrowserState* browser_state);
+
+  // Unregisters the mailto handler for browser state.
+  virtual void RemoveMailtoHandling();
 
   // Deprecated: Set up mailto handling for the current user.
   // The Signed-In Identity Block should return the primary signed in user.
diff --git a/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.mm b/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.mm
index 00ac77d..bb8bdd6 100644
--- a/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.mm
+++ b/ios/public/provider/chrome/browser/mailto/mailto_handler_provider.mm
@@ -13,7 +13,9 @@
 MailtoHandlerProvider::~MailtoHandlerProvider() {}
 
 void MailtoHandlerProvider::PrepareMailtoHandling(
-    ios::ChromeBrowserState* browserState) {}
+    ios::ChromeBrowserState* browser_state) {}
+
+void MailtoHandlerProvider::RemoveMailtoHandling() {}
 
 void MailtoHandlerProvider::PrepareMailtoHandling(
     SignedInIdentityBlock signed_in_identity_block,
diff --git a/mash/example/window_type_launcher/DEPS b/mash/example/window_type_launcher/DEPS
deleted file mode 100644
index 5d108a0..0000000
--- a/mash/example/window_type_launcher/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+mojo/edk/embedder",
-  "+mojo/runner",
-]
diff --git a/media/gpu/vaapi/vaapi_picture_factory.cc b/media/gpu/vaapi/vaapi_picture_factory.cc
index 5a726a3..5c4d1ac 100644
--- a/media/gpu/vaapi/vaapi_picture_factory.cc
+++ b/media/gpu/vaapi/vaapi_picture_factory.cc
@@ -45,7 +45,9 @@
     const MakeGLContextCurrentCallback& make_context_current_cb,
     const BindGLImageCallback& bind_image_cb,
     const PictureBuffer& picture_buffer) {
-  DCHECK_EQ(picture_buffer.texture_target(), GetGLTextureTarget());
+  // ARC++ sends |picture_buffer| with no texture_target().
+  DCHECK(picture_buffer.texture_target() == GetGLTextureTarget() ||
+         picture_buffer.texture_target() == 0u);
 
   // |client_texture_ids| and |service_texture_ids| are empty from ARC++.
   const uint32_t client_texture_id =
diff --git a/services/device/media_transfer_protocol/media_transfer_protocol_manager.cc b/services/device/media_transfer_protocol/media_transfer_protocol_manager.cc
index 94fd4d3..bb833e9a 100644
--- a/services/device/media_transfer_protocol/media_transfer_protocol_manager.cc
+++ b/services/device/media_transfer_protocol/media_transfer_protocol_manager.cc
@@ -17,7 +17,6 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
 #include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
 #include "base/threading/thread_checker.h"
@@ -66,27 +65,25 @@
 
     VLOG(1) << "MediaTransferProtocolManager Shutdown completed";
   }
-
   // MediaTransferProtocolManager override.
-  void AddObserverAndEnumerateStorages(
-      Observer* observer,
-      EnumerateStoragesCallback callback) override {
+  void EnumerateStoragesAndSetClient(
+      mojom::MtpManagerClientAssociatedPtrInfo client,
+      mojom::MtpManager::EnumerateStoragesAndSetClientCallback callback)
+      override {
     DCHECK(thread_checker_.CalledOnValidThread());
 
     // Return all available storage info.
-    std::vector<const mojom::MtpStorageInfo*> storage_info_list;
-    storage_info_list.reserve(storage_info_map_.size());
+    std::vector<mojom::MtpStorageInfoPtr> storage_info_ptr_list;
+    storage_info_ptr_list.reserve(storage_info_map_.size());
     for (const auto& info : storage_info_map_)
-      storage_info_list.push_back(&info.second);
-    std::move(callback).Run(std::move(storage_info_list));
+      storage_info_ptr_list.push_back(info.second.Clone());
+    std::move(callback).Run(std::move(storage_info_ptr_list));
 
-    observers_.AddObserver(observer);
-  }
+    // Set client.
+    if (!client.is_valid())
+      return;
 
-  // MediaTransferProtocolManager override.
-  void RemoveObserver(Observer* observer) override {
-    DCHECK(thread_checker_.CalledOnValidThread());
-    observers_.RemoveObserver(observer);
+    client_.Bind(std::move(client));
   }
 
   // MediaTransferProtocolManager override.
@@ -329,11 +326,14 @@
     if (storage_info_map_.erase(storage_name) == 0) {
       // This can happen for a storage where
       // MediaTransferProtocolDaemonClient::GetStorageInfo() failed.
-      // Return to avoid giving observers phantom detach events.
+      // Return to avoid giving client phantom detach events.
       return;
     }
-    for (auto& observer : observers_)
-      observer.StorageDetached(storage_name);
+
+    // Notify the bound MtpManagerClient.
+    if (client_) {
+      client_->StorageDetached(storage_name);
+    }
   }
 
   void OnStorageChanged(bool is_attach, const std::string& storage_name) {
@@ -367,16 +367,17 @@
       // After that, all incoming signals are either for new storage
       // attachments, which should not be in |storage_info_map_|, or for
       // storage detachments, which do not add to |storage_info_map_|.
-      // Return to avoid giving observers phantom detach events.
+      // Return to avoid giving client phantom detach events.
       NOTREACHED();
       return;
     }
 
-    // New storage. Add it and let the observers know.
+    // New storage. Add it and let the bound client know.
     storage_info_map_.insert(std::make_pair(storage_name, storage_info));
 
-    for (auto& observer : observers_)
-      observer.StorageAttached(storage_info);
+    if (client_) {
+      client_->StorageAttached(storage_info.Clone());
+    }
   }
 
   void OnGetStorageInfoFromDevice(const mojom::MtpStorageInfo& storage_info) {
@@ -572,8 +573,10 @@
   // DBusThreadManager to provide a bus in unit tests.
   scoped_refptr<dbus::Bus> const bus_;
 
-  // Device attachment / detachment observers.
-  base::ObserverList<Observer> observers_;
+  // MtpManager client who keeps tuned on attachment / detachment events.
+  // Currently, storage_monitor::StorageMonitorCros is supposed to be the
+  // only client.
+  mojom::MtpManagerClientAssociatedPtr client_;
 
   // Map to keep track of attached storages by name.
   base::flat_map<std::string, mojom::MtpStorageInfo> storage_info_map_;
diff --git a/services/device/media_transfer_protocol/media_transfer_protocol_manager.h b/services/device/media_transfer_protocol/media_transfer_protocol_manager.h
index ab03028..64bbc90 100644
--- a/services/device/media_transfer_protocol/media_transfer_protocol_manager.h
+++ b/services/device/media_transfer_protocol/media_transfer_protocol_manager.h
@@ -26,15 +26,8 @@
 namespace device {
 
 // This class handles the interaction with mtpd.
-// Other classes can add themselves as observers.
 class MediaTransferProtocolManager {
  public:
-  // A callback to handle the result of AddObserverAndEnumerateStorages().
-  // The argument is the returned vector of available MTP storages info.
-  // The pointers in the vector are guaranteed to be non-NULL.
-  using EnumerateStoragesCallback = base::OnceCallback<void(
-      std::vector<const mojom::MtpStorageInfo*> storage_info_list)>;
-
   // A callback to handle the result of GetStorages().
   // The argument is the returned vector of available MTP storage names.
   using GetStoragesCallback =
@@ -72,27 +65,15 @@
   // The first argument is true if there was an error.
   using DeleteObjectCallback = base::Callback<void(bool error)>;
 
-  // Implement this interface to be notified about MTP storage
-  // attachment / detachment events.
-  class Observer {
-   public:
-    virtual ~Observer() {}
-
-    // Functions called after a MTP storage has been attached / detached.
-    virtual void StorageAttached(
-        const device::mojom::MtpStorageInfo& storage_info) = 0;
-    virtual void StorageDetached(const std::string& storage_name) = 0;
-  };
-
   virtual ~MediaTransferProtocolManager() {}
 
-  // Adds an observer and runs |callback| with a list of existing storages.
-  virtual void AddObserverAndEnumerateStorages(
-      Observer* observer,
-      EnumerateStoragesCallback callback) = 0;
-
-  // Removes an observer.
-  virtual void RemoveObserver(Observer* observer) = 0;
+  // This is a combined interface to get existing storages and set a
+  // client for incoming storage change events. It is designed to reduce
+  // async calls and eliminate a potential race condition between
+  // the client being set and storage updates being made.
+  virtual void EnumerateStoragesAndSetClient(
+      mojom::MtpManagerClientAssociatedPtrInfo client,
+      mojom::MtpManager::EnumerateStoragesAndSetClientCallback callback) = 0;
 
   // Gets all available MTP storages and runs |callback|.
   virtual void GetStorages(GetStoragesCallback callback) const = 0;
diff --git a/services/device/media_transfer_protocol/mtp_device_manager.cc b/services/device/media_transfer_protocol/mtp_device_manager.cc
index 6356f84..6fa8ba2 100644
--- a/services/device/media_transfer_protocol/mtp_device_manager.cc
+++ b/services/device/media_transfer_protocol/mtp_device_manager.cc
@@ -9,40 +9,6 @@
 
 namespace device {
 
-namespace {
-
-class ForwardingMediaTransferProtocolManagerObserver
-    : public MediaTransferProtocolManager::Observer {
- public:
-  explicit ForwardingMediaTransferProtocolManagerObserver(
-      mojom::MtpManagerClientAssociatedPtr client)
-      : client_(std::move(client)) {}
-
-  void StorageAttached(
-      const device::mojom::MtpStorageInfo& storage_info) override {
-    client_->StorageAttached(storage_info.Clone());
-  }
-
-  void StorageDetached(const std::string& storage_name) override {
-    client_->StorageDetached(storage_name);
-  }
-
- private:
-  mojom::MtpManagerClientAssociatedPtr client_;
-};
-
-void EnumerateStorageCallbackWrapper(
-    mojom::MtpManager::EnumerateStoragesAndSetClientCallback callback,
-    std::vector<const mojom::MtpStorageInfo*> storage_info_list) {
-  std::vector<mojom::MtpStorageInfoPtr> storage_info_ptr_list(
-      storage_info_list.size());
-  for (size_t i = 0; i < storage_info_list.size(); ++i)
-    storage_info_ptr_list[i] = storage_info_list[i]->Clone();
-  std::move(callback).Run(std::move(storage_info_ptr_list));
-}
-
-}  // namespace
-
 MtpDeviceManager::MtpDeviceManager()
     : media_transfer_protocol_manager_(
           MediaTransferProtocolManager::Initialize()) {}
@@ -56,17 +22,8 @@
 void MtpDeviceManager::EnumerateStoragesAndSetClient(
     mojom::MtpManagerClientAssociatedPtrInfo client,
     EnumerateStoragesAndSetClientCallback callback) {
-  if (!client.is_valid())
-    return;
-
-  DCHECK(!observer_);
-  mojom::MtpManagerClientAssociatedPtr client_ptr;
-  client_ptr.Bind(std::move(client));
-  observer_ = std::make_unique<ForwardingMediaTransferProtocolManagerObserver>(
-      std::move(client_ptr));
-  media_transfer_protocol_manager_->AddObserverAndEnumerateStorages(
-      observer_.get(),
-      base::BindOnce(EnumerateStorageCallbackWrapper, std::move(callback)));
+  media_transfer_protocol_manager_->EnumerateStoragesAndSetClient(
+      std::move(client), std::move(callback));
 }
 
 void MtpDeviceManager::GetStorageInfo(const std::string& storage_name,
diff --git a/services/device/media_transfer_protocol/mtp_device_manager.h b/services/device/media_transfer_protocol/mtp_device_manager.h
index 9de60ebc..12afa11 100644
--- a/services/device/media_transfer_protocol/mtp_device_manager.h
+++ b/services/device/media_transfer_protocol/mtp_device_manager.h
@@ -74,7 +74,6 @@
   std::unique_ptr<MediaTransferProtocolManager>
       media_transfer_protocol_manager_;
 
-  std::unique_ptr<MediaTransferProtocolManager::Observer> observer_;
   mojo::BindingSet<mojom::MtpManager> bindings_;
 
   DISALLOW_COPY_AND_ASSIGN(MtpDeviceManager);
diff --git a/services/network/session_cleanup_cookie_store_unittest.cc b/services/network/session_cleanup_cookie_store_unittest.cc
index e3b8cce..7c6e4b8 100644
--- a/services/network/session_cleanup_cookie_store_unittest.cc
+++ b/services/network/session_cleanup_cookie_store_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/task_scheduler/task_scheduler.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
-#include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -127,11 +126,6 @@
   cookies.clear();
 }
 
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
-#define MAYBE_TestDeleteSessionCookies DISABLED_TestDeleteSessionCookies
-#else
-#define MAYBE_TestDeleteSessionCookies TestDeleteSessionCookies
-#endif
 TEST_F(SessionCleanupCookieStoreTest, TestDeleteSessionCookies) {
   CanonicalCookieVector cookies = CreateAndLoad();
   ASSERT_EQ(0u, cookies.size());
@@ -161,6 +155,7 @@
       base::BindRepeating([](const std::string& domain, bool is_https) {
         return domain == "nonpersistent.com";
       }));
+  scoped_task_environment_.RunUntilIdle();
   DestroyStore();
   cookies = CreateAndLoad();
 
@@ -198,6 +193,7 @@
       base::BindRepeating([](const std::string& domain, bool is_https) {
         return domain == "nonpersistent.com";
       }));
+  scoped_task_environment_.RunUntilIdle();
   DestroyStore();
   cookies = CreateAndLoad();
 
diff --git a/services/network/throttling/scoped_throttling_token.h b/services/network/throttling/scoped_throttling_token.h
index 69afce6..b97892a 100644
--- a/services/network/throttling/scoped_throttling_token.h
+++ b/services/network/throttling/scoped_throttling_token.h
@@ -7,6 +7,8 @@
 
 #include <stdint.h>
 
+#include <memory>
+
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/optional.h"
diff --git a/services/ui/common/DEPS b/services/ui/common/DEPS
index 5c8fe475..562f91be 100644
--- a/services/ui/common/DEPS
+++ b/services/ui/common/DEPS
@@ -6,9 +6,3 @@
   "+gpu/ipc/host",
   "+services/viz/privileged/interfaces",
 ]
-
-specific_include_rules = {
-  "run_all_service_tests\.cc": [
-    "+mojo/edk/embedder/embedder.h",
-  ],
-}
diff --git a/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom b/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom
index aefe35f9..8bcd4e4 100644
--- a/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom
+++ b/services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom
@@ -46,11 +46,6 @@
                   gfx.mojom.Rect content_rect,
                   FrameSinkVideoConsumerFrameCallbacks callbacks);
 
-  // Indicates the video capture target (a frame sink) has gone away. A consumer
-  // should use this to determine whether to change to a different target or
-  // shutdown.
-  OnTargetLost(FrameSinkId frame_sink_id);
-
   // Indicates that OnFrameCaptured() will not be called again, an end-of-stream
   // signal.
   OnStopped();
@@ -119,8 +114,9 @@
   SetAutoThrottlingEnabled(bool enabled);
 
   // Targets a different compositor frame sink. This may be called anytime,
-  // before or after Start().
-  ChangeTarget(FrameSinkId frame_sink_id);
+  // before or after Start(). If the argument is null, capture will suspend
+  // until a new frame sink target is set.
+  ChangeTarget(FrameSinkId? frame_sink_id);
 
   // Starts emitting video frames to the given |consumer|.
   Start(FrameSinkVideoConsumer consumer);
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 681b942..4a28eee7 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -5923,6 +5923,13 @@
       },
       {
         "swarming": {
+          "can_use_on_swarming_builders": true,
+          "shards": 6
+        },
+        "test": "interactive_ui_tests"
+      },
+      {
+        "swarming": {
           "can_use_on_swarming_builders": true
         },
         "test": "ipc_tests"
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index aadd3357..9b137ff6 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1457,8 +1457,6 @@
       # chromium.clang
       'ToTLinuxUBSanVptr',  # https://crbug.com/815190
       'UBSanVptr Linux',  # https://crbug.com/815190
-      # chromium.memory
-      'Linux TSan Tests',
     ],
     'modifications': {
       # chromium.win
@@ -1469,8 +1467,13 @@
       },
       # chromium.memory
       'Linux ASan LSan Tests (1)': {
-        # These are slow on the ASAN trybot for some reason.
-        # crbug.com/794372
+        # These are slow on the ASan trybot for some reason, crbug.com/794372
+        'swarming': {
+          'shards': 6,
+        },
+      },
+      'Linux TSan Tests': {
+        # These are slow on the TSan trybot for some reason, crbug.com/794372
         'swarming': {
           'shards': 6,
         },
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index e9f5f61..0aa0fa32 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -1,6 +1,7 @@
 # These tests currently fail when they run with --enable-blink-features=LayoutNG
 # See https://crbug.com/591099.
 
+
 # Need support for Range.getClientRects() and Range.getBoundingClientRect()
 crbug.com/755750 accessibility/selection-affinity.html [ Failure ]
 
@@ -104,6 +105,8 @@
 crbug.com/591099 compositing/geometry/repaint-foreground-layer.html [ Failure ]
 crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure ]
 crbug.com/591099 compositing/layer-creation/rotate3d-overlap.html [ Failure ]
+crbug.com/591099 compositing/overflow/scroll-ancestor-update.html [ Failure ]
+crbug.com/591099 compositing/self-painting-layers.html [ Failure ]
 crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ]
 crbug.com/591099 css1/box_properties/float_on_text_elements.html [ Failure ]
 crbug.com/591099 css1/classification/list_style_image.html [ Failure ]
@@ -432,7 +435,6 @@
 crbug.com/591099 fast/css-grid-layout/grid-self-baseline-vertical-rl-05.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/grid-self-baseline-vertical-rl-06.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/grid-self-baseline-vertical-rl-07.html [ Failure ]
-crbug.com/591099 fast/css-grid-layout/grid-shorthand-get-set.html [ Pass Timeout ]
 crbug.com/591099 fast/css-grid-layout/maximize-tracks-definite-indefinite-width.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/percent-padding-margin-resolution-grid-item.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/fillavailable-minmax-content-inlinesize-contribution-nonreplaced-blocks.html [ Failure ]
@@ -533,8 +535,6 @@
 crbug.com/591099 fast/lists/003.html [ Failure ]
 crbug.com/591099 fast/lists/004.html [ Failure ]
 crbug.com/591099 fast/lists/009-vertical.html [ Failure ]
-crbug.com/591099 fast/lists/calc-width-with-space.html [ Failure ]
-crbug.com/591099 fast/lists/inline-before-content-after-list-marker.html [ Failure ]
 crbug.com/591099 fast/lists/list-item-line-height.html [ Failure ]
 crbug.com/591099 fast/lists/marker-before-empty-inline.html [ Failure ]
 crbug.com/591099 fast/masking/clip-path-selection.html [ Failure ]
@@ -860,13 +860,12 @@
 crbug.com/591099 paint/invalidation/table/table-extra-bottom-grow.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-outer-border.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-row.html [ Failure ]
+crbug.com/591099 paint/invalidation/table/table-section-overflow.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-section-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-shrink-row-repaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/table/table-two-pass-layout-overpaint.html [ Failure ]
 crbug.com/591099 paint/invalidation/text-append-dirty-lines.html [ Failure ]
-crbug.com/714962 paint/invalidation/text-match-pre-wrapped-text.html [ Failure Pass ]
-crbug.com/714962 paint/invalidation/text-match-transparent-text.html [ Failure Pass ]
-crbug.com/714962 paint/invalidation/text-match.html [ Failure Pass ]
+crbug.com/591099 paint/invalidation/text-match-document-change.html [ Failure ]
 crbug.com/591099 paint/invalidation/transform/change-transform.html [ Failure ]
 crbug.com/591099 paint/invalidation/transform/transform-inline-layered-child.html [ Crash ]
 crbug.com/591099 paint/invalidation/transform/transform-layout-repaint.html [ Failure ]
@@ -885,7 +884,6 @@
 crbug.com/591099 paint/markers/ellipsis-mixed-text-in-rtl-flow-with-markers.html [ Failure ]
 crbug.com/591099 paint/markers/ellipsis-rtl-text-in-ltr-flow-with-markers.html [ Failure ]
 crbug.com/591099 paint/markers/ellipsis-rtl-text-in-rtl-flow-with-markers.html [ Failure ]
-crbug.com/591099 paint/markers/first-letter.html [ Failure Pass ]
 crbug.com/591099 paint/overflow/background-mask-should-be-recorded-full.html [ Failure ]
 crbug.com/591099 paint/pagination/pagination-change-clip-crash.html [ Failure ]
 crbug.com/714962 paint/text/text-match-highlights-big-line-height.html [ Failure ]
@@ -894,8 +892,8 @@
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
 crbug.com/591099 scrollbars/scrollbar-miss-mousemove-disabled.html [ Failure ]
 crbug.com/591099 shapedetection/detection-HTMLVideoElement.html [ Pass ]
-crbug.com/591099 storage/indexeddb/cursor-continue-validity.html [ Timeout ]
-crbug.com/591099 storage/indexeddb/index-cursor.html [ Pass Timeout ]
+crbug.com/591099 storage/indexeddb/cursor-continue-validity.html [ Pass Timeout ]
+crbug.com/591099 storage/indexeddb/index-cursor.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/mozilla/indexes.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ]
@@ -941,7 +939,6 @@
 crbug.com/591099 virtual/android/ [ Skip ]
 crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
 crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ]
-crbug.com/591099 virtual/gpu-rasterization/images/feature-policy-max-downscaling-image-styles.html [ Failure Pass ]
 crbug.com/591099 virtual/gpu/fast/canvas/shadow-huge-blur.html [ Pass ]
 crbug.com/591099 virtual/layout_ng/ [ Skip ]
 crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ]
@@ -968,6 +965,7 @@
 crbug.com/591099 virtual/spv2/paint/invalidation/box/margin.html [ Failure Pass ]
 crbug.com/591099 virtual/stable/ [ Skip ]
 crbug.com/591099 virtual/threaded/ [ Skip ]
+crbug.com/591099 virtual/user-activation-v2/fast/dom/Window/window-lookup-precedence.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/background-tab-on-submit-ctrl-click.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/background-tab-on-submit-synthesized-ctrl-click.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/event-on-culled_inline.html [ Failure ]
@@ -977,12 +975,14 @@
 crbug.com/591099 virtual/user-activation-v2/fast/events/select-element.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/sequential-focus-navigation-starting-point.html [ Failure ]
 crbug.com/591099 virtual/user-activation-v2/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
+crbug.com/591099 virtual/user-activation-v2/fullscreen/full-screen-with-flex-item.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/audio-controls-rendering.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/media-document-audio-repaint.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/picture-in-picture/picture-in-picture-enabled.html [ Pass ]
 crbug.com/591099 virtual/video-surface-layer/media/video-aspect-ratio.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/video-colorspace-yuv420.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/video-colorspace-yuv422.html [ Failure ]
+crbug.com/591099 virtual/video-surface-layer/media/video-display-toggle.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/video-layer-crash.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/video-poster-scale.html [ Failure ]
 crbug.com/591099 virtual/video-surface-layer/media/video-replaces-poster.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index 72df7a7..4d3917fe 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -6,6 +6,7 @@
 Bug(none) external/wpt/html/browsers/offline/appcache/workers/appcache-worker.html [ Timeout ]
 crbug.com/829417 external/wpt/html/browsers/offline/appcache/workers/appcache-worker.https.html [ Timeout ]
 crbug.com/771118 external/wpt/service-workers/service-worker/mime-sniffing.https.html [ Failure ]
+crbug.com/850839 external/wpt/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html [ Failure Crash ]
 
 # Passes on NetworkService and fails on non-NetworkService because
 # NetworkService isn't affected by https://crbug.com/595993.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f6fcc820..21bb728 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1754,6 +1754,7 @@
 
 # Failing tests in dictionary order.
 crbug.com/802835 virtual/outofblink-cors/external/wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html [ Failure ]
+crbug.com/850839 virtual/outofblink-cors/external/wpt/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-image-cache.https.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-image.https.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html [ Failure ]
@@ -2278,6 +2279,8 @@
 crbug.com/630342 virtual/mse-1mb-buffers/http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html [ Skip ]
 crbug.com/630342 http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-1mb-buffers.html [ Skip ]
 
+crbug.com/850839 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html [ Failure Crash ]
+
 # On these platforms (all but Android) media tests don't currently use gpu-accelerated (proprietary) codecs, so no
 # benefit to running them again with gpu acceleration enabled.
 crbug.com/555703 [ Linux Mac Win Fuchsia ] virtual/media-gpu-accelerated [ Skip ]
@@ -2815,6 +2818,10 @@
 crbug.com/849859 external/wpt/web-animations/timing-model/animations/pausing-an-animation.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-scoping/shadow-directionality-002.tentative.html [ Failure ]
+crbug.com/626703 external/wpt/infrastructure/server/order-of-metas.any.worker.html [ Timeout ]
+crbug.com/626703 external/wpt/css/css-scoping/shadow-directionality-001.tentative.html [ Failure ]
+crbug.com/626703 external/wpt/infrastructure/server/order-of-metas.any.sharedworker.html [ Timeout ]
 crbug.com/626703 external/wpt/payment-request/PaymentMethodChangeEvent/methodName-attribute.https.html [ Timeout ]
 crbug.com/626703 external/wpt/payment-request/PaymentMethodChangeEvent/methodDetails-attribute.https.html [ Timeout ]
 crbug.com/626703 external/wpt/screen-orientation/orientation-reading.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/battery-status/no-gc-with-pending-promise.html b/third_party/WebKit/LayoutTests/battery-status/no-gc-with-pending-promise.html
new file mode 100644
index 0000000..508bed03
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/battery-status/no-gc-with-pending-promise.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/gc.js"></script>
+<script>
+promise_test(async () => {
+  let batteryManagerPromise = navigator.getBattery();
+  gc();
+  await batteryManagerPromise;
+}, "navigator.getBattery() should resolve even in the face of GC");
+</script>
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/6026335-expected.txt b/third_party/WebKit/LayoutTests/editing/deleting/6026335-expected.txt
deleted file mode 100644
index ba7fada7..0000000
--- a/third_party/WebKit/LayoutTests/editing/deleting/6026335-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This tests deleting a selection that starts at the beginning of an editable pocket inside a non-editable table. The caret should not disappear during the delete and should be placed inside the editable span. When text is then inserted, it should be placed inside that span.
-
-<div contenteditable="false"><span>&nbsp;</span><span contenteditable="true" id="start">Text</span></div>
-
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/6026335.html b/third_party/WebKit/LayoutTests/editing/deleting/6026335.html
index de8a62f4..8312d7a4 100644
--- a/third_party/WebKit/LayoutTests/editing/deleting/6026335.html
+++ b/third_party/WebKit/LayoutTests/editing/deleting/6026335.html
@@ -1,18 +1,45 @@
-<div id="description">This tests deleting a selection that starts at the beginning of an editable pocket inside a non-editable table. The caret should not disappear during the delete and should be placed inside the editable span. When text is then inserted, it should be placed inside that span.</div>
-<div id="edit" contentEditable="true">
-<div contentEditable="false"><span>&nbsp;</span><span contentEditable="true" id="start">Hello</span></div>
-<div id="end"><br></div>
-</div>
-
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
 <script>
-if (window.testRunner)
-    testRunner.dumpAsText();
-start = document.getElementById("start");
-end = document.getElementById("end");
-s = window.getSelection();
-s.setBaseAndExtent(start, 0, end, 0);
-document.execCommand("Delete");
-document.execCommand("InsertText", false, "Text");
-if (window.testRunner)
-    document.body.innerText = document.getElementById("description").innerText + "\n" + document.getElementById("edit").innerHTML;
+selection_test(
+  [ '<div contenteditable>',
+      '<div contenteditable="false">',
+        '<span>&nbsp;</span>',
+        '<span contenteditable>|Hello</span>',
+      '</div>',
+      '<div>^<br></div>',
+    '</div>',
+  ],
+  'delete',
+  [ '<div contenteditable>',
+      '<div contenteditable="false">',
+        '<span>\xa0</span>',
+        '<span contenteditable>|</span>',
+      '</div>',
+    '</div>',
+  ],
+  'Test stage 1, tests deleting a selection that starts at the beginning of an editable pocket'
++ ' inside a non-editable table. The caret should not disappear during the delete and should be'
++ ' placed inside the editable span.'
+);
+selection_test(
+  [ '<div contenteditable>',
+      '<div contenteditable="false">',
+        '<span>\xa0</span>',
+        '<span contenteditable>|</span>',
+      '</div>',
+    '</div>',
+  ],
+  'insertText Text',
+  [ '<div contenteditable>',
+      '<div contenteditable="false">',
+        '<span>\xa0</span>',
+        '<span contenteditable>Text|</span>',
+      '</div>',
+    '</div>',
+  ],
+  'Test stage 2, when text is then inserted, it should be placed inside that span.'
+);
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 791d3020..4dd8138 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -52471,6 +52471,30 @@
      {}
     ]
    ],
+   "css/css-scoping/shadow-directionality-001.tentative.html": [
+    [
+     "/css/css-scoping/shadow-directionality-001.tentative.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/shadow-directionality-002.tentative.html": [
+    [
+     "/css/css-scoping/shadow-directionality-002.tentative.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/shadow-disabled-sheet-001.html": [
     [
      "/css/css-scoping/shadow-disabled-sheet-001.html",
@@ -95067,6 +95091,18 @@
      {}
     ]
    ],
+   "shadow-dom/directionality-001.tentative.html": [
+    [
+     "/shadow-dom/directionality-001.tentative.html",
+     [
+      [
+       "/shadow-dom/directionality-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "shadow-dom/layout-slot-no-longer-assigned.html": [
     [
      "/shadow-dom/layout-slot-no-longer-assigned.html",
@@ -95451,6 +95487,18 @@
      {}
     ]
    ],
+   "svg/pservers/reftests/radialgradient-basic-002.svg": [
+    [
+     "/svg/pservers/reftests/radialgradient-basic-002.svg",
+     [
+      [
+       "/svg/pservers/reftests/radialgradient-basic-002-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/shapes/line-dasharray.svg": [
     [
      "/svg/shapes/line-dasharray.svg",
@@ -102553,17 +102601,17 @@
      {}
     ]
    ],
-   "background-fetch/interfaces-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "background-fetch/interfaces-worker.https-expected.txt": [
     [
      {}
     ]
    ],
-   "background-fetch/interfaces.worker-expected.txt": [
+   "background-fetch/interfaces.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "background-fetch/interfaces.https.worker-expected.txt": [
     [
      {}
     ]
@@ -157118,6 +157166,31 @@
      {}
     ]
    ],
+   "infrastructure/server/order-of-metas.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "infrastructure/server/order-of-metas.window-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "infrastructure/server/resources/expect-global.js": [
+    [
+     {}
+    ]
+   ],
+   "infrastructure/server/resources/expect-seen-testharness.js": [
+    [
+     {}
+    ]
+   ],
+   "infrastructure/server/resources/expect-title-meta.js": [
+    [
+     {}
+    ]
+   ],
    "infrastructure/server/wpt-server-http.sub-expected.txt": [
     [
      {}
@@ -157418,11 +157491,26 @@
      {}
     ]
    ],
+   "interfaces/mediacapture-fromelement.idl": [
+    [
+     {}
+    ]
+   ],
+   "interfaces/mediacapture-image.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/mediacapture-main.idl": [
     [
      {}
     ]
    ],
+   "interfaces/mediacapture-record.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/mediasession.idl": [
     [
      {}
@@ -164443,11 +164531,6 @@
      {}
     ]
    ],
-   "server-timing/service_worker_idl-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "server-timing/sw.js": [
     [
      {}
@@ -164743,6 +164826,11 @@
      {}
     ]
    ],
+   "service-workers/service-worker/detached-context.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "service-workers/service-worker/fetch-canvas-tainting-video-cache.https-expected.txt": [
     [
      {}
@@ -165148,6 +165236,21 @@
      {}
     ]
    ],
+   "service-workers/service-worker/resources/cors-approved.txt": [
+    [
+     {}
+    ]
+   ],
+   "service-workers/service-worker/resources/cors-approved.txt.headers": [
+    [
+     {}
+    ]
+   ],
+   "service-workers/service-worker/resources/cors-denied.txt": [
+    [
+     {}
+    ]
+   ],
    "service-workers/service-worker/resources/dummy-shared-worker-interceptor.js": [
     [
      {}
@@ -166368,6 +166471,11 @@
      {}
     ]
    ],
+   "shadow-dom/directionality-001-ref.html": [
+    [
+     {}
+    ]
+   ],
    "shadow-dom/historical-expected.txt": [
     [
      {}
@@ -167443,6 +167551,11 @@
      {}
     ]
    ],
+   "svg/pservers/reftests/radialgradient-basic-002-ref.svg": [
+    [
+     {}
+    ]
+   ],
    "svg/shapes/line-dasharray-ref.svg": [
     [
      {}
@@ -167473,6 +167586,11 @@
      {}
     ]
    ],
+   "svg/styling/required-properties-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "svg/types/scripted/SVGLength-px-expected.txt": [
     [
      {}
@@ -169118,6 +169236,16 @@
      {}
     ]
    ],
+   "webrtc-stats/META.yml": [
+    [
+     {}
+    ]
+   ],
+   "webrtc-stats/README.md": [
+    [
+     {}
+    ]
+   ],
    "webrtc/META.yml": [
     [
      {}
@@ -172468,6 +172596,11 @@
      {}
     ]
    ],
+   "workers/modules/dedicated-worker-import.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "workers/modules/dedicated-worker-options-credentials.html.headers": [
     [
      {}
@@ -172613,6 +172746,31 @@
      {}
     ]
    ],
+   "workers/nested_worker_close_from_parent_worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "workers/nested_worker_close_self.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "workers/nested_worker_importScripts.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "workers/nested_worker_sync_xhr.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "workers/nested_worker_terminate_from_document-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "workers/non-automated/application-cache-dedicated.html": [
     [
      {}
@@ -172858,6 +173016,11 @@
      {}
     ]
    ],
+   "workers/support/parent_of_nested_worker.js": [
+    [
+     {}
+    ]
+   ],
    "workers/support/sandboxed-tests.html": [
     [
      {}
@@ -172868,6 +173031,16 @@
      {}
     ]
    ],
+   "workers/support/sync_xhr.js": [
+    [
+     {}
+    ]
+   ],
+   "workers/support/sync_xhr_target.xml": [
+    [
+     {}
+    ]
+   ],
    "worklets/META.yml": [
     [
      {}
@@ -178494,13 +178667,13 @@
      {}
     ]
    ],
-   "BackgroundSync/interfaces.any.js": [
+   "BackgroundSync/interfaces.https.any.js": [
     [
-     "/BackgroundSync/interfaces.any.html",
+     "/BackgroundSync/interfaces.https.any.html",
      {}
     ],
     [
-     "/BackgroundSync/interfaces.any.worker.html",
+     "/BackgroundSync/interfaces.https.any.worker.html",
      {}
     ]
    ],
@@ -182028,15 +182201,15 @@
      {}
     ]
    ],
-   "background-fetch/interfaces.html": [
+   "background-fetch/interfaces.https.html": [
     [
-     "/background-fetch/interfaces.html",
+     "/background-fetch/interfaces.https.html",
      {}
     ]
    ],
-   "background-fetch/interfaces.worker.js": [
+   "background-fetch/interfaces.https.worker.js": [
     [
-     "/background-fetch/interfaces.worker.html",
+     "/background-fetch/interfaces.https.worker.html",
      {}
     ]
    ],
@@ -222510,6 +222683,34 @@
      {}
     ]
    ],
+   "infrastructure/server/order-of-metas.any.js": [
+    [
+     "/infrastructure/server/order-of-metas.any.html",
+     {
+      "timeout": "long"
+     }
+    ],
+    [
+     "/infrastructure/server/order-of-metas.any.sharedworker.html",
+     {
+      "timeout": "long"
+     }
+    ],
+    [
+     "/infrastructure/server/order-of-metas.any.worker.html",
+     {
+      "timeout": "long"
+     }
+    ]
+   ],
+   "infrastructure/server/order-of-metas.window.js": [
+    [
+     "/infrastructure/server/order-of-metas.window.html",
+     {
+      "timeout": "long"
+     }
+    ]
+   ],
    "infrastructure/server/secure-context.https.any.js": [
     [
      "/infrastructure/server/secure-context.https.any.html",
@@ -235250,9 +235451,13 @@
      {}
     ]
    ],
-   "performance-timeline/performanceentry-tojson.html": [
+   "performance-timeline/performanceentry-tojson.any.js": [
     [
-     "/performance-timeline/performanceentry-tojson.html",
+     "/performance-timeline/performanceentry-tojson.any.html",
+     {}
+    ],
+    [
+     "/performance-timeline/performanceentry-tojson.any.worker.html",
      {}
     ]
    ],
@@ -235328,15 +235533,23 @@
      {}
     ]
    ],
-   "performance-timeline/po-takeRecords.html": [
+   "performance-timeline/po-takeRecords.any.js": [
     [
-     "/performance-timeline/po-takeRecords.html",
+     "/performance-timeline/po-takeRecords.any.html",
+     {}
+    ],
+    [
+     "/performance-timeline/po-takeRecords.any.worker.html",
      {}
     ]
    ],
-   "performance-timeline/webtiming-resolution.html": [
+   "performance-timeline/webtiming-resolution.any.js": [
     [
-     "/performance-timeline/webtiming-resolution.html",
+     "/performance-timeline/webtiming-resolution.any.html",
+     {}
+    ],
+    [
+     "/performance-timeline/webtiming-resolution.any.worker.html",
      {}
     ]
    ],
@@ -245226,9 +245439,9 @@
      {}
     ]
    ],
-   "server-timing/service_worker_idl.html": [
+   "server-timing/service_worker_idl.https.html": [
     [
-     "/server-timing/service_worker_idl.html",
+     "/server-timing/service_worker_idl.https.html",
      {}
     ]
    ],
@@ -245730,6 +245943,12 @@
      {}
     ]
    ],
+   "service-workers/service-worker/controller-with-no-fetch-event-handler.https.html": [
+    [
+     "/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html",
+     {}
+    ]
+   ],
    "service-workers/service-worker/dedicated-worker-service-worker-interception.https.html": [
     [
      "/service-workers/service-worker/dedicated-worker-service-worker-interception.https.html",
@@ -248818,6 +249037,12 @@
      {}
     ]
    ],
+   "svg/styling/required-properties.svg": [
+    [
+     "/svg/styling/required-properties.svg",
+     {}
+    ]
+   ],
    "svg/svg-in-svg/svg-in-svg-circular-filter-reference-crash.html": [
     [
      "/svg/svg-in-svg/svg-in-svg-circular-filter-reference-crash.html",
@@ -256258,9 +256483,13 @@
      {}
     ]
    ],
-   "workers/modules/dedicated-worker-import.html": [
+   "workers/modules/dedicated-worker-import.any.js": [
     [
-     "/workers/modules/dedicated-worker-import.html",
+     "/workers/modules/dedicated-worker-import.any.html",
+     {}
+    ],
+    [
+     "/workers/modules/dedicated-worker-import.any.worker.html",
      {}
     ]
    ],
@@ -256288,6 +256517,36 @@
      {}
     ]
    ],
+   "workers/nested_worker_close_from_parent_worker.html": [
+    [
+     "/workers/nested_worker_close_from_parent_worker.html",
+     {}
+    ]
+   ],
+   "workers/nested_worker_close_self.worker.js": [
+    [
+     "/workers/nested_worker_close_self.worker.html",
+     {}
+    ]
+   ],
+   "workers/nested_worker_importScripts.worker.js": [
+    [
+     "/workers/nested_worker_importScripts.worker.html",
+     {}
+    ]
+   ],
+   "workers/nested_worker_sync_xhr.worker.js": [
+    [
+     "/workers/nested_worker_sync_xhr.worker.html",
+     {}
+    ]
+   ],
+   "workers/nested_worker_terminate_from_document.html": [
+    [
+     "/workers/nested_worker_terminate_from_document.html",
+     {}
+    ]
+   ],
    "workers/opaque-origin.html": [
     [
      "/workers/opaque-origin.html",
@@ -268223,7 +268482,7 @@
    "d4b8d3ee30aca9e9bd4435534615172c89f9ca9c",
    "support"
   ],
-  "BackgroundSync/interfaces.any.js": [
+  "BackgroundSync/interfaces.https.any.js": [
    "4b754f0550409475495768483f2075e8f54782d0",
    "testharness"
   ],
@@ -270800,7 +271059,7 @@
    "manual"
   ],
   "accelerometer/META.yml": [
-   "939b04014d0d0c4818e330d4119ba6fdc9f7db58",
+   "f99b5f4f8bb9d631f1b55857512be56738801e6e",
    "support"
   ],
   "accelerometer/OWNERS": [
@@ -271559,27 +271818,27 @@
    "fd9efe16c485c6fa6cc4b587b492eb24bf9ccac2",
    "testharness"
   ],
-  "background-fetch/interfaces-expected.txt": [
-   "610600c981732946c6ee3b3ca950a4344f89e861",
-   "support"
-  ],
   "background-fetch/interfaces-worker.https-expected.txt": [
    "88211a0d44012d229af146366440ced5d12b0988",
    "support"
   ],
   "background-fetch/interfaces-worker.https.html": [
-   "3bdcb55c864d99da109cdc0abe56c06aaf3e3d1e",
+   "ddb477404c7f985dfa2ed61c820d68848ea3acb5",
    "testharness"
   ],
-  "background-fetch/interfaces.html": [
+  "background-fetch/interfaces.https-expected.txt": [
+   "145c69b2dffb9739c14693f8aa2ab2226a16a565",
+   "support"
+  ],
+  "background-fetch/interfaces.https.html": [
    "dc48b3e0bff00fed4a0e846e35f2499d6579dcd8",
    "testharness"
   ],
-  "background-fetch/interfaces.worker-expected.txt": [
-   "a8c15d8086ed570c858d0f2495423301b3c38e42",
+  "background-fetch/interfaces.https.worker-expected.txt": [
+   "be45725c15e69f8bd48e3f84a965b0347f399c5e",
    "support"
   ],
-  "background-fetch/interfaces.worker.js": [
+  "background-fetch/interfaces.https.worker.js": [
    "f1013d140f361226c81c24926548860d975ec3b2",
    "testharness"
   ],
@@ -273060,11 +273319,11 @@
    "support"
   ],
   "console/console-count-logging-manual.html": [
-   "1ffcacf40728c1cd9f0eadbd68dad59e7c2c35d3",
+   "f2e0d5c03356d15844f2ffa3f8800a7b44fd6319",
    "manual"
   ],
   "console/console-countReset-logging-manual.html": [
-   "587de5bb8dcb002025244e8058b52d4ba0b1bdd3",
+   "6edce76ce23ebc0b885f171020909617409016b9",
    "manual"
   ],
   "console/console-counting-label-conversion.any-expected.txt": [
@@ -273092,11 +273351,11 @@
    "support"
   ],
   "console/console-number-format-specifiers-symbol-manual.html": [
-   "a0b0c97ec5312027ff0152536458071254235d01",
+   "0ad8917ef886b6c9a6d0ce5f3befcca76a3b0fa4",
    "manual"
   ],
   "console/console-string-format-specifier-symbol-manual.html": [
-   "d3126f4c136d646f79f2534f66b4d9f8d0c5c67d",
+   "d1b45d95169637c84eb6509aa3f8d4cf118dcc8c",
    "manual"
   ],
   "console/console-tests-historical.any.js": [
@@ -307152,7 +307411,7 @@
    "support"
   ],
   "css/css-fonts/test_font_feature_values_parsing.html": [
-   "a6397508316c35300513830a7a53d882debe3829",
+   "fb4bbba9672183a627f7535399af8a58beec6eb8",
    "testharness"
   ],
   "css/css-fonts/variations/META.yml": [
@@ -313883,6 +314142,14 @@
    "46913ea7e47811b11be898de5c3bd0a330ea6637",
    "testharness"
   ],
+  "css/css-scoping/shadow-directionality-001.tentative.html": [
+   "51cf8c6780bb66f64082a0054f24f64c09b0258f",
+   "reftest"
+  ],
+  "css/css-scoping/shadow-directionality-002.tentative.html": [
+   "c5cc9738b5b81a728c7cc16569360bd65b857ab3",
+   "reftest"
+  ],
   "css/css-scoping/shadow-disabled-sheet-001.html": [
    "3de2d23c1b3339b964ec2c009832a3207a3b9dc4",
    "reftest"
@@ -338328,11 +338595,11 @@
    "testharness"
   ],
   "css/cssom/getComputedStyle-detached-subtree-expected.txt": [
-   "97468a05d62bcdfab973529ff97a6e8912195c37",
+   "fa6387feb811e5aa698070e867c96160936d3a9e",
    "support"
   ],
   "css/cssom/getComputedStyle-detached-subtree.html": [
-   "01978ca7ea08cbf61b28e9d77753fe5852bcbff9",
+   "886f72b4eaa82d3aeb4de5c5b27f71369dbe0186",
    "testharness"
   ],
   "css/cssom/getComputedStyle-dynamic-subdoc.html": [
@@ -352576,7 +352843,7 @@
    "testharness"
   ],
   "generic-sensor/META.yml": [
-   "501e235c91dc76460ba4932e9da1d074d657dd1e",
+   "5de173230a2e4904d93951cb5da07c2140768f2c",
    "support"
   ],
   "generic-sensor/OWNERS": [
@@ -352764,7 +353031,7 @@
    "testharness"
   ],
   "geolocation-sensor/META.yml": [
-   "b01c3f57ae359f08bb0ac0600e5dfde4a9b36571",
+   "5de8e1095bec7eb4dded143ac269e09ba4fa02c4",
    "support"
   ],
   "geolocation-sensor/idlharness.https-expected.txt": [
@@ -352880,7 +353147,7 @@
    "manual"
   ],
   "gyroscope/META.yml": [
-   "939b04014d0d0c4818e330d4119ba6fdc9f7db58",
+   "f99b5f4f8bb9d631f1b55857512be56738801e6e",
    "support"
   ],
   "gyroscope/OWNERS": [
@@ -373175,6 +373442,34 @@
    "7c39501c8a2ddcd9ee0405af1df84e259205ab04",
    "reftest"
   ],
+  "infrastructure/server/order-of-metas.any-expected.txt": [
+   "eead08f85859baaee78a90ef2b059a1d98dc2a96",
+   "support"
+  ],
+  "infrastructure/server/order-of-metas.any.js": [
+   "13cf63163e3aad97c71982929fbcc27ebf4fd5d1",
+   "testharness"
+  ],
+  "infrastructure/server/order-of-metas.window-expected.txt": [
+   "eead08f85859baaee78a90ef2b059a1d98dc2a96",
+   "support"
+  ],
+  "infrastructure/server/order-of-metas.window.js": [
+   "43c1f60e50759125c485fea1c536715b51b47444",
+   "testharness"
+  ],
+  "infrastructure/server/resources/expect-global.js": [
+   "0f13f760c717d07673e3f86662a115f855972a35",
+   "support"
+  ],
+  "infrastructure/server/resources/expect-seen-testharness.js": [
+   "3e40b1eb70e88f6666463b4711520528f26833e1",
+   "support"
+  ],
+  "infrastructure/server/resources/expect-title-meta.js": [
+   "c2ea5aab7970615d4d4f6b706d1d974fcabbddb9",
+   "support"
+  ],
   "infrastructure/server/secure-context.https.any.js": [
    "6f246bdc6d67a92a6518870542c20d2f8b2b5f5d",
    "testharness"
@@ -373463,10 +373758,22 @@
    "17413896d6281553091cf2c369c29de42d450962",
    "support"
   ],
+  "interfaces/mediacapture-fromelement.idl": [
+   "501b9ce0b557e52c122a2bb7f3be1a3e360da512",
+   "support"
+  ],
+  "interfaces/mediacapture-image.idl": [
+   "22f1cdf8c2c07e72570786750f50168d0a5ba782",
+   "support"
+  ],
   "interfaces/mediacapture-main.idl": [
    "a2a5e12acdc863828532e28574ed4904f0b0b2b8",
    "support"
   ],
+  "interfaces/mediacapture-record.idl": [
+   "2af81807d578af4bfec67e58aeb17fa194bf83b4",
+   "support"
+  ],
   "interfaces/mediasession.idl": [
    "7cbe73f7f563ee45772bb466ce63e16a549548d3",
    "support"
@@ -373604,7 +373911,7 @@
    "support"
   ],
   "interfaces/webxr.idl": [
-   "cea1f5425969a98f261fa4173aba6ddb91ee5a8d",
+   "abc92e822310850493632eb1ee7183b6e859b78a",
    "support"
   ],
   "interfaces/xhr.idl": [
@@ -373900,7 +374207,7 @@
    "support"
   ],
   "magnetometer/META.yml": [
-   "939b04014d0d0c4818e330d4119ba6fdc9f7db58",
+   "f99b5f4f8bb9d631f1b55857512be56738801e6e",
    "support"
   ],
   "magnetometer/Magnetometer-disabled-by-feature-policy.https-expected.txt": [
@@ -374652,7 +374959,7 @@
    "support"
   ],
   "mediacapture-fromelement/idlharness.html": [
-   "c6b4b7ac4a8caa64fcf662a75ae746acf953c943",
+   "cbda24f01aad5bbcc75ce5e19df2979d3e2e9c3a",
    "testharness"
   ],
   "mediacapture-image/META.yml": [
@@ -374668,7 +374975,7 @@
    "support"
   ],
   "mediacapture-image/idlharness.html": [
-   "bdbb04fda38eacb634b40a12497501b0fe7f0384",
+   "69441fcf969ff3bd014ac6109c1f8b1a18a8ec54",
    "testharness"
   ],
   "mediacapture-record/BlobEvent-constructor.html": [
@@ -374688,7 +374995,7 @@
    "support"
   ],
   "mediacapture-record/idlharness.html": [
-   "b47e6c73bca3b00e2cd6c4fa5fd746abb803c99c",
+   "fade50f6800c09a97104c96c0b5d80b2094455b6",
    "testharness"
   ],
   "mediacapture-streams/GUM-api.https.html": [
@@ -374740,11 +375047,11 @@
    "testharness"
   ],
   "mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt": [
-   "296328da85a5eb016d8b6db9cffe315520e27d31",
+   "1f510d6f699b3b1f0f80cc844fe69a2955083608",
    "support"
   ],
   "mediacapture-streams/MediaDevices-IDL-enumerateDevices.html": [
-   "cea6395d985eadd8340a4f3d64df2bb266a7f793",
+   "7d47f11a93d68c886612de8ac6847194fc02ad67",
    "testharness"
   ],
   "mediacapture-streams/MediaDevices-enumerateDevices.https.html": [
@@ -383332,7 +383639,7 @@
    "testharness"
   ],
   "orientation-sensor/META.yml": [
-   "939b04014d0d0c4818e330d4119ba6fdc9f7db58",
+   "f99b5f4f8bb9d631f1b55857512be56738801e6e",
    "support"
   ],
   "orientation-sensor/OWNERS": [
@@ -384027,8 +384334,8 @@
    "0a3ea0b532a1634008b776489b7409b348952d6f",
    "testharness"
   ],
-  "performance-timeline/performanceentry-tojson.html": [
-   "bc8a6f3fb13af9df11781a21b96f342e7d7ddf4e",
+  "performance-timeline/performanceentry-tojson.any.js": [
+   "dabdb522fde4513d92878f541dc652651829e0a2",
    "testharness"
   ],
   "performance-timeline/performanceobservers.js": [
@@ -384079,8 +384386,8 @@
    "e06354c2fd72bb868f8964cbf9ab393b629a3789",
    "testharness"
   ],
-  "performance-timeline/po-takeRecords.html": [
-   "e674c882ca331e48c92e6b9bf88d8b8a054316e4",
+  "performance-timeline/po-takeRecords.any.js": [
+   "b767e4ba133c33b1354768105472b4c8261224e9",
    "testharness"
   ],
   "performance-timeline/resources/square.png": [
@@ -384091,8 +384398,8 @@
    "6536127a1136f45cd59f62a9851fe61ceabe3d5b",
    "support"
   ],
-  "performance-timeline/webtiming-resolution.html": [
-   "75737bc80f456599ecdc247d0f0054d48f59e3ae",
+  "performance-timeline/webtiming-resolution.any.js": [
+   "17b1c06f9b31b0e77e1601f3f83e1759d66cc41b",
    "testharness"
   ],
   "performance-timeline/worker-with-performance-observer.html": [
@@ -394791,11 +395098,7 @@
    "10f756bbf749b7ad8f7c6eb4efe752ee79c44b4a",
    "testharness"
   ],
-  "server-timing/service_worker_idl-expected.txt": [
-   "ecc444813caba5ddc5baece8fdbaa6ca377a6d10",
-   "support"
-  ],
-  "server-timing/service_worker_idl.html": [
+  "server-timing/service_worker_idl.https.html": [
    "cb5ea3136399f88fb6c4e8071ad8e3b7ccebb242",
    "testharness"
   ],
@@ -395319,6 +395622,10 @@
    "8402c159967bb6e91903adc52e7d68c8d2443a72",
    "testharness"
   ],
+  "service-workers/service-worker/controller-with-no-fetch-event-handler.https.html": [
+   "c555850c4c7b56781532de9f10f935f337ac50dc",
+   "testharness"
+  ],
   "service-workers/service-worker/dedicated-worker-service-worker-interception.https-expected.txt": [
    "d1db0d4ebb3b70913dde139c68f7a747c257a045",
    "support"
@@ -395327,6 +395634,10 @@
    "f0eefc8b5ca0e26d87bddd7821bcfcb2a387d6f8",
    "testharness"
   ],
+  "service-workers/service-worker/detached-context.https-expected.txt": [
+   "640996d112e5be4253dd131b68b61c09645b2523",
+   "support"
+  ],
   "service-workers/service-worker/detached-context.https.html": [
    "81fc149311b54f92a2daedd81ffaba33fb88e831",
    "testharness"
@@ -395580,7 +395891,7 @@
    "testharness"
   ],
   "service-workers/service-worker/http-to-https-redirect-and-register.https.html": [
-   "d9e1cc801c3ee075ceb5a5e68ce662cfb2432965",
+   "a047873e7a25ed44f4ed953dc5993ac8dd08b9b8",
    "testharness"
   ],
   "service-workers/service-worker/immutable-prototype-serviceworker.https.html": [
@@ -395644,7 +395955,7 @@
    "testharness"
   ],
   "service-workers/service-worker/local-url-inherit-controller.https-expected.txt": [
-   "51d5ae95fb11dc104f21285cf1326f354b2f686e",
+   "5971cb67b8db3877cca183ab2cc95a18a202df3a",
    "support"
   ],
   "service-workers/service-worker/local-url-inherit-controller.https.html": [
@@ -396115,6 +396426,18 @@
    "1557f173e6cc5d1540ed9d78e8c9216b312fabb5",
    "support"
   ],
+  "service-workers/service-worker/resources/cors-approved.txt": [
+   "d58bf2436c1b4596c8725efbf332fa65f8387350",
+   "support"
+  ],
+  "service-workers/service-worker/resources/cors-approved.txt.headers": [
+   "3ddccda06ce83050ec70996773f2b595e28a7bea",
+   "support"
+  ],
+  "service-workers/service-worker/resources/cors-denied.txt": [
+   "b4802b6e97bfb4fe22a10b1f4f9bfedf882df51d",
+   "support"
+  ],
   "service-workers/service-worker/resources/dummy-shared-worker-interceptor.js": [
    "dd3d9a5f1c9cb6cbfcf018ba13118439dfa13eef",
    "support"
@@ -396452,7 +396775,7 @@
    "support"
   ],
   "service-workers/service-worker/resources/http-to-https-redirect-and-register-iframe.html": [
-   "b1a69bedbfbcb8f5b38d35f637f75f167d80118a",
+   "c1d36190219535c1daae941d7823d97a1ac7e056",
    "support"
   ],
   "service-workers/service-worker/resources/iframe-with-image.html": [
@@ -397499,6 +397822,14 @@
    "61f7da763fa4eb6f21077868caf0a07a4a9e44ae",
    "testharness"
   ],
+  "shadow-dom/directionality-001-ref.html": [
+   "818d966e37de205936380fd47605f13b5aa505d7",
+   "support"
+  ],
+  "shadow-dom/directionality-001.tentative.html": [
+   "763fd90e8ed83fb616379997735a5c283f0bd869",
+   "reftest"
+  ],
   "shadow-dom/event-composed-path-after-dom-mutation.html": [
    "69ea3efc8230a0ed31968f24379289c6691d77d1",
    "testharness"
@@ -399847,6 +400178,14 @@
    "b85e9086b134478e4c4b468cb19cc4e57aca06ae",
    "support"
   ],
+  "svg/pservers/reftests/radialgradient-basic-002-ref.svg": [
+   "65ce2b6056fcf008cdfeabf94a7e7314654731c5",
+   "support"
+  ],
+  "svg/pservers/reftests/radialgradient-basic-002.svg": [
+   "03751dba3c2dfc7b4d478879dc94878b0dffcc99",
+   "reftest"
+  ],
   "svg/scripted/text-attrs-dxdy-have-length.svg": [
    "91cd3e09332fa52800b05346d8c183bb599d7f46",
    "testharness"
@@ -399927,6 +400266,14 @@
    "42ecd7bc94a3379d920687c79c12e2d3c55b9e98",
    "testharness"
   ],
+  "svg/styling/required-properties-expected.txt": [
+   "263e806a9bfda4cb32f55e7ff01d157d85d53a05",
+   "support"
+  ],
+  "svg/styling/required-properties.svg": [
+   "b59f278e8303641d5654420c89da3d1e64995458",
+   "testharness"
+  ],
   "svg/svg-in-svg/svg-in-svg-circular-filter-reference-crash.html": [
    "2976a4812636c4515cc5e2c633b17c47bee392ab",
    "testharness"
@@ -403471,6 +403818,14 @@
    "7665873355c531e009824021a2b75daaf2dd6e3f",
    "testharness"
   ],
+  "webrtc-stats/META.yml": [
+   "fe059455b173c57e29cbcd0ce90e6e5b6c21afb3",
+   "support"
+  ],
+  "webrtc-stats/README.md": [
+   "927d32e9ebff034b34cf3bebde7955bbf3330e08",
+   "support"
+  ],
   "webrtc/META.yml": [
    "211af3b4837a5d879fc390270db420088b228807",
    "support"
@@ -403664,7 +404019,7 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-createDataChannel-expected.txt": [
-   "bf4f2f1415ed7d438beb694b510fca0ce8bdb592",
+   "cbd46d89210749a522add49049dc614894a27fdd",
    "support"
   ],
   "webrtc/RTCPeerConnection-createDataChannel.html": [
@@ -403720,7 +404075,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-getStats.https.html": [
-   "f0d783d2d2ebf9d303976a63981328f485bb21f7",
+   "f703ed5bf1fc434afd72f525e1639c7e4621e1b7",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-getTransceivers-expected.txt": [
@@ -403732,7 +404087,7 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-helper.js": [
-   "481c2c11f030f30fdc5c919c72e971e8bae48228",
+   "e25c8f69e6a9c9b5c565d1375d7bb6dd210f4784",
    "support"
   ],
   "webrtc/RTCPeerConnection-iceConnectionState-expected.txt": [
@@ -403788,7 +404143,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-removeTrack.https.html": [
-   "dfd8c24034da48944eb5c5fe805f940c5fc5a282",
+   "0cc7f4a5694e69e9e604fda5849c0b81f360db7d",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt": [
@@ -404128,7 +404483,7 @@
    "support"
   ],
   "webrtc/interfaces.https.html": [
-   "ef5a449587001f2bdfe82dad68920972f2aeafb1",
+   "e66dc8812ea38e216c4483dbb3c7814574c39653",
    "testharness"
   ],
   "webrtc/no-media-call.html": [
@@ -408556,7 +408911,7 @@
    "support"
   ],
   "webxr/interfaces.https-expected.txt": [
-   "c5671a172cff81a9c539caaa89df5f729ade2058",
+   "61c3134ea7352340f3eaa5ccc78701a64bd1d201",
    "support"
   ],
   "webxr/interfaces.https.html": [
@@ -408568,7 +408923,7 @@
    "support"
   ],
   "webxr/resources/webxr_util.js": [
-   "df6490ff3370ea580015f6b02ef5ec7ef2bb1e2b",
+   "e8e9631d39b75b8e01a583636de765bc9c81dcd1",
    "support"
   ],
   "webxr/webxr_availability.http.sub.html": [
@@ -409323,10 +409678,14 @@
    "309df42ef9329addc1fc59e2d3c0443454e14ad7",
    "testharness"
   ],
-  "workers/modules/dedicated-worker-import.html": [
-   "0b839e87ae98ad1abf32216a2086334cbc011ac0",
+  "workers/modules/dedicated-worker-import.any.js": [
+   "8a3a5bdcf6034d99cb244cc6ff36ada8f422ef37",
    "testharness"
   ],
+  "workers/modules/dedicated-worker-import.any.worker-expected.txt": [
+   "7297d62a2bf3dcda91bfdc1b80c939fcf96f4f44",
+   "support"
+  ],
   "workers/modules/dedicated-worker-options-credentials.html": [
    "f182ac364e933ce744b18c0ca6e03ae975a883a3",
    "testharness"
@@ -409459,6 +409818,46 @@
    "4f3e18270ff312e53a8ccb6dacfd7af80e5355e4",
    "testharness"
   ],
+  "workers/nested_worker_close_from_parent_worker-expected.txt": [
+   "e2fe03ce719b850154da9fb33fd81241260fadea",
+   "support"
+  ],
+  "workers/nested_worker_close_from_parent_worker.html": [
+   "2224e949cc23fd7741d0372d2876c5128c5005df",
+   "testharness"
+  ],
+  "workers/nested_worker_close_self.worker-expected.txt": [
+   "d80d980c6f55e9b286c8ee1ddfbfedbb513df64e",
+   "support"
+  ],
+  "workers/nested_worker_close_self.worker.js": [
+   "70714124e09615d7f4756ecca18789e7e981a524",
+   "testharness"
+  ],
+  "workers/nested_worker_importScripts.worker-expected.txt": [
+   "3a42c56315a45e86f10a9681b7956ac0a9c7faf1",
+   "support"
+  ],
+  "workers/nested_worker_importScripts.worker.js": [
+   "6409ab5cfc9ffd1db51a1ed1cccac90e8bd1c68e",
+   "testharness"
+  ],
+  "workers/nested_worker_sync_xhr.worker-expected.txt": [
+   "7dca8999ffad761c24e041716fd03c33ed3182cf",
+   "support"
+  ],
+  "workers/nested_worker_sync_xhr.worker.js": [
+   "637b556d0e1a0fdbb270df3f2215c100681ccc63",
+   "testharness"
+  ],
+  "workers/nested_worker_terminate_from_document-expected.txt": [
+   "ec44e040fca88cc848aeeebece6e96ada39f789d",
+   "support"
+  ],
+  "workers/nested_worker_terminate_from_document.html": [
+   "597512ecf36dc5536dcaf33671cc8b8dd4680f7a",
+   "testharness"
+  ],
   "workers/non-automated/application-cache-dedicated.html": [
    "73258fa7c4803f0d5035d5593354af41d3119c78",
    "support"
@@ -409823,6 +410222,10 @@
    "aa81cbafc77ccc9407cba3ac0bd4498e5076bf2b",
    "support"
   ],
+  "workers/support/parent_of_nested_worker.js": [
+   "18710328994ab49eed94453068d1e56c6a7313f1",
+   "support"
+  ],
   "workers/support/sandboxed-tests.html": [
    "89547c85b03f401be7cfc0c29251d5bc55236e44",
    "support"
@@ -409831,6 +410234,14 @@
    "671ecb263ceb15ca28ef9cfc2ee6efa6e08a70fb",
    "support"
   ],
+  "workers/support/sync_xhr.js": [
+   "e6ba3a7274b17ed3e8f936a2792fb08c148d9fd6",
+   "support"
+  ],
+  "workers/support/sync_xhr_target.xml": [
+   "abdd02de96974a9140bd74862e0b1b581da79bfd",
+   "support"
+  ],
   "workers/worker-from-blob-url.window.js": [
    "173e62999ab5556c2b1f0b587473c54683555f94",
    "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/META.yml b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/META.yml
index ecdfdc3..2eeea5b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/META.yml
@@ -4,4 +4,4 @@
   - riju
   - Honry
   - alexshalamov
-  - pozdnyakov
+  - rakuco
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/console-count-logging-manual.html b/third_party/WebKit/LayoutTests/external/wpt/console/console-count-logging-manual.html
index 4cd430e..640729f1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/console/console-count-logging-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/console/console-count-logging-manual.html
@@ -7,7 +7,7 @@
 <link rel="help" href="https://console.spec.whatwg.org/#count">
 </head>
 <body>
-<p>Open the console inside the developer tools. It should contain four lines whose contents are:</p>
+<p>Open the console inside the developer tools. It should contain four entries whose contents are:</p>
 <p><code>default: 1</code></p>
 <p><code>default: 2</code></p>
 <p><code>default: 3</code></p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/console-countReset-logging-manual.html b/third_party/WebKit/LayoutTests/external/wpt/console/console-countReset-logging-manual.html
index e2ed2dd..62122fb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/console/console-countReset-logging-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/console/console-countReset-logging-manual.html
@@ -7,7 +7,7 @@
 <link rel="help" href="https://console.spec.whatwg.org/#countReset">
 </head>
 <body>
-<p>Open the console inside the developer tools. It should contain lines whose contents are:</p>
+<p>Open the console inside the developer tools. It should contain entries whose contents are:</p>
 <p><code>default: 1</code></p>
 <p><code>default: 1</code></p>
 <p><code>default: 1</code></p>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/console-number-format-specifiers-symbol-manual.html b/third_party/WebKit/LayoutTests/external/wpt/console/console-number-format-specifiers-symbol-manual.html
index 4fb65fa..f77b84e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/console/console-number-format-specifiers-symbol-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/console/console-number-format-specifiers-symbol-manual.html
@@ -7,7 +7,7 @@
 <link rel="help" href="https://console.spec.whatwg.org/#formatter">
 </head>
 <body>
-<p>Open the console inside the developer tools. It should contain 15 lines, each of which are:</p>
+<p>Open the console inside the developer tools. It should contain 15 entries, each of which are:</p>
 <p><code>NaN</code></p>
 
 <script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/console/console-string-format-specifier-symbol-manual.html b/third_party/WebKit/LayoutTests/external/wpt/console/console-string-format-specifier-symbol-manual.html
index 5988b14..3a1b93f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/console/console-string-format-specifier-symbol-manual.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/console/console-string-format-specifier-symbol-manual.html
@@ -7,7 +7,7 @@
 <link rel="help" href="https://console.spec.whatwg.org/#formatter">
 </head>
 <body>
-<p>Open the console inside the developer tools. It should contain five lines, each of which are:</p>
+<p>Open the console inside the developer tools. It should contain five entries, each of which are:</p>
 <p><code>Symbol(description)</code></p>
 
 <script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/test_font_feature_values_parsing.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/test_font_feature_values_parsing.html
index f5c03c1..7a5844d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/test_font_feature_values_parsing.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/test_font_feature_values_parsing.html
@@ -4,7 +4,7 @@
   <meta charset=utf-8>
   <title>@font-feature-values rule parsing tests</title>
   <link rel="author" title="John Daggett" href="mailto:jdaggett@mozilla.com">
-  <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-feature-values" />
+  <link rel="help" href="http://www.w3.org/TR/css-fonts-4/#font-feature-values" />
   <meta name="assert" content="tests that valid @font-feature-values rules parse and invalid ones don't" />
   <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=549861 -->
   <script type="text/javascript" src="/resources/testharness.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-directionality-001.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-directionality-001.tentative.html
new file mode 100644
index 0000000..7070d2a1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-directionality-001.tentative.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>CSS Test: directionality propagation in Shadow DOM.</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://html.spec.whatwg.org/#the-dir-attribute">
+<link rel="help" href="https://github.com/whatwg/html/issues/3699">
+<link rel="match" href="reference/green-box.html">
+<style>
+  div { width: 100px; }
+</style>
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<div id="host1"></div>
+<div id="host2" dir="rtl"></div>
+<div id="host3"></div>
+<div id="host4" dir="rtl"></div>
+<script>
+  host1.attachShadow({ mode: "open" }).innerHTML = `
+    <style>:dir(ltr) { background: green; height: 25px; }</style>
+    <div></div>
+  `;
+  host2.attachShadow({ mode: "open" }).innerHTML = `
+    <style>:dir(rtl) { background: green; height: 25px; }</style>
+    <div></div>
+  `;
+  host3.attachShadow({ mode: "open" }).innerHTML = `
+    <style>:dir(rtl) { background: green; height: 25px; }</style>
+    <div></div>
+  `;
+  host4.attachShadow({ mode: "open" }).innerHTML = `
+    <style>span:dir(ltr) { display: block; background: green; height: 25px; }</style>
+    <div dir="ltr"><span></span></div>
+  `;
+  document.body.offsetTop;
+  host3.setAttribute("dir", "rtl");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-directionality-002.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-directionality-002.tentative.html
new file mode 100644
index 0000000..6aba124
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-scoping/shadow-directionality-002.tentative.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>CSS Test: directionality propagation in Shadow DOM, appending a shadow host.</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://html.spec.whatwg.org/#the-dir-attribute">
+<link rel="help" href="https://github.com/whatwg/html/issues/3699">
+<link rel="match" href="reference/green-box.html">
+<p>Test passes if you see a single 100px by 100px green box below.</p>
+<style>
+  div { width: 100px; }
+</style>
+<div id="host-parent" dir="rtl"></div>
+<script>
+  let host = document.createElement("div");
+  host.attachShadow({ mode: "open" }).innerHTML = `
+    <style>:dir(rtl) { background: green; height: 100px; width: 100px; }</style>
+    <div></div>
+  `;
+  document.getElementById("host-parent").appendChild(host);
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt
index 7af2b8a..35c11f0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree-expected.txt
@@ -1,6 +1,7 @@
 This is a testharness.js-based test.
 PASS getComputedStyle returns no style for detached element
 FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) assert_true: expected true got false
+FAIL getComputedStyle returns no style for element in non-rendered iframe (display: none) from iframe's window assert_true: expected true got false
 FAIL getComputedStyle returns no style for element outside the flat tree assert_true: expected true got false
 FAIL getComputedStyle returns no style for descendant outside the flat tree assert_true: expected true got false
 PASS getComputedStyle returns no style for shadow tree outside of flattened tree
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree.html b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree.html
index 1cbb92a4..4f59ccd 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/getComputedStyle-detached-subtree.html
@@ -12,10 +12,10 @@
 </div>
 <iframe srcdoc="<html></html>" style="display: none"></iframe>
 <script>
-function testNoComputedStyle(element, description) {
+function testNoComputedStyle(element, description, global) {
   test(function() {
     assert_true(!!element);
-    let style = getComputedStyle(element);
+    let style = (global ? global : window).getComputedStyle(element);
     assert_true(!!style);
     assert_true(style.length === 0);
     assert_equals(style.color, "");
@@ -28,6 +28,10 @@
 testNoComputedStyle(document.querySelector('iframe').contentDocument.documentElement,
                     "element in non-rendered iframe (display: none)");
 
+testNoComputedStyle(document.querySelector('iframe').contentDocument.documentElement,
+                    "element in non-rendered iframe (display: none) from iframe's window",
+                    document.querySelector('iframe').contentWindow);
+
 host.attachShadow({ mode: "open" });
 testNoComputedStyle(document.getElementById('non-slotted'),
                     "element outside the flat tree");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/META.yml b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/META.yml
index f0d3b8e1..e2bef0a1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/META.yml
@@ -3,5 +3,5 @@
   - dontcallmedom
   - riju
   - alexshalamov
-  - pozdnyakov
+  - rakuco
   - Honry
diff --git a/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/META.yml b/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/META.yml
index c5511ef..447e8b0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/geolocation-sensor/META.yml
@@ -1,3 +1,4 @@
 suggested_reviewers:
   - anssiko
   - Honry
+  - rakuco
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/META.yml b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/META.yml
index ecdfdc3..2eeea5b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/META.yml
@@ -4,4 +4,4 @@
   - riju
   - Honry
   - alexshalamov
-  - pozdnyakov
+  - rakuco
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.any-expected.txt
new file mode 100644
index 0000000..d71e2c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.any-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL order of scripts assert_array_equals: value is undefined, expected array
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.any.js b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.any.js
new file mode 100644
index 0000000..20f67847
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.any.js
@@ -0,0 +1,10 @@
+// META: global=window,dedicatedworker,sharedworker
+// META: script=resources/expect-seen-testharness.js
+// META: timeout=long
+// META: title=foo
+// META: script=resources/expect-global.js
+// META: script=resources/expect-title-meta.js
+
+test(() => {
+  assert_array_equals(scripts, ['expect-seen-testharness.js', 'expect-global.js', 'expect-title-meta.js']);
+}, "order of scripts");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.window-expected.txt
new file mode 100644
index 0000000..d71e2c6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.window-expected.txt
@@ -0,0 +1,4 @@
+This is a testharness.js-based test.
+FAIL order of scripts assert_array_equals: value is undefined, expected array
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.window.js b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.window.js
new file mode 100644
index 0000000..ec28480
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/order-of-metas.window.js
@@ -0,0 +1,8 @@
+// META: script=resources/expect-seen-testharness.js
+// META: timeout=long
+// META: title=foo
+// META: script=resources/expect-title-meta.js
+
+test(() => {
+  assert_array_equals(scripts, ['expect-seen-testharness.js', 'expect-title-meta.js']);
+}, "order of scripts");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-global.js b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-global.js
new file mode 100644
index 0000000..63d4944
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-global.js
@@ -0,0 +1,5 @@
+test(() => {
+  assert_true('GLOBAL' in self);
+}, 'GLOBAL exists');
+
+scripts.push('expect-global.js');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-seen-testharness.js b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-seen-testharness.js
new file mode 100644
index 0000000..29af1fc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-seen-testharness.js
@@ -0,0 +1,5 @@
+test(() => {
+  assert_true('add_completion_callback' in self);
+}, 'add_completion_callback exists');
+
+var scripts = ['expect-seen-testharness.js'];
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-title-meta.js b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-title-meta.js
new file mode 100644
index 0000000..d17588a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/server/resources/expect-title-meta.js
@@ -0,0 +1,11 @@
+if (!self.GLOBAL || self.GLOBAL.isWindow()) {
+  test(() => {
+    assert_equals(document.title, "foo");
+  }, '<title> exists');
+
+  test(() => {
+    assert_equals(document.querySelectorAll("meta[name=timeout][content=long]").length, 1);
+  }, '<meta name=timeout> exists');
+}
+
+scripts.push('expect-title-meta.js');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-fromelement.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-fromelement.idl
new file mode 100644
index 0000000..7b35de99
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-fromelement.idl
@@ -0,0 +1,16 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "Media Capture from DOM Elements" spec.
+// See: https://w3c.github.io/mediacapture-fromelement/
+
+partial interface HTMLMediaElement {
+    MediaStream captureStream();
+};
+partial interface HTMLCanvasElement {
+    MediaStream captureStream(optional double frameRequestRate);
+};
+[Exposed=Window]
+interface CanvasCaptureMediaStreamTrack : MediaStreamTrack {
+    readonly attribute HTMLCanvasElement canvas;
+    void requestFrame();
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-image.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-image.idl
new file mode 100644
index 0000000..3aeb6eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-image.idl
@@ -0,0 +1,150 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the MediaStream Image Capture spec.
+// See https://w3c.github.io/mediacapture-image/
+
+[Exposed=Window, Constructor(MediaStreamTrack videoTrack)]
+interface ImageCapture {
+   Promise<Blob>              takePhoto(optional PhotoSettings photoSettings);
+   Promise<PhotoCapabilities> getPhotoCapabilities();
+   Promise<PhotoSettings>     getPhotoSettings();
+
+   Promise<ImageBitmap>       grabFrame();
+
+   readonly attribute MediaStreamTrack track;
+};
+
+[Exposed=Window] interface PhotoCapabilities {
+  readonly attribute RedEyeReduction            redEyeReduction;
+  readonly attribute MediaSettingsRange         imageHeight;
+  readonly attribute MediaSettingsRange         imageWidth;
+  readonly attribute FrozenArray<FillLightMode> fillLightMode;
+};
+
+dictionary PhotoSettings {
+  FillLightMode   fillLightMode;
+  double          imageHeight;
+  double          imageWidth;
+  boolean         redEyeReduction;
+};
+
+[Exposed=Window] interface MediaSettingsRange {
+    readonly attribute double max;
+    readonly attribute double min;
+    readonly attribute double step;
+};
+
+enum RedEyeReduction {
+  "never",
+  "always",
+  "controllable"
+};
+
+enum FillLightMode {
+  "auto",
+  "off",
+  "flash"
+};
+
+partial dictionary MediaTrackSupportedConstraints {
+  boolean whiteBalanceMode = true;
+  boolean exposureMode = true;
+  boolean focusMode = true;
+  boolean pointsOfInterest = true;
+
+  boolean exposureCompensation = true;
+  boolean exposureTime = true;
+  boolean colorTemperature = true;
+  boolean iso = true;
+
+  boolean brightness = true;
+  boolean contrast = true;
+  boolean saturation = true;
+  boolean sharpness = true;
+  boolean focusDistance = true;
+  boolean zoom = true;
+  boolean torch = true;
+};
+
+partial dictionary MediaTrackCapabilities {
+  sequence<DOMString>  whiteBalanceMode;
+  sequence<DOMString>  exposureMode;
+  sequence<DOMString>  focusMode;
+
+  MediaSettingsRange   exposureCompensation;
+  MediaSettingsRange   exposureTime;
+  MediaSettingsRange   colorTemperature;
+  MediaSettingsRange   iso;
+
+  MediaSettingsRange   brightness;
+  MediaSettingsRange   contrast;
+  MediaSettingsRange   saturation;
+  MediaSettingsRange   sharpness;
+
+  MediaSettingsRange   focusDistance;
+  MediaSettingsRange   zoom;
+
+  boolean              torch;
+};
+
+partial dictionary MediaTrackConstraintSet {
+  ConstrainDOMString whiteBalanceMode;
+  ConstrainDOMString exposureMode;
+  ConstrainDOMString focusMode;
+  ConstrainPoint2D   pointsOfInterest;
+
+  ConstrainDouble    exposureCompensation;
+  ConstrainDouble    exposureTime;
+  ConstrainDouble    colorTemperature;
+  ConstrainDouble    iso;
+
+  ConstrainDouble    brightness;
+  ConstrainDouble    contrast;
+  ConstrainDouble    saturation;
+  ConstrainDouble    sharpness;
+
+  ConstrainDouble    focusDistance;
+  ConstrainDouble    zoom;
+
+  ConstrainBoolean   torch;
+};
+
+partial dictionary MediaTrackSettings {
+  DOMString         whiteBalanceMode;
+  DOMString         exposureMode;
+  DOMString         focusMode;
+  sequence<Point2D> pointsOfInterest;
+
+  double            exposureCompensation;
+  double            exposureTime;
+  double            colorTemperature;
+  double            iso;
+
+  double            brightness;
+  double            contrast;
+  double            saturation;
+  double            sharpness;
+
+  double            focusDistance;
+  double            zoom;
+
+  boolean           torch;
+};
+
+dictionary ConstrainPoint2DParameters {
+  sequence<Point2D> exact;
+  sequence<Point2D> ideal;
+};
+
+typedef (sequence<Point2D> or ConstrainPoint2DParameters) ConstrainPoint2D;
+
+enum MeteringMode {
+  "none",
+  "manual",
+  "single-shot",
+  "continuous"
+};
+
+dictionary Point2D {
+  double x = 0.0;
+  double y = 0.0;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-record.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-record.idl
new file mode 100644
index 0000000..d1a2f21
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/mediacapture-record.idl
@@ -0,0 +1,60 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the MediaStream Recording spec.
+// See https://w3c.github.io/mediacapture-record/
+
+[Exposed=Window,
+ Constructor(MediaStream stream, optional MediaRecorderOptions options)]
+interface MediaRecorder : EventTarget {
+  readonly attribute MediaStream stream;
+  readonly attribute DOMString mimeType;
+  readonly attribute RecordingState state;
+  attribute EventHandler onstart;
+  attribute EventHandler onstop;
+  attribute EventHandler ondataavailable;
+  attribute EventHandler onpause;
+  attribute EventHandler onresume;
+  attribute EventHandler onerror;
+  readonly attribute unsigned long videoBitsPerSecond;
+  readonly attribute unsigned long audioBitsPerSecond;
+
+  void start(optional long timeslice);
+  void stop();
+  void pause();
+  void resume();
+  void requestData();
+
+  static boolean isTypeSupported(DOMString type);
+};
+
+dictionary MediaRecorderOptions {
+  DOMString mimeType;
+  unsigned long audioBitsPerSecond;
+  unsigned long videoBitsPerSecond;
+  unsigned long bitsPerSecond;
+};
+
+enum RecordingState {
+  "inactive",
+  "recording",
+  "paused"
+};
+
+[Exposed=Window, Constructor(DOMString type, BlobEventInit eventInitDict)]
+interface BlobEvent : Event {
+  [SameObject] readonly attribute Blob data;
+  readonly attribute DOMHighResTimeStamp timecode;
+};
+
+dictionary BlobEventInit {
+  required Blob data;
+  DOMHighResTimeStamp timecode;
+};
+
+dictionary MediaRecorderErrorEventInit : EventInit {
+  required DOMException error;
+};
+
+[Exposed=Window, Constructor(DOMString type, MediaRecorderErrorEventInit eventInitDict)]
+interface MediaRecorderErrorEvent : Event {
+  [SameObject] readonly attribute DOMException error;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/META.yml b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/META.yml
index ecdfdc3..2eeea5b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/META.yml
@@ -4,4 +4,4 @@
   - riju
   - Honry
   - alexshalamov
-  - pozdnyakov
+  - rakuco
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.html
index 500720b..2403d8a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness.html
@@ -13,33 +13,16 @@
   <media id='media' width=10 height=10/>
   <canvas id='canvas' width=10 height=10/>
 
-  <pre id="idl" style="display: none">
-    // https://w3c.github.io/mediacapture-fromelement/
-
-    partial interface HTMLMediaElement {
-        MediaStream captureStream();
-    };
-
-    partial interface HTMLCanvasElement {
-        MediaStream captureStream(optional double frameRequestRate);
-    };
-
-    interface CanvasCaptureMediaStreamTrack : MediaStreamTrack {
-        readonly attribute HTMLCanvasElement canvas;
-        void requestFrame();
-    };
-
-  </pre>
   <script>
     'use strict';
 
     promise_test(async () => {
-      const main = await fetch('/interfaces/mediacapture-main.idl').then(r => r.text());
-      const html = await fetch('/interfaces/html.idl').then(r => r.text());
-      const dom = await fetch('/interfaces/dom.idl').then(r => r.text());
+      const srcs = ['mediacapture-fromelement', 'mediacapture-main', 'html', 'dom'];
+      const [idl, main, html, dom] = await Promise.all(
+        srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
 
       var idl_array = new IdlArray();
-      idl_array.add_idls(document.getElementById("idl").textContent);
+      idl_array.add_idls(idl);
       idl_array.add_dependency_idls(main);
       idl_array.add_dependency_idls(html);
       idl_array.add_dependency_idls(dom);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.html
index 46e82a0..4b19b58 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-image/idlharness.html
@@ -13,158 +13,13 @@
 <body>
   <canvas id='canvas' width=10 height=10/>
 
-  <pre id="idl" style="display: none">
-    // https://w3c.github.io/mediacapture-image
-
-    [Constructor(MediaStreamTrack videoTrack)]
-    interface ImageCapture {
-       Promise<Blob>              takePhoto(optional PhotoSettings photoSettings);
-       Promise<PhotoCapabilities> getPhotoCapabilities();
-
-       Promise<ImageBitmap>       grabFrame();
-
-       readonly attribute MediaStreamTrack track;
-    };
-
-    interface PhotoCapabilities {
-      readonly attribute RedEyeReduction            redEyeReduction;
-      readonly attribute MediaSettingsRange         imageHeight;
-      readonly attribute MediaSettingsRange         imageWidth;
-      readonly attribute FrozenArray<FillLightMode> fillLightMode;
-    };
-
-    dictionary PhotoSettings {
-      FillLightMode   fillLightMode;
-      double          imageHeight;
-      double          imageWidth;
-      boolean         redEyeReduction;
-    };
-
-    interface MediaSettingsRange {
-        readonly attribute double max;
-        readonly attribute double min;
-        readonly attribute double step;
-    };
-
-    enum RedEyeReduction {
-      "never",
-      "always",
-      "controllable",
-    };
-
-    enum FillLightMode {
-      "auto",
-      "off",
-      "flash",
-    };
-
-    // Partial dictionaries are unsupported, see
-    // https://github.com/w3c/testharness.js/issues/84
-
-    partial dictionary MediaTrackSupportedConstraints {
-      boolean whiteBalanceMode = true;
-      boolean exposureMode = true;
-      boolean focusMode = true;
-      boolean pointsOfInterest = true;
-
-      boolean exposureCompensation = true;
-      boolean colorTemperature = true;
-      boolean iso = true;
-
-      boolean brightness = true;
-      boolean contrast = true;
-      boolean saturation = true;
-      boolean sharpness = true;
-      boolean zoom = true;
-      boolean torch = true;
-    };
-
-    partial dictionary MediaTrackCapabilities {
-      sequence<DOMString>  whiteBalanceMode;
-      sequence<DOMString>  exposureMode;
-      sequence<DOMString>  focusMode;
-
-      MediaSettingsRange   exposureCompensation;
-      MediaSettingsRange   colorTemperature;
-      MediaSettingsRange   iso;
-
-      MediaSettingsRange   brightness;
-      MediaSettingsRange   contrast;
-      MediaSettingsRange   saturation;
-      MediaSettingsRange   sharpness;
-
-      MediaSettingsRange   zoom;
-
-      boolean              torch;
-    };
-
-    partial dictionary MediaTrackConstraintSet {
-      ConstrainDOMString whiteBalanceMode;
-      ConstrainDOMString exposureMode;
-      ConstrainDOMString focusMode;
-      ConstrainPoint2D   pointsOfInterest;
-
-      ConstrainDouble    exposureCompensation;
-      ConstrainDouble    colorTemperature;
-      ConstrainDouble    iso;
-
-      ConstrainDouble    brightness;
-      ConstrainDouble    contrast;
-      ConstrainDouble    saturation;
-      ConstrainDouble    sharpness;
-
-      ConstrainDouble    zoom;
-
-      ConstrainBoolean   torch;
-    };
-
-    partial dictionary MediaTrackSettings {
-      DOMString         whiteBalanceMode;
-      DOMString         exposureMode;
-      DOMString         focusMode;
-      sequence<Point2D> pointsOfInterest;
-
-      double            exposureCompensation;
-      double            colorTemperature;
-      double            iso;
-
-      double            brightness;
-      double            contrast;
-      double            saturation;
-      double            sharpness;
-
-      double            zoom;
-
-      boolean           torch;
-    };
-
-    dictionary ConstrainPoint2DParameters {
-      sequence<Point2D> exact;
-      sequence<Point2D> ideal;
-    };
-
-    typedef (sequence<Point2D> or ConstrainPoint2DParameters) ConstrainPoint2D;
-
-    enum MeteringMode {
-      "none",
-      "manual",
-      "single-shot",
-      "continuous"
-    };
-
-    dictionary Point2D {
-      double x = 0.0;
-      double y = 0.0;
-    };
-
-  </pre>
 <script>
   'use strict';
 
   promise_test(async () => {
-    const main = await fetch('/interfaces/mediacapture-main.idl').then(r => r.text());
-    const html = await fetch('/interfaces/html.idl').then(r => r.text());
-    const dom = await fetch('/interfaces/dom.idl').then(r => r.text());
+    const srcs = ['mediacapture-image', 'mediacapture-main', 'html', 'dom'];
+    const [idl, main, html, dom] = await Promise.all(
+      srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
 
     var canvas = document.getElementById('canvas');
     var context = canvas.getContext("2d");
@@ -173,7 +28,7 @@
     var track = canvas.captureStream().getVideoTracks()[0];
 
     var idl_array = new IdlArray();
-    idl_array.add_idls(document.getElementById("idl").textContent);
+    idl_array.add_idls(idl);
     idl_array.add_dependency_idls(main);
     idl_array.add_dependency_idls(html);
     idl_array.add_dependency_idls(dom);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-record/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-record/idlharness.html
index 01cc1511..8e4ba3c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-record/idlharness.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-record/idlharness.html
@@ -12,72 +12,11 @@
 </head>
 <body>
   <canvas id='canvas' width=10 height=10/>
-
-  <pre id="idl" style="display: none">
-    // https://w3c.github.io/mediacapture-record/MediaRecorder.html
-
-    [Constructor(MediaStream stream, optional MediaRecorderOptions options)]
-    interface MediaRecorder : EventTarget {
-      readonly attribute MediaStream stream;
-      readonly attribute DOMString mimeType;
-      readonly attribute RecordingState state;
-      attribute EventHandler onstart;
-      attribute EventHandler onstop;
-      attribute EventHandler ondataavailable;
-      attribute EventHandler onpause;
-      attribute EventHandler onresume;
-      attribute EventHandler onerror;
-      readonly attribute unsigned long videoBitsPerSecond;
-      readonly attribute unsigned long audioBitsPerSecond;
-
-      void start(optional long timeslice);
-      void stop();
-      void pause();
-      void resume();
-      void requestData();
-
-      static boolean isTypeSupported(DOMString type);
-    };
-
-    dictionary MediaRecorderOptions {
-      DOMString mimeType;
-      unsigned long audioBitsPerSecond;
-      unsigned long videoBitsPerSecond;
-      unsigned long bitsPerSecond;
-    };
-
-    enum RecordingState {
-      "inactive",
-      "recording",
-      "paused"
-    };
-
-    [Constructor(DOMString type, BlobEventInit eventInitDict)]
-    interface BlobEvent : Event {
-      [SameObject] readonly attribute Blob data;
-      readonly attribute DOMHighResTimeStamp timecode;
-    };
-
-    dictionary BlobEventInit {
-      required Blob data;
-      DOMHighResTimeStamp timecode;
-    };
-
-    dictionary MediaRecorderErrorEventInit : EventInit {
-      required DOMException error;
-    };
-
-    [Exposed=Window, Constructor(DOMString type, MediaRecorderErrorEventInit eventInitDict)]
-    interface MediaRecorderErrorEvent : Event {
-      [SameObject] readonly attribute DOMException error;
-    };
-
-  </pre>
   <script>
-    promise_test(async function() {
-      const main = await fetch('/interfaces/mediacapture-main.idl').then(r => r.text());
-      const html = await fetch('/interfaces/html.idl').then(r => r.text());
-      const dom = await fetch('/interfaces/dom.idl').then(r => r.text());
+    promise_test(async () => {
+      const srcs = ['mediacapture-record', 'mediacapture-main', 'html', 'dom'];
+      const [idl, main, html, dom] = await Promise.all(
+          srcs.map(i => fetch(`/interfaces/${i}.idl`).then(r => r.text())));
 
       var canvas = document.getElementById('canvas');
       var context = canvas.getContext("2d");
@@ -86,7 +25,7 @@
       var stream = canvas.captureStream();
 
       var idl_array = new IdlArray();
-      idl_array.add_idls(document.getElementById("idl").textContent);
+      idl_array.add_idls(idl);
       idl_array.add_dependency_idls(main);
       idl_array.add_dependency_idls(html);
       idl_array.add_dependency_idls(dom);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
index 70cf1c48..686371c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
@@ -3,10 +3,6 @@
 PASS Test MediaDevices.enumerateDevices call and result. Types only.
 PASS Partial interface NavigatorUserMedia: original interface defined
 PASS Partial interface MediaDevices: original interface defined
-PASS Navigator interface: attribute mediaDevices
-PASS Unscopable handled correctly for mediaDevices property on Navigator
-PASS Navigator interface: operation getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback)
-PASS Unscopable handled correctly for getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback) on Navigator
 PASS MediaStream interface: existence and properties of interface object
 PASS MediaStream interface object length
 PASS MediaStream interface object name
@@ -136,5 +132,9 @@
 PASS MediaDeviceInfo interface: [object InputDeviceInfo] must inherit property "groupId" with the proper type
 PASS MediaDeviceInfo interface: [object InputDeviceInfo] must inherit property "toJSON()" with the proper type
 PASS Test default toJSON operation of InputDeviceInfo
+PASS Navigator interface: attribute mediaDevices
+PASS Unscopable handled correctly for mediaDevices property on Navigator
+PASS Navigator interface: operation getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback)
+PASS Unscopable handled correctly for getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback) on Navigator
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices.html
index 0d6c6c0..446ee15 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices.html
@@ -20,13 +20,15 @@
 <script>
   "use strict";
 
-  function doIdlTest([dom, idlText]) {
-    const MDI_idl = new IdlArray();
+  promise_test(async () => {
+    const idl = await fetch(`/interfaces/mediacapture-main.idl`).then(r => r.text());
+    const dom = await fetch(`/interfaces/dom.idl`).then(r => r.text());
+    const html = await fetch(`/interfaces/html.idl`).then(r => r.text());
 
-    MDI_idl.add_untested_idls(dom, { only: ['Event', 'EventInit'] });
-    MDI_idl.add_untested_idls("interface EventTarget {};");
-    MDI_idl.add_untested_idls("interface Navigator {};");
-    MDI_idl.add_idls(idlText);
+    const MDI_idl = new IdlArray();
+    MDI_idl.add_idls(idl);
+    MDI_idl.add_dependency_idls(html);
+    MDI_idl.add_dependency_idls(dom);
 
     assert_true(undefined !== navigator.mediaDevices.enumerateDevices,
       "navigator.mediaDevices.enumerateDevices exists");
@@ -56,16 +58,6 @@
 
       MDI_idl.test();
     });
-  }
-
-  promise_test(() => {
-      return Promise.all(
-        [
-          '/interfaces/dom.idl',
-          '/interfaces/mediacapture-main.idl',
-        ].map(url => fetch(url).then(r => r.text())))
-      .then(doIdlTest);
-
   }, "Test MediaDevices.enumerateDevices call and result. Types only.");
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/META.yml b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/META.yml
index ecdfdc3..2eeea5b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/META.yml
+++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/META.yml
@@ -4,4 +4,4 @@
   - riju
   - Honry
   - alexshalamov
-  - pozdnyakov
+  - rakuco
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/performanceentry-tojson.html b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/performanceentry-tojson.any.js
similarity index 76%
rename from third_party/WebKit/LayoutTests/external/wpt/performance-timeline/performanceentry-tojson.html
rename to third_party/WebKit/LayoutTests/external/wpt/performance-timeline/performanceentry-tojson.any.js
index 8576872..44f0156 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/performanceentry-tojson.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/performanceentry-tojson.any.js
@@ -1,12 +1,3 @@
-<!doctype html>
-<html>
-<head>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-</head>
-<body>
-<script>
-
 test(() => {
   performance.mark('markName');
   performance.measure('measureName');
@@ -28,6 +19,3 @@
     }
   }
 }, 'Test toJSON() in PerformanceEntry');
-</script>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/po-takeRecords.html b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/po-takeRecords.any.js
similarity index 79%
rename from third_party/WebKit/LayoutTests/external/wpt/performance-timeline/po-takeRecords.html
rename to third_party/WebKit/LayoutTests/external/wpt/performance-timeline/po-takeRecords.any.js
index eb660f71..86ad397 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/po-takeRecords.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/po-takeRecords.any.js
@@ -1,11 +1,7 @@
-<!DOCTYPE HTML>
-<meta charset=utf-8>
-<title>PerformanceObserver: takeRecords</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="performanceobservers.js"></script>
-<script>
-  async_test(function (t) {
+// META: title=PerformanceObserver: takeRecords
+// META: script=performanceobservers.js
+
+async_test(function (t) {
     const observer = new PerformanceObserver(function (entryList, observer) {
       assert_unreached('This callback should not have been called.')
     });
@@ -36,4 +32,3 @@
     observer.disconnect();
     t.done();
   }, "Test PerformanceObserver's takeRecords()");
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/webtiming-resolution.html b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/webtiming-resolution.any.js
similarity index 80%
rename from third_party/WebKit/LayoutTests/external/wpt/performance-timeline/webtiming-resolution.html
rename to third_party/WebKit/LayoutTests/external/wpt/performance-timeline/webtiming-resolution.any.js
index 1723c29..4031388a3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/webtiming-resolution.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/webtiming-resolution.any.js
@@ -1,11 +1,3 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-</head>
-<body>
-<script>
 function testTimeResolution(highResTimeFunc, funcString) {
     test(() => {
         const t0 = highResTimeFunc();
@@ -30,6 +22,3 @@
 
 testTimeResolution(timeByPerformanceNow, 'performance.now()');
 testTimeResolution(timeByUserTiming, 'entry.startTime');
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html
new file mode 100644
index 0000000..7147c33
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Service Worker: controller without a fetch event handler</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/test-helpers.sub.js?pipe=sub"></script>
+<body>
+<script>
+let registration;
+let frame;
+const host_info = get_host_info();
+const remote_base_url =
+    new URL(`${host_info.HTTPS_REMOTE_ORIGIN}${base_path()}resources/`);
+
+promise_test(async t => {
+  const script = 'resources/empty.js'
+  const scope = 'resources/';
+
+  promise_test(async t => {
+    if (frame)
+      frame.remove();
+
+    if (registration)
+      await registration.unregister();
+  }, 'cleanup global state');
+
+  registration = await
+      service_worker_unregister_and_register(t, script, scope);
+  await wait_for_state(t, registration.installing, 'activated');
+  frame = await with_iframe(scope + 'blank.html');
+}, 'global setup');
+
+promise_test(async t => {
+    const url = new URL('cors-approved.txt', remote_base_url);
+    const response = await frame.contentWindow.fetch(url, {mode:'no-cors'});
+    const text = await response.text();
+    assert_equals(text, '');
+}, 'cross-origin request, no-cors mode');
+
+
+promise_test(async t => {
+    const url = new URL('cors-denied.txt', remote_base_url);
+    const response = frame.contentWindow.fetch(url);
+    await promise_rejects(t, new TypeError(), response);
+}, 'cross-origin request, cors denied');
+
+promise_test(async t => {
+    const url = new URL('cors-approved.txt', remote_base_url);
+    response = await frame.contentWindow.fetch(url);
+    let text = await response.text();
+    text = text.trim();
+    assert_equals(text, 'plaintext');
+}, 'cross-origin request, cors approved');
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-approved.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-approved.txt
new file mode 100644
index 0000000..1cd89bb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-approved.txt
@@ -0,0 +1 @@
+plaintext
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-approved.txt.headers b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-approved.txt.headers
new file mode 100644
index 0000000..f7985fd9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-approved.txt.headers
@@ -0,0 +1,3 @@
+Content-Type: text/plain
+Access-Control-Allow-Origin: *
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-denied.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-denied.txt
new file mode 100644
index 0000000..ff333bd9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/resources/cors-denied.txt
@@ -0,0 +1,2 @@
+this file is served without Access-Control-Allow-Origin headers so it should not
+be readable from cross-origin.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/shadow-dom/directionality-001-ref.html b/third_party/WebKit/LayoutTests/external/wpt/shadow-dom/directionality-001-ref.html
new file mode 100644
index 0000000..7a2eaeb8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/shadow-dom/directionality-001-ref.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<div dir="rtl"> 123 456 <span><span> 789 101112 </span></span></div>
+<div dir="rtl"> 123 456 <span dir="ltr"><span> 789 101112 </span></span></div>
+<div dir="rtl"> 123 456 <span><span> 789 101112 </span></span></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/shadow-dom/directionality-001.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/shadow-dom/directionality-001.tentative.html
new file mode 100644
index 0000000..d96926a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/shadow-dom/directionality-001.tentative.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Test: directionality propagation in Shadow DOM.</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://html.spec.whatwg.org/#the-dir-attribute">
+<link rel="help" href="https://github.com/whatwg/html/issues/3699">
+<link rel="match" href="directionality-001-ref.html">
+<div id="host0" dir="rtl"><span> 789 101112 </span></div>
+<div id="host1" dir="rtl"><span> 789 101112 </span></div>
+<div id="host2" dir="rtl"><span> 789 101112 </span></div>
+<script>
+  host0.attachShadow({mode: 'closed'}).innerHTML =
+    '<div> 123 456 <span><slot></slot></span></div>';
+
+  host1.attachShadow({mode: 'closed'}).innerHTML =
+    '<div> 123 456 <span dir="ltr"><slot></slot></span></div>';
+
+  host2.attachShadow({mode: 'closed'}).innerHTML =
+    '<div> 123 456 <span><slot dir="ltr"></slot></span></div>';
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/pservers/reftests/radialgradient-basic-002-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/pservers/reftests/radialgradient-basic-002-ref.svg
new file mode 100644
index 0000000..26f4f50
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/pservers/reftests/radialgradient-basic-002-ref.svg
@@ -0,0 +1,50 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>Radial gradient: Basic three stop gradient with 'fr'.</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+  </g>
+
+  <style id="test-font" type="text/css">
+    /* Standard Font (if needed). */
+    @font-face {
+      font-family: FreeSans;
+      src: url("../fonts/FreeSans.woff") format("woff");
+    }
+    text {
+      font-family: FreeSans, sans-serif;
+      text-anchor: middle;
+      fill: black;
+    }
+    #title {
+      font-size: 24px;
+    }
+    .label {
+      font-size: 18px;
+    }
+  </style>
+
+  <defs>
+    <radialGradient id="RadialGradient1" gradientUnits="userSpaceOnUse" cx="120" cy="240" fx="120" fy="240" r="100">
+      <stop style="stop-color:#0000ff" offset="50%"/>
+      <stop style="stop-color:#00ffff" offset="75%"/>
+      <stop style="stop-color:#ffff00" offset="100%"/>
+    </radialGradient>
+    <radialGradient id="RadialGradient2" gradientUnits="objectBoundingBox" cx="0.5" cy="0.5" rx="0.5" y2="0.5" r="0.5">
+      <stop style="stop-color:#0000ff" offset="50%"/>
+      <stop style="stop-color:#00ffff" offset="75%"/>
+      <stop style="stop-color:#ffff00" offset="100%"/>
+    </radialGradient>
+  </defs>
+
+  <g id="test-reference" font-size="16">
+    <rect x="20"  y="140" width="200" height="200" style="fill:url(#RadialGradient1)" />
+    <rect x="260" y="140" width="200" height="200" style="fill:url(#RadialGradient2)" />
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/pservers/reftests/radialgradient-basic-002.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/pservers/reftests/radialgradient-basic-002.svg
new file mode 100644
index 0000000..04d8d30
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/pservers/reftests/radialgradient-basic-002.svg
@@ -0,0 +1,53 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>Radial gradient: Basic three stop gradient with 'fr'.</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+    <html:link rel="help"
+          href="https://www.w3.org/TR/SVG2/pservers.html#RadialGradients"/>
+    <html:link rel="match"  href="radialgradient-basic-002-ref.svg" />
+  </g>
+
+  <style id="test-font" type="text/css">
+    /* Standard Font (if needed). */
+    @font-face {
+      font-family: FreeSans;
+      src: url("../fonts/FreeSans.woff") format("woff");
+    }
+    text {
+      font-family: FreeSans, sans-serif;
+      text-anchor: middle;
+      fill: black;
+    }
+    #title {
+      font-size: 24px;
+    }
+    .label {
+      font-size: 18px;
+    }
+  </style>
+
+  <defs>
+    <radialGradient id="RadialGradient1" gradientUnits="userSpaceOnUse" cx="120" cy="240" fx="120" fy="240" r="100" fr="50">
+      <stop style="stop-color:#0000ff" offset="0%"/>
+      <stop style="stop-color:#00ffff" offset="50%"/>
+      <stop style="stop-color:#ffff00" offset="100%"/>
+    </radialGradient>
+    <radialGradient id="RadialGradient2" gradientUnits="objectBoundingBox" cx="0.5" cy="0.5" rx="0.5" y2="0.5" r="0.5" fr="0.25">
+      <stop style="stop-color:#0000ff" offset="0%"/>
+      <stop style="stop-color:#00ffff" offset="50%"/>
+      <stop style="stop-color:#ffff00" offset="100%"/>
+    </radialGradient>
+  </defs>
+
+  <g id="test-body-content" font-size="16">
+    <rect x="20"  y="140" width="200" height="200" style="fill:url(#RadialGradient1)" />
+    <rect x="260" y="140" width="200" height="200" style="fill:url(#RadialGradient2)" />
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/styling/required-properties-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/svg/styling/required-properties-expected.txt
new file mode 100644
index 0000000..875660c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/styling/required-properties-expected.txt
@@ -0,0 +1,87 @@
+This is a testharness.js-based test.
+Found 83 tests; 79 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Property "alignment-baseline" is supported
+PASS Property "baseline-shift" is supported
+PASS Property "clip" is supported
+PASS Property "clip-path" is supported
+PASS Property "clip-rule" is supported
+PASS Property "color" is supported
+PASS Property "color-interpolation" is supported
+PASS Property "color-interpolation-filters" is supported
+PASS Property "color-rendering" is supported
+PASS Property "cursor" is supported
+PASS Property "direction" is supported
+PASS Property "display" is supported
+PASS Property "dominant-baseline" is supported
+PASS Property "fill" is supported
+PASS Property "fill-opacity" is supported
+PASS Property "fill-rule" is supported
+PASS Property "filter" is supported
+PASS Property "flood-color" is supported
+PASS Property "flood-opacity" is supported
+PASS Property "font" is supported
+PASS Property "font-family" is supported
+PASS Property "font-feature-settings" is supported
+PASS Property "font-kerning" is supported
+PASS Property "font-size" is supported
+PASS Property "font-size-adjust" is supported
+PASS Property "font-stretch" is supported
+PASS Property "font-style" is supported
+PASS Property "font-variant" is supported
+PASS Property "font-variant-caps" is supported
+PASS Property "font-variant-east-asian" is supported
+PASS Property "font-variant-ligatures" is supported
+PASS Property "font-variant-numeric" is supported
+FAIL Property "font-variant-position" is supported assert_true: expected true got false
+PASS Property "font-weight" is supported
+FAIL Property "glyph-orientation-vertical" is supported assert_true: expected true got false
+PASS Property "image-rendering" is supported
+PASS Property "isolation" is supported
+PASS Property "letter-spacing" is supported
+PASS Property "lighting-color" is supported
+PASS Property "line-height" is supported
+PASS Property "marker" is supported
+PASS Property "marker-end" is supported
+PASS Property "marker-mid" is supported
+PASS Property "marker-start" is supported
+PASS Property "mask" is supported
+PASS Property "opacity" is supported
+PASS Property "overflow" is supported
+PASS Property "paint-order" is supported
+PASS Property "pointer-events" is supported
+PASS Property "shape-rendering" is supported
+PASS Property "stop-color" is supported
+PASS Property "stop-opacity" is supported
+PASS Property "stroke" is supported
+PASS Property "stroke-dasharray" is supported
+PASS Property "stroke-dashoffset" is supported
+PASS Property "stroke-linecap" is supported
+PASS Property "stroke-linejoin" is supported
+PASS Property "stroke-miterlimit" is supported
+PASS Property "stroke-opacity" is supported
+PASS Property "stroke-width" is supported
+PASS Property "text-align" is supported
+FAIL Property "text-align-all" is supported assert_true: expected true got false
+PASS Property "text-align-last" is supported
+PASS Property "text-anchor" is supported
+PASS Property "text-decoration" is supported
+PASS Property "text-decoration-color" is supported
+PASS Property "text-decoration-line" is supported
+PASS Property "text-decoration-style" is supported
+PASS Property "text-indent" is supported
+PASS Property "text-orientation" is supported
+PASS Property "text-overflow" is supported
+PASS Property "text-rendering" is supported
+FAIL Property "text-space-collapse" is supported assert_true: expected true got false
+PASS Property "transform" is supported
+PASS Property "transform-box" is supported
+PASS Property "transform-origin" is supported
+PASS Property "unicode-bidi" is supported
+PASS Property "vector-effect" is supported
+PASS Property "vertical-align" is supported
+PASS Property "visibility" is supported
+PASS Property "white-space" is supported
+PASS Property "word-spacing" is supported
+PASS Property "writing-mode" is supported
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/styling/required-properties.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/styling/required-properties.svg
new file mode 100644
index 0000000..c257254
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/styling/required-properties.svg
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml">
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/styling.html#RequiredProperties"/>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/propidx.html"/>
+    <h:meta name="assert" content="All required properties are supported"/>
+    <!-- Note: This test does not verify that the properties are actually applied to SVG rendering. -->
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <script><![CDATA[
+  var properties = [
+    // Properties listed in https://svgwg.org/svg2-draft/propidx.html
+    "alignment-baseline",
+    "baseline-shift",
+    "clip",
+    "clip-path",
+    "clip-rule",
+    "color",
+    "color-interpolation",
+    "color-rendering",
+    "cursor",
+    "direction",
+    "display",
+    "dominant-baseline",
+    "fill",
+    "fill-opacity",
+    "fill-rule",
+    "filter",
+    "flood-color",
+    "flood-opacity",
+    "font",
+    "font-family",
+    "font-size",
+    "font-size-adjust",
+    "font-stretch",
+    "font-style",
+    "font-variant",
+    "font-weight",
+    "glyph-orientation-vertical",
+    "image-rendering",
+    "letter-spacing",
+    "lighting-color",
+    "line-height",
+    "marker",
+    "marker-end",
+    "marker-mid",
+    "marker-start",
+    "mask",
+    "opacity",
+    "overflow",
+    "paint-order",
+    "pointer-events",
+    "shape-rendering",
+    "stop-color",
+    "stop-opacity",
+    "stroke",
+    "stroke-dasharray",
+    "stroke-dashoffset",
+    "stroke-linecap",
+    "stroke-linejoin",
+    "stroke-miterlimit",
+    "stroke-opacity",
+    "stroke-width",
+    "text-anchor",
+    "text-decoration",
+    "text-rendering",
+    "unicode-bidi",
+    "vector-effect",
+    "visibility",
+    "word-spacing",
+    "white-space",
+    "writing-mode",
+
+    // Properties listed in https://svgwg.org/svg2-draft/styling.html#RequiredProperties
+    "display",
+    "overflow",
+    "visibility",
+    "cursor",
+    "text-overflow",
+    "clip",
+    "clip-path",
+    "clip-rule",
+    "mask",
+    "color",
+    "opacity",
+    "color-interpolation-filters",
+    "filter",
+    "flood-color",
+    "flood-opacity",
+    "isolation",
+    "lighting-color",
+    "transform",
+    "transform-box",
+    "transform-origin",
+    "letter-spacing",
+    "text-align",
+    "text-align-all",
+    "text-align-last",
+    "text-indent",
+    "word-spacing",
+    "white-space",
+    "text-space-collapse",
+    "vertical-align",
+    "dominant-baseline",
+    "alignment-baseline",
+    "baseline-shift",
+    "direction",
+    "text-orientation",
+    "writing-mode",
+    "font",
+    "font-family",
+    "font-feature-settings",
+    "font-kerning",
+    "font-size",
+    "font-size-adjust",
+    "font-stretch",
+    "font-style",
+    "font-variant",
+    "font-variant-position",
+    "font-variant-ligatures",
+    "font-variant-caps",
+    "font-variant-numeric",
+    "font-variant-east-asian",
+    "font-weight",
+    "text-decoration",
+    "text-decoration-line",
+    "text-decoration-style",
+    "text-decoration-color"
+  ];
+  properties.sort();
+
+  var target = document.getElementById('target');
+  var previous = null;
+  for (var property of properties) {
+    if (property === previous)
+      continue; // Avoid duplicate test names
+    previous = property;
+
+    test(function() {
+      assert_true(target.style.hasOwnProperty(property));
+    }, 'Property "' + property + '" is supported');
+  }
+  ]]></script>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/META.yml b/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/META.yml
new file mode 100644
index 0000000..f4eb0f3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/META.yml
@@ -0,0 +1,3 @@
+suggested_reviewers:
+  - henbos
+  - vr000m
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/README.md b/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/README.md
new file mode 100644
index 0000000..2b69372
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webrtc-stats/README.md
@@ -0,0 +1,7 @@
+The following 4 test cases in the `webrtc/` directory test some of the mandatory-to-implement stats defined in WebRTC Statistics:
+
+* `getstats.html`
+* `RTCPeerConnection-getStats.https.html`
+* `RTCPeerConnection-track-stats.https.html`
+* `RTCRtpReceiver-getStats.https.html`
+* `RTCRtpSender-getStats.https.html`
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-self-baseline-and-item-relayout-should-not-crash-expected.txt b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-self-baseline-and-item-relayout-should-not-crash-expected.txt
new file mode 100644
index 0000000..d779069
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-self-baseline-and-item-relayout-should-not-crash-expected.txt
@@ -0,0 +1,3 @@
+This test should not crash
+
+PASS
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-self-baseline-and-item-relayout-should-not-crash.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-self-baseline-and-item-relayout-should-not-crash.html
new file mode 100644
index 0000000..78aea1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-self-baseline-and-item-relayout-should-not-crash.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
+<p>This test should not crash</p>
+<div style="display: grid;">
+    <div id="item" style="align-self: baseline;">PASS</div>
+</div>
+<script>
+    let item = document.getElementById("item");
+    item.offsetLeft;
+    item.style.width = "20px";
+</script>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/image-selection-highlight-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/image-selection-highlight-expected.png
index c0641a6..3822a36a 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/image-selection-highlight-expected.png
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/fast/overflow/image-selection-highlight-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/selection/image-writing-modes-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/selection/image-writing-modes-expected.png
new file mode 100644
index 0000000..c03ad41
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/selection/image-writing-modes-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/selection/image-writing-modes-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/selection/image-writing-modes-expected.txt
new file mode 100644
index 0000000..ff5575a2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/paint/selection/image-writing-modes-expected.txt
@@ -0,0 +1,34 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 756
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 785x756 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutNGBlockFlow {HTML} at (0,0) size 785x756
+    LayoutNGBlockFlow {BODY} at (8,8) size 769x740
+      LayoutNGBlockFlow {DIV} at (0,0) size 769x200
+        LayoutText {#text} at (0,40) size 60x20
+          text run at (0,40) width 60: "foo"
+        LayoutImage {IMG} at (60,26) size 40x30
+        LayoutImage {IMG} at (100,26) size 40x30
+        LayoutBR {BR} at (140,40) size 0x0
+        LayoutImage {IMG} at (0,126) size 40x30
+      LayoutNGBlockFlow (anonymous) at (0,200) size 769x100
+        LayoutBR {BR} at (0,40) size 0x0
+      LayoutNGBlockFlow {DIV} at (0,300) size 200x120
+        LayoutText {#text} at (40,0) size 20x60
+          text run at (40,0) width 60: "foo"
+        LayoutImage {IMG} at (30,60) size 40x30
+        LayoutImage {IMG} at (30,90) size 40x30
+        LayoutBR {BR} at (40,120) size 0x0
+        LayoutImage {IMG} at (130,0) size 40x30
+      LayoutNGBlockFlow (anonymous) at (0,420) size 769x100
+        LayoutBR {BR} at (0,40) size 0x0
+      LayoutNGBlockFlow {DIV} at (0,520) size 200x120
+        LayoutText {#text} at (140,0) size 20x60
+          text run at (140,0) width 60: "foo"
+        LayoutImage {IMG} at (30,60) size 40x30
+        LayoutImage {IMG} at (30,90) size 40x30
+        LayoutBR {BR} at (140,120) size 0x0
+        LayoutImage {IMG} at (130,0) size 40x30
+      LayoutNGBlockFlow (anonymous) at (0,640) size 769x100
+        LayoutBR {BR} at (0,40) size 0x0
+selection start: position 0 of child 0 {#text} of child 0 {DIV} of body
+selection end:   position 0 of child 7 {BR} of body
diff --git a/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes-expected.png b/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes-expected.png
new file mode 100644
index 0000000..d95cabf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes-expected.txt b/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes-expected.txt
new file mode 100644
index 0000000..dcc414975
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes-expected.txt
@@ -0,0 +1,34 @@
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 756
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 785x756 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
+  LayoutBlockFlow {HTML} at (0,0) size 785x756
+    LayoutBlockFlow {BODY} at (8,8) size 769x740
+      LayoutBlockFlow {DIV} at (0,0) size 769x200
+        LayoutText {#text} at (0,40) size 60x20
+          text run at (0,40) width 60: "foo"
+        LayoutImage {IMG} at (60,26) size 40x30
+        LayoutImage {IMG} at (100,26) size 40x30
+        LayoutBR {BR} at (140,40) size 0x20
+        LayoutImage {IMG} at (0,126) size 40x30
+      LayoutBlockFlow (anonymous) at (0,200) size 769x100
+        LayoutBR {BR} at (0,40) size 0x20
+      LayoutBlockFlow {DIV} at (0,300) size 200x120
+        LayoutText {#text} at (40,0) size 20x60
+          text run at (40,0) width 60: "foo"
+        LayoutImage {IMG} at (30,60) size 40x30
+        LayoutImage {IMG} at (30,90) size 40x30
+        LayoutBR {BR} at (40,120) size 20x0
+        LayoutImage {IMG} at (130,0) size 40x30
+      LayoutBlockFlow (anonymous) at (0,420) size 769x100
+        LayoutBR {BR} at (0,40) size 0x20
+      LayoutBlockFlow {DIV} at (0,520) size 200x120
+        LayoutText {#text} at (40,0) size 20x60
+          text run at (40,0) width 60: "foo"
+        LayoutImage {IMG} at (30,60) size 40x30
+        LayoutImage {IMG} at (30,90) size 40x30
+        LayoutBR {BR} at (40,120) size 20x0
+        LayoutImage {IMG} at (130,0) size 40x30
+      LayoutBlockFlow (anonymous) at (0,640) size 769x100
+        LayoutBR {BR} at (0,40) size 0x20
+selection start: position 0 of child 0 {#text} of child 0 {DIV} of body
+selection end:   position 0 of child 7 {BR} of body
diff --git a/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes.html b/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes.html
new file mode 100644
index 0000000..fd4a8672
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/selection/image-writing-modes.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="../../resources/ahem.js"></script>
+<style>
+body {
+  font: 20px/1 Ahem;
+  line-height: 100px;
+}
+img {
+  width: 40px;
+  height: 30px;
+}
+</style>
+<!-- Test selection painting on replaced elements -->
+<div>foo<img /><img /><br /><img /></div><br />
+<div style="writing-mode:vertical-lr">foo<img /><img /><br /><img /></div><br />
+<div style="writing-mode:vertical-rl">foo<img /><img /><br /><img /></div><br />
+<script>
+  document.execCommand("SelectAll");
+</script>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/selection/image-writing-modes-expected.png b/third_party/WebKit/LayoutTests/platform/mac/paint/selection/image-writing-modes-expected.png
new file mode 100644
index 0000000..b7f772c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/selection/image-writing-modes-expected.png
Binary files differ
diff --git a/third_party/blink/public/mojom/service_worker/service_worker_object.mojom b/third_party/blink/public/mojom/service_worker/service_worker_object.mojom
index 6f23aa5..79c3393 100644
--- a/third_party/blink/public/mojom/service_worker/service_worker_object.mojom
+++ b/third_party/blink/public/mojom/service_worker/service_worker_object.mojom
@@ -10,6 +10,26 @@
 
 const int64 kInvalidServiceWorkerVersionId = -1;
 
+// Describes whether a controller service worker exists and if it has a fetch
+// handler.
+//
+// BEWARE: In non-NetS13nServiceWorker, the renderer often does not know which
+// controller service worker a request will go to, as skipWaiting() may occur
+// in the browser process at the same time the renderer makes a request.
+// Therefore, non-NetS13nServiceWorker should usually treat
+// kNoFetchEventHandler and kControlled as the same.
+//
+// TODO(falken): This should be moved to controller_service_worker.mojom once
+// it moves to Blink.
+enum ControllerServiceWorkerMode {
+  // No controller exists.
+  kNoController,
+  // The controller exists, but it has no fetch event handler.
+  kNoFetchEventHandler,
+  // The controller exists and it has a fetch event handler.
+  kControlled
+};
+
 // Describes a ServiceWorker object:
 // https://w3c.github.io/ServiceWorker/#serviceworker-interface
 struct ServiceWorkerObjectInfo {
diff --git a/third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h b/third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h
index 70cc473..64aea932 100644
--- a/third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h
+++ b/third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h
@@ -34,6 +34,7 @@
 #include <memory>
 
 #include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-shared.h"
 #include "third_party/blink/public/platform/web_url_loader.h"
 
 namespace base {
@@ -63,11 +64,12 @@
   // Returns an identifier of this provider.
   virtual int ProviderID() const { return -1; }
 
-  // Whether the document associated with WebDocumentLoader is controlled by a
-  // service worker.
-  virtual bool HasControllerServiceWorker() { return false; }
+  virtual blink::mojom::ControllerServiceWorkerMode
+  IsControlledByServiceWorker() {
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  }
 
-  // Returns an identifier of the service worker controlling the document
+  // Returns an identifier of the controller service worker
   // associated with the WebDocumentLoader.
   virtual int64_t ControllerServiceWorkerID() { return -1; }
 
diff --git a/third_party/blink/public/platform/web_worker_fetch_context.h b/third_party/blink/public/platform/web_worker_fetch_context.h
index db4b6436..ac2f4579 100644
--- a/third_party/blink/public/platform/web_worker_fetch_context.h
+++ b/third_party/blink/public/platform/web_worker_fetch_context.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-shared.h"
 #include "third_party/blink/public/platform/web_application_cache_host.h"
 #include "third_party/blink/public/platform/web_document_subresource_filter.h"
 #include "third_party/blink/public/platform/web_url.h"
@@ -67,7 +68,8 @@
   virtual void WillSendRequest(WebURLRequest&) = 0;
 
   // Whether the fetch context is controlled by a service worker.
-  virtual bool IsControlledByServiceWorker() const = 0;
+  virtual blink::mojom::ControllerServiceWorkerMode
+  IsControlledByServiceWorker() const = 0;
 
   // This flag is used to block all mixed content in subframes.
   virtual void SetIsOnSubframe(bool) {}
diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
index 89924025..ac7fe5b 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 
 #include "third_party/blink/public/web/web_settings.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/script_module.cc b/third_party/blink/renderer/bindings/core/v8/script_module.cc
index 3a4e7be..5fb21b2 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_module.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_module.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/bindings/core/v8/script_module.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
index dd9832d..c5e5d0a 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
index e5896cb..a6e4920b 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
+++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
@@ -26,20 +26,22 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_SCRIPT_RUNNER_H_
 #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_SCRIPT_RUNNER_H_
 
-#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
 #include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "v8/include/v8.h"
 
+namespace WTF {
+class TextPosition;
+}
+
 namespace blink {
 
 class ExecutionContext;
+class ReferrerScriptInfo;
 class ScriptSourceCode;
+class ScriptState;
 
 class CORE_EXPORT V8ScriptRunner final {
   STATIC_ONLY(V8ScriptRunner);
@@ -58,7 +60,7 @@
                                                   const String& source,
                                                   const String& file_name,
                                                   AccessControlStatus,
-                                                  const TextPosition&,
+                                                  const WTF::TextPosition&,
                                                   const ReferrerScriptInfo&);
   static v8::MaybeLocal<v8::Value> RunCompiledScript(v8::Isolate*,
                                                      v8::Local<v8::Script>,
@@ -93,7 +95,7 @@
   static void ReportExceptionForModule(v8::Isolate*,
                                        v8::Local<v8::Value> exception,
                                        const String& file_name,
-                                       const TextPosition&);
+                                       const WTF::TextPosition&);
 
   // Calls a function on the V8 extras binding object.
   template <size_t N>
diff --git a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
index c94a8d7..dd164b35 100644
--- a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
+++ b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
@@ -34,6 +34,7 @@
 
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_value.h"
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 5a8f38d..7585d48 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -221,6 +221,7 @@
     "//third_party/blink/renderer/core/style:svg_style",
     "//third_party/blink/renderer/core/svg",
     "//third_party/blink/renderer/core/timing",
+    "//third_party/blink/renderer/core/trustedtypes",
     "//third_party/blink/renderer/core/typed_arrays",
     "//third_party/blink/renderer/core/url",
     "//third_party/blink/renderer/core/workers",
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni
index 5836b3a..5a2ce82 100644
--- a/third_party/blink/renderer/core/core_idl_files.gni
+++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -133,9 +133,9 @@
                     "dom/events/custom_event.idl",
                     "dom/events/event.idl",
                     "dom/events/event_target.idl",
-                    "dom/trustedtypes/trusted_html.idl",
-                    "dom/trustedtypes/trusted_script_url.idl",
-                    "dom/trustedtypes/trusted_url.idl",
+                    "trustedtypes/trusted_html.idl",
+                    "trustedtypes/trusted_script_url.idl",
+                    "trustedtypes/trusted_url.idl",
                     "editing/selection.idl",
                     "events/animation_event.idl",
                     "events/animation_playback_event.idl",
diff --git a/third_party/blink/renderer/core/dom/BUILD.gn b/third_party/blink/renderer/core/dom/BUILD.gn
index 9bf0594..c41f552 100644
--- a/third_party/blink/renderer/core/dom/BUILD.gn
+++ b/third_party/blink/renderer/core/dom/BUILD.gn
@@ -136,8 +136,6 @@
     "events/event_target.h",
     "events/event_target_impl.cc",
     "events/event_target_impl.h",
-    "events/media_element_event_queue.cc",
-    "events/media_element_event_queue.h",
     "events/node_event_context.cc",
     "events/node_event_context.h",
     "events/scoped_event_queue.cc",
@@ -277,12 +275,6 @@
     "tree_scope_adopter.h",
     "tree_walker.cc",
     "tree_walker.h",
-    "trustedtypes/trusted_html.cc",
-    "trustedtypes/trusted_html.h",
-    "trustedtypes/trusted_script_url.cc",
-    "trustedtypes/trusted_script_url.h",
-    "trustedtypes/trusted_url.cc",
-    "trustedtypes/trusted_url.h",
     "user_action_element_set.cc",
     "user_action_element_set.h",
     "user_gesture_indicator.cc",
@@ -306,6 +298,7 @@
     "//services/metrics/public/cpp:metrics_cpp",
     "//services/metrics/public/cpp:ukm_builders",
     "//services/metrics/public/mojom",
+
     # Needed to generate add_event_listener_options.h
     "//third_party/blink/renderer/bindings/core/v8:bindings_core_impl_generated",
   ]
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 10551b89..4d62c72 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -114,7 +114,6 @@
 #include "third_party/blink/renderer/core/dom/static_node_list.h"
 #include "third_party/blink/renderer/core/dom/transform_source.h"
 #include "third_party/blink/renderer/core/dom/tree_walker.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
 #include "third_party/blink/renderer/core/dom/visited_link_state.h"
 #include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
 #include "third_party/blink/renderer/core/dom/xml_document.h"
@@ -236,6 +235,7 @@
 #include "third_party/blink/renderer/core/svg_names.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/window_performance.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
 #include "third_party/blink/renderer/core/workers/shared_worker_repository_client.h"
 #include "third_party/blink/renderer/core/xml/parser/xml_document_parser.h"
 #include "third_party/blink/renderer/core/xml_names.h"
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 8d7fdf6..2009a51 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -74,8 +74,6 @@
 #include "third_party/blink/renderer/core/dom/slot_assignment.h"
 #include "third_party/blink/renderer/core/dom/space_split_string.h"
 #include "third_party/blink/renderer/core/dom/text.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h"
 #include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
 #include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
@@ -142,6 +140,8 @@
 #include "third_party/blink/renderer/core/svg/svg_a_element.h"
 #include "third_party/blink/renderer/core/svg/svg_element.h"
 #include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
 #include "third_party/blink/renderer/core/xml_names.h"
 #include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
diff --git a/third_party/blink/renderer/core/dom/events/event_queue.h b/third_party/blink/renderer/core/dom/events/event_queue.h
index 5523c186..1abbf56 100644
--- a/third_party/blink/renderer/core/dom/events/event_queue.h
+++ b/third_party/blink/renderer/core/dom/events/event_queue.h
@@ -43,6 +43,7 @@
   virtual void Trace(blink::Visitor* visitor) {}
   virtual bool EnqueueEvent(const base::Location&, Event*) = 0;
   virtual void CancelAllEvents() = 0;
+  virtual bool HasPendingEvents() const = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/event_queue_impl.cc b/third_party/blink/renderer/core/dom/events/event_queue_impl.cc
index b03827e..7c4ab23 100644
--- a/third_party/blink/renderer/core/dom/events/event_queue_impl.cc
+++ b/third_party/blink/renderer/core/dom/events/event_queue_impl.cc
@@ -99,14 +99,11 @@
   DCHECK(GetExecutionContext());
 
   probe::AsyncTask async_task(GetExecutionContext(), event);
-  // TODO(hajimehoshi): Don't use |event->target()| here. Assuming the taget
-  // exists here is weird since event target is set later at
-  // |EventTarget::DispatchEvent|.
-  EventTarget* event_target = event->target();
-  if (LocalDOMWindow* window = event_target->ToLocalDOMWindow())
+  EventTarget* target = event->target();
+  if (LocalDOMWindow* window = target->ToLocalDOMWindow())
     window->DispatchEvent(event, nullptr);
   else
-    event_target->DispatchEvent(event);
+    target->DispatchEvent(event);
 }
 
 void EventQueueImpl::ContextDestroyed(ExecutionContext* context) {
@@ -124,4 +121,8 @@
   queued_events_.clear();
 }
 
+bool EventQueueImpl::HasPendingEvents() const {
+  return queued_events_.size() > 0;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/event_queue_impl.h b/third_party/blink/renderer/core/dom/events/event_queue_impl.h
index 5300ea1..7ecfaee0 100644
--- a/third_party/blink/renderer/core/dom/events/event_queue_impl.h
+++ b/third_party/blink/renderer/core/dom/events/event_queue_impl.h
@@ -51,6 +51,7 @@
   void Trace(blink::Visitor*) override;
   bool EnqueueEvent(const base::Location&, Event*) override;
   void CancelAllEvents() override;
+  bool HasPendingEvents() const override;
 
  private:
   EventQueueImpl(ExecutionContext*, TaskType);
diff --git a/third_party/blink/renderer/core/dom/events/media_element_event_queue.cc b/third_party/blink/renderer/core/dom/events/media_element_event_queue.cc
deleted file mode 100644
index bd0edf0..0000000
--- a/third_party/blink/renderer/core/dom/events/media_element_event_queue.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
-
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-
-namespace blink {
-
-MediaElementEventQueue* MediaElementEventQueue::Create(
-    ExecutionContext* context) {
-  return new MediaElementEventQueue(context);
-}
-
-MediaElementEventQueue::MediaElementEventQueue(ExecutionContext* context)
-    : ContextLifecycleObserver(context), is_closed_(false) {
-  if (!GetExecutionContext())
-    Close(nullptr);
-}
-
-MediaElementEventQueue::~MediaElementEventQueue() = default;
-
-void MediaElementEventQueue::Trace(blink::Visitor* visitor) {
-  visitor->Trace(pending_events_);
-  ContextLifecycleObserver::Trace(visitor);
-}
-
-bool MediaElementEventQueue::EnqueueEvent(const base::Location& from_here,
-                                          Event* event) {
-  if (is_closed_)
-    return false;
-
-  DCHECK(event->target());
-  DCHECK(GetExecutionContext());
-
-  TRACE_EVENT_ASYNC_BEGIN1("event", "MediaElementEventQueue:enqueueEvent",
-                           event, "type", event->type().Ascii());
-  probe::AsyncTaskScheduled(GetExecutionContext(), event->type(), event);
-
-  pending_events_.insert(event);
-  GetExecutionContext()
-      ->GetTaskRunner(TaskType::kMediaElementEvent)
-      ->PostTask(FROM_HERE,
-                 WTF::Bind(&MediaElementEventQueue::DispatchEvent,
-                           WrapPersistent(this), WrapPersistent(event)));
-  return true;
-}
-
-bool MediaElementEventQueue::RemoveEvent(Event* event) {
-  auto found = pending_events_.find(event);
-  if (found == pending_events_.end())
-    return false;
-  pending_events_.erase(found);
-  return true;
-}
-
-void MediaElementEventQueue::DispatchEvent(Event* event) {
-  if (!RemoveEvent(event))
-    return;
-
-  DCHECK(GetExecutionContext());
-
-  CString type(event->type().Ascii());
-  probe::AsyncTask async_task(GetExecutionContext(), event);
-  TRACE_EVENT_ASYNC_STEP_INTO1("event", "MediaElementEventQueue:enqueueEvent",
-                               event, "dispatch", "type", type);
-  event->target()->DispatchEvent(event);
-  TRACE_EVENT_ASYNC_END1("event", "MediaElementEventQueue:enqueueEvent", event,
-                         "type", type);
-}
-
-void MediaElementEventQueue::CancelAllEvents() {
-  if (!GetExecutionContext()) {
-    DCHECK(!pending_events_.size());
-    return;
-  }
-  DoCancelAllEvents(GetExecutionContext());
-}
-
-bool MediaElementEventQueue::HasPendingEvents() const {
-  return pending_events_.size() > 0;
-}
-
-void MediaElementEventQueue::ContextDestroyed(ExecutionContext* context) {
-  Close(context);
-}
-
-void MediaElementEventQueue::Close(ExecutionContext* context) {
-  is_closed_ = true;
-  DoCancelAllEvents(context);
-}
-
-void MediaElementEventQueue::DoCancelAllEvents(ExecutionContext* context) {
-  DCHECK(!pending_events_.size() || context);
-  for (auto& event : pending_events_) {
-    TRACE_EVENT_ASYNC_END2("event", "MediaElementEventQueue:enqueueEvent",
-                           event, "type", event->type().Ascii(), "status",
-                           "cancelled");
-    probe::AsyncTaskCanceled(context, event);
-  }
-  pending_events_.clear();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/media_element_event_queue.h b/third_party/blink/renderer/core/dom/events/media_element_event_queue.h
deleted file mode 100644
index 9286be42..0000000
--- a/third_party/blink/renderer/core/dom/events/media_element_event_queue.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_MEDIA_ELEMENT_EVENT_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_MEDIA_ELEMENT_EVENT_QUEUE_H_
-
-#include "base/location.h"
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-// Queue for events originating in MediaElement and having
-// "media element event" task type according to the spec.
-class CORE_EXPORT MediaElementEventQueue final
-    : public GarbageCollectedFinalized<MediaElementEventQueue>,
-      public ContextLifecycleObserver {
-  USING_GARBAGE_COLLECTED_MIXIN(MediaElementEventQueue);
-
- public:
-  static MediaElementEventQueue* Create(ExecutionContext*);
-  ~MediaElementEventQueue();
-
-  void Trace(blink::Visitor*) override;
-  bool EnqueueEvent(const base::Location&, Event*);
-
-  void CancelAllEvents();
-  bool HasPendingEvents() const;
-
- private:
-  explicit MediaElementEventQueue(ExecutionContext*);
-  bool RemoveEvent(Event* event);
-  void DispatchEvent(Event* event);
-
-  void ContextDestroyed(ExecutionContext*) override;
-  void Close(ExecutionContext*);
-  void DoCancelAllEvents(ExecutionContext*);
-
-  HeapHashSet<Member<Event>> pending_events_;
-
-  bool is_closed_;
-};
-
-}  // namespace blink
-
-#endif
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc
index b03b82c..cd5a9f3 100644
--- a/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -37,7 +37,6 @@
 #include "third_party/blink/renderer/core/dom/slot_assignment.h"
 #include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
 #include "third_party/blink/renderer/core/dom/text.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
 #include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
 #include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
 #include "third_party/blink/renderer/core/editing/serializers/serialization.h"
@@ -45,6 +44,7 @@
 #include "third_party/blink/renderer/core/html/html_shadow_element.h"
 #include "third_party/blink/renderer/core/html/html_slot_element.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
 
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc
index b2ec51e..96515ec 100644
--- a/third_party/blink/renderer/core/frame/location.cc
+++ b/third_party/blink/renderer/core/frame/location.cc
@@ -31,11 +31,11 @@
 #include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
 #include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
 #include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h"
 #include "third_party/blink/renderer/core/frame/dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/loader/frame_loader.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
 #include "third_party/blink/renderer/core/url/dom_url_utils_read_only.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h"
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index db191c29..65b1b65 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -52,6 +52,7 @@
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/dom/element_traversal.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue_impl.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -464,7 +465,8 @@
           this,
           &HTMLMediaElement::CheckViewportIntersectionTimerFired),
       played_time_ranges_(),
-      async_event_queue_(MediaElementEventQueue::Create(GetExecutionContext())),
+      async_event_queue_(EventQueueImpl::Create(GetExecutionContext(),
+                                                TaskType::kMediaElementEvent)),
       playback_rate_(1.0f),
       default_playback_rate_(1.0f),
       network_state_(kNetworkEmpty),
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h
index d9de0cc3..d85b016 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -35,7 +35,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
 #include "third_party/blink/renderer/core/dom/pausable_object.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
 #include "third_party/blink/renderer/core/html/media/media_controls.h"
@@ -44,6 +43,7 @@
 #include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
 #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/web_task_runner.h"
 
 namespace cc {
@@ -60,6 +60,7 @@
 class CueTimeline;
 class EnumerationHistogram;
 class Event;
+class EventQueue;
 class ExceptionState;
 class HTMLMediaElementControlsList;
 class HTMLMediaSource;
@@ -567,7 +568,7 @@
   TaskRunnerTimer<HTMLMediaElement> check_viewport_intersection_timer_;
 
   Member<TimeRanges> played_time_ranges_;
-  Member<MediaElementEventQueue> async_event_queue_;
+  Member<EventQueue> async_event_queue_;
 
   double playback_rate_;
   double default_playback_rate_;
diff --git a/third_party/blink/renderer/core/html/track/text_track_list.cc b/third_party/blink/renderer/core/html/track/text_track_list.cc
index d55f04e..9bf1c29 100644
--- a/third_party/blink/renderer/core/html/track/text_track_list.cc
+++ b/third_party/blink/renderer/core/html/track/text_track_list.cc
@@ -25,7 +25,7 @@
 
 #include "third_party/blink/renderer/core/html/track/text_track_list.h"
 
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue_impl.h"
 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
 #include "third_party/blink/renderer/core/html/track/inband_text_track.h"
 #include "third_party/blink/renderer/core/html/track/loadable_text_track.h"
@@ -37,8 +37,9 @@
 
 TextTrackList::TextTrackList(HTMLMediaElement* owner)
     : owner_(owner),
-      async_event_queue_(
-          MediaElementEventQueue::Create(GetExecutionContext())) {}
+      async_event_queue_(EventQueueImpl::Create(GetExecutionContext(),
+                                                TaskType::kMediaElementEvent)) {
+}
 
 TextTrackList::~TextTrackList() = default;
 
diff --git a/third_party/blink/renderer/core/html/track/text_track_list.h b/third_party/blink/renderer/core/html/track/text_track_list.h
index 04be154b..ccc8a5a 100644
--- a/third_party/blink/renderer/core/html/track/text_track_list.h
+++ b/third_party/blink/renderer/core/html/track/text_track_list.h
@@ -36,7 +36,7 @@
 
 namespace blink {
 
-class MediaElementEventQueue;
+class EventQueue;
 class TextTrack;
 
 class CORE_EXPORT TextTrackList final : public EventTargetWithInlineData {
@@ -87,7 +87,7 @@
 
   Member<HTMLMediaElement> owner_;
 
-  Member<MediaElementEventQueue> async_event_queue_;
+  Member<EventQueue> async_event_queue_;
 
   HeapVector<TraceWrapperMember<TextTrack>> add_track_tracks_;
   HeapVector<TraceWrapperMember<TextTrack>> element_tracks_;
diff --git a/third_party/blink/renderer/core/inspector/network_resources_data.cc b/third_party/blink/renderer/core/inspector/network_resources_data.cc
index 1bece0d..2420ccd 100644
--- a/third_party/blink/renderer/core/inspector/network_resources_data.cc
+++ b/third_party/blink/renderer/core/inspector/network_resources_data.cc
@@ -32,6 +32,7 @@
 #include "third_party/blink/renderer/core/dom/dom_implementation.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/layout/grid.cc b/third_party/blink/renderer/core/layout/grid.cc
index 53e50dc..89d0145 100644
--- a/third_party/blink/renderer/core/layout/grid.cc
+++ b/third_party/blink/renderer/core/layout/grid.cc
@@ -142,10 +142,6 @@
   return direction == kForColumns ? area.columns : area.rows;
 }
 
-void Grid::SetHasAnyOrthogonalGridItem(bool has_any_orthogonal_grid_item) {
-  has_any_orthogonal_grid_item_ = has_any_orthogonal_grid_item;
-}
-
 void Grid::SetNeedsItemsPlacement(bool needs_items_placement) {
   needs_items_placement_ = needs_items_placement;
 
@@ -157,13 +153,14 @@
   ClearGridDataStructure();
   grid_item_area_.clear();
   grid_items_indexes_map_.clear();
-  has_any_orthogonal_grid_item_ = false;
   smallest_row_start_ = 0;
   smallest_column_start_ = 0;
   auto_repeat_columns_ = 0;
   auto_repeat_rows_ = 0;
   auto_repeat_empty_columns_ = nullptr;
   auto_repeat_empty_rows_ = nullptr;
+  baseline_grid_items_.resize(0);
+  orthogonal_grid_items_.resize(0);
 }
 
 Grid::GridIterator::GridIterator(GridTrackSizingDirection direction,
diff --git a/third_party/blink/renderer/core/layout/grid.h b/third_party/blink/renderer/core/layout/grid.h
index 45ea645a..135d0b3 100644
--- a/third_party/blink/renderer/core/layout/grid.h
+++ b/third_party/blink/renderer/core/layout/grid.h
@@ -46,10 +46,21 @@
   // Note that out of flow children are not grid items.
   bool HasGridItems() const { return !grid_item_area_.IsEmpty(); }
 
-  bool HasAnyOrthogonalGridItem() const {
-    return has_any_orthogonal_grid_item_;
+  void AddBaselineAlignedItem(LayoutBox& item) {
+    baseline_grid_items_.push_back(&item);
   }
-  void SetHasAnyOrthogonalGridItem(bool);
+  void AddOrthogonalItem(LayoutBox& item) {
+    orthogonal_grid_items_.push_back(&item);
+  }
+  bool HasAnyOrthogonalGridItem() const {
+    return !orthogonal_grid_items_.IsEmpty();
+  }
+  const Vector<LayoutBox*>& OrthogonalGridItems() const {
+    return orthogonal_grid_items_;
+  }
+  const Vector<LayoutBox*>& BaselineGridItems() const {
+    return baseline_grid_items_;
+  }
 
   GridArea GridItemArea(const LayoutBox&) const;
   void SetGridItemArea(const LayoutBox&, GridArea);
@@ -131,7 +142,6 @@
   size_t auto_repeat_columns_{0};
   size_t auto_repeat_rows_{0};
 
-  bool has_any_orthogonal_grid_item_{false};
   bool needs_items_placement_{true};
 
   HashMap<const LayoutBox*, GridArea> grid_item_area_;
@@ -139,6 +149,9 @@
 
   std::unique_ptr<OrderedTrackIndexSet> auto_repeat_empty_columns_{nullptr};
   std::unique_ptr<OrderedTrackIndexSet> auto_repeat_empty_rows_{nullptr};
+
+  Vector<LayoutBox*> orthogonal_grid_items_;
+  Vector<LayoutBox*> baseline_grid_items_;
 };
 
 class VectorGrid final : public Grid {
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
index 9d80ecf..25e9ff6 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -1884,7 +1884,7 @@
       }
 
       // Ignore spaces after a list marker.
-      if (child->IsListMarker())
+      if (child->IsListMarkerIncludingNG())
         strip_front_spaces = true;
     } else {
       min_logical_width = std::max(min_logical_width, inline_min);
diff --git a/third_party/blink/renderer/core/layout/layout_grid.cc b/third_party/blink/renderer/core/layout/layout_grid.cc
index 3258b7f..88f9c569 100644
--- a/third_party/blink/renderer/core/layout/layout_grid.cc
+++ b/third_party/blink/renderer/core/layout/layout_grid.cc
@@ -304,6 +304,8 @@
     LayoutUnit available_space_for_columns = AvailableLogicalWidth();
     PlaceItemsOnGrid(track_sizing_algorithm_, available_space_for_columns);
 
+    PerformGridItemsPreLayout(track_sizing_algorithm_);
+
     track_sizing_algorithm_.ComputeBaselineAlignmentContext();
 
     // 1- First, the track sizing algorithm is used to resolve the sizes of the
@@ -499,6 +501,8 @@
   GridTrackSizingAlgorithm algorithm(this, *grid);
   PlaceItemsOnGrid(algorithm, base::nullopt);
 
+  PerformGridItemsPreLayout(algorithm);
+
   algorithm.ComputeBaselineAlignmentContext();
   ComputeTrackSizesForIndefiniteSize(algorithm, kForColumns, min_logical_width,
                                      max_logical_width);
@@ -770,8 +774,6 @@
 
   Vector<LayoutBox*> auto_major_axis_auto_grid_items;
   Vector<LayoutBox*> specified_major_axis_auto_grid_items;
-  Vector<LayoutBox*> orthogonal_grid_items;
-  Vector<LayoutBox*> baseline_grid_items;
 #if DCHECK_IS_ON()
   DCHECK(!grid.HasAnyGridItemPaintOrder());
 #endif
@@ -791,9 +793,9 @@
       child->SetOverrideContainingBlockContentLogicalHeight(LayoutUnit(-1));
 
     if (GridLayoutUtils::IsOrthogonalChild(*this, *child))
-      orthogonal_grid_items.push_back(child);
+      grid.AddOrthogonalItem(*child);
     if (IsBaselineAlignmentForChild(*child))
-      baseline_grid_items.push_back(child);
+      grid.AddBaselineAlignedItem(*child);
     grid.SetGridItemPaintOrder(*child, child_index++);
 
     GridArea area = grid.GridItemArea(*child);
@@ -815,7 +817,6 @@
     }
     grid.insert(*child, area);
   }
-  grid.SetHasAnyOrthogonalGridItem(!orthogonal_grid_items.IsEmpty());
 
 #if DCHECK_IS_ON()
   if (grid.HasGridItems()) {
@@ -839,19 +840,6 @@
 
   grid.SetNeedsItemsPlacement(false);
 
-  // Blink does a pre-layout of all the orthogonal boxes in the layout
-  // tree (see how LocalFrameView::PerformLayout calls its
-  // LayoutOrthogonalWritingModeRoots function). However, grid items
-  // don't participate in this process (see the function
-  // PrepareOrthogonalWritingModeRootForLayout) because it's useless
-  // and even wrong if they don't have their corresponding Grid Area.
-  LayoutOrthogonalWritingModeRoots(algorithm, orthogonal_grid_items);
-
-  // We need to layout the item to know whether it must synthesize its
-  // baseline or not, which may imply a cyclic sizing dependency.
-  // TODO (jfernandez): Can we avoid it ?
-  LayoutBaselineAlignedItems(algorithm, baseline_grid_items);
-
 #if DCHECK_IS_ON()
   for (LayoutBox* child = grid.GetOrderIterator().First(); child;
        child = grid.GetOrderIterator().Next()) {
@@ -876,32 +864,34 @@
   return true;
 }
 
-// TODO(lajava): Consider rafactoring this code with
-// LocalFrameView::LayoutOrthogonalWritingModeRoots
-void LayoutGrid::LayoutOrthogonalWritingModeRoots(
-    const GridTrackSizingAlgorithm& algorithm,
-    const Vector<LayoutBox*>& orthogonal_grid_items) const {
+void LayoutGrid::PerformGridItemsPreLayout(
+    const GridTrackSizingAlgorithm& algorithm) const {
+  DCHECK(!algorithm.GetGrid().NeedsItemsPlacement());
   if (!GetDocument().View()->IsInPerformLayout())
     return;
-
-  for (auto* root : orthogonal_grid_items) {
-    DCHECK(GridLayoutUtils::IsOrthogonalChild(*this, *root));
-    if (PrepareOrthogonalWritingModeRootForLayout(*root)) {
+  // Blink does a pre-layout of all the orthogonal boxes in the layout
+  // tree (see how LocalFrameView::PerformLayout calls its
+  // LayoutOrthogonalWritingModeRoots function). However, grid items
+  // don't participate in this process (see the function
+  // PrepareOrthogonalWritingModeRootForLayout) because it's useless
+  // and even wrong if they don't have their corresponding Grid Area.
+  // TODO(jfernandez): Consider rafactoring this code with
+  // LocalFrameView::LayoutOrthogonalWritingModeRoots
+  for (auto* item : algorithm.GetGrid().OrthogonalGridItems()) {
+    DCHECK(GridLayoutUtils::IsOrthogonalChild(*this, *item));
+    if (PrepareOrthogonalWritingModeRootForLayout(*item)) {
       UpdateGridAreaLogicalSize(
-          *root, algorithm.EstimatedGridAreaBreadthForChild(*root));
-      root->LayoutIfNeeded();
+          *item, algorithm.EstimatedGridAreaBreadthForChild(*item));
+      item->LayoutIfNeeded();
     }
   }
-}
-
-void LayoutGrid::LayoutBaselineAlignedItems(
-    const GridTrackSizingAlgorithm& algorithm,
-    const Vector<LayoutBox*>& items_list) const {
-  if (!GetDocument().View()->IsInPerformLayout())
-    return;
-
-  for (auto* item : items_list) {
+  // We need to layout the item to know whether it must synthesize its
+  // baseline or not, which may imply a cyclic sizing dependency.
+  // TODO (jfernandez): Can we avoid it ?
+  for (auto* item : algorithm.GetGrid().BaselineGridItems()) {
     DCHECK(IsBaselineAlignmentForChild(*item));
+    if (GridLayoutUtils::IsOrthogonalChild(*this, *item))
+      continue;
     if (item->HasRelativeLogicalWidth() || item->HasRelativeLogicalHeight()) {
       UpdateGridAreaLogicalSize(
           *item, algorithm.EstimatedGridAreaBreadthForChild(*item));
diff --git a/third_party/blink/renderer/core/layout/layout_grid.h b/third_party/blink/renderer/core/layout/layout_grid.h
index 22e92ca5..0e3bcbb 100644
--- a/third_party/blink/renderer/core/layout/layout_grid.h
+++ b/third_party/blink/renderer/core/layout/layout_grid.h
@@ -172,10 +172,7 @@
       Grid&,
       GridTrackSizingDirection) const;
 
-  void LayoutOrthogonalWritingModeRoots(const GridTrackSizingAlgorithm&,
-                                        const Vector<LayoutBox*>&) const;
-  void LayoutBaselineAlignedItems(const GridTrackSizingAlgorithm&,
-                                  const Vector<LayoutBox*>&) const;
+  void PerformGridItemsPreLayout(const GridTrackSizingAlgorithm&) const;
 
   void PlaceItemsOnGrid(
       GridTrackSizingAlgorithm&,
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index f956b5b..ed41ad49 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1601,6 +1601,10 @@
     return IsListItem() || IsLayoutNGListItem();
   }
 
+  bool IsListMarkerIncludingNG() const {
+    return IsListMarker() || IsLayoutNGListMarker();
+  }
+
   virtual bool IsCombineText() const { return false; }
 
   virtual int CaretMinOffset() const;
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.cc b/third_party/blink/renderer/core/layout/layout_replaced.cc
index 93ad6d1d..046da37 100644
--- a/third_party/blink/renderer/core/layout/layout_replaced.cc
+++ b/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -963,6 +963,19 @@
   if (GetSelectionState() == SelectionState::kNone)
     return LayoutRect();
 
+  if (IsInline()) {
+    const auto fragments = NGPaintFragment::InlineFragmentsFor(this);
+    if (fragments.IsInLayoutNGInlineFormattingContext()) {
+      LayoutRect rect;
+      for (const NGPaintFragment* fragment : fragments) {
+        const NGPhysicalOffsetRect fragment_rect =
+            fragment->ComputeLocalSelectionRectForReplaced();
+        rect.Unite(fragment_rect.ToLayoutRect());
+      }
+      return rect;
+    }
+  }
+
   if (!InlineBoxWrapper()) {
     // We're a block-level replaced element.  Just return our own dimensions.
     return LayoutRect(LayoutPoint(), Size());
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index f5f6ed1..fdd31b9 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -1902,7 +1902,7 @@
       if (status.start == status.end)
         continue;
       NGPhysicalOffsetRect fragment_rect =
-          fragment->ComputeLocalSelectionRect(status);
+          fragment->ComputeLocalSelectionRectForText(status);
       fragment_rect.offset += fragment->InlineOffsetToContainerBox();
       rect.Unite(fragment_rect.ToLayoutRect());
     }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 792d06f4..baf3c9b 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -70,13 +70,8 @@
   builder->EnterBlock(block->Style());
   LayoutObject* node = GetLayoutObjectForFirstChildNode(block);
 
-  LayoutObject* symbol = nullptr;
-  if (block->IsLayoutNGListMarker()) {
-    symbol = ToLayoutNGListMarker(block)->SymbolMarkerLayoutText();
-  } else if (block->IsLayoutNGListItem()) {
-    symbol = ToLayoutNGListItem(block)->SymbolMarkerLayoutText();
-  }
-
+  const LayoutObject* symbol =
+      LayoutNGListItem::FindSymbolMarkerLayoutText(block);
   while (node) {
     if (node->IsText()) {
       LayoutText* layout_text = ToLayoutText(node);
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
index 6f44e23..d0e848c0 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
@@ -66,8 +66,8 @@
   if (!marker_)
     return;
 
-  // Make sure marker is the direct child of ListItem.
-  if (marker_->Parent() && marker_->Parent() != this) {
+  // Make sure outside marker is the direct child of ListItem.
+  if (!IsInside() && marker_->Parent() != this) {
     marker_->Remove();
     AddChild(marker_, FirstChild());
   }
@@ -302,4 +302,21 @@
   return marker_->SlowFirstChild();
 }
 
+const LayoutObject* LayoutNGListItem::FindSymbolMarkerLayoutText(
+    const LayoutObject* object) {
+  if (!object)
+    return nullptr;
+
+  if (object->IsLayoutNGListItem())
+    return ToLayoutNGListItem(object)->SymbolMarkerLayoutText();
+
+  if (object->IsLayoutNGListMarker())
+    return ToLayoutNGListMarker(object)->SymbolMarkerLayoutText();
+
+  if (object->IsAnonymousBlock())
+    return FindSymbolMarkerLayoutText(object->Parent());
+
+  return nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h
index c8f1e61a82..a060bb1 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h
@@ -37,6 +37,7 @@
   void WillCollectInlines() override;
 
   LayoutObject* SymbolMarkerLayoutText() const;
+  static const LayoutObject* FindSymbolMarkerLayoutText(const LayoutObject*);
 
   const char* GetName() const override { return "LayoutNGListItem"; }
 
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index df42b3c..65cddf1 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -86,6 +86,7 @@
 #include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
 #include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
 #include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/network/http_names.h"
 #include "third_party/blink/renderer/platform/network/http_parsers.h"
 #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
@@ -977,7 +978,8 @@
   // didObserveLoadingBehavior() must be called after dispatchDidCommitLoad() is
   // called for the metrics tracking logic to handle it properly.
   if (service_worker_network_provider_ &&
-      service_worker_network_provider_->HasControllerServiceWorker()) {
+      service_worker_network_provider_->IsControlledByServiceWorker() !=
+          blink::mojom::ControllerServiceWorkerMode::kNoController) {
     GetLocalFrameClient().DidObserveLoadingBehavior(
         kWebLoadingBehaviorServiceWorkerControlled);
   }
diff --git a/third_party/blink/renderer/core/loader/document_threadable_loader.cc b/third_party/blink/renderer/core/loader/document_threadable_loader.cc
index 2cec592e..727fdf6 100644
--- a/third_party/blink/renderer/core/loader/document_threadable_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_threadable_loader.cc
@@ -360,7 +360,8 @@
   if (!async_ || new_request.GetSkipServiceWorker() ||
       !SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
           new_request.Url().Protocol()) ||
-      !loading_context_->GetResourceFetcher()->IsControlledByServiceWorker()) {
+      loading_context_->GetResourceFetcher()->IsControlledByServiceWorker() ==
+          blink::mojom::ControllerServiceWorkerMode::kNoController) {
     DispatchInitialRequest(new_request);
     return;
   }
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index eb405bf..0943e10 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -795,20 +795,23 @@
   return GetContentSettingsClient()->AllowImage(images_enabled, url);
 }
 
-bool FrameFetchContext::IsControlledByServiceWorker() const {
+blink::mojom::ControllerServiceWorkerMode
+FrameFetchContext::IsControlledByServiceWorker() const {
   if (IsDetached())
-    return false;
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
 
   DCHECK(MasterDocumentLoader());
 
   auto* service_worker_network_provider =
       MasterDocumentLoader()->GetServiceWorkerNetworkProvider();
-  return service_worker_network_provider &&
-         service_worker_network_provider->HasControllerServiceWorker();
+  if (!service_worker_network_provider)
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  return service_worker_network_provider->IsControlledByServiceWorker();
 }
 
 int64_t FrameFetchContext::ServiceWorkerID() const {
-  DCHECK(IsControlledByServiceWorker());
+  DCHECK(IsControlledByServiceWorker() !=
+         blink::mojom::ControllerServiceWorkerMode::kNoController);
   DCHECK(MasterDocumentLoader());
   auto* service_worker_network_provider =
       MasterDocumentLoader()->GetServiceWorkerNetworkProvider();
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
index a650fbf..b643a9c 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -33,6 +33,7 @@
 
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 #include "third_party/blink/renderer/core/loader/base_fetch_context.h"
@@ -136,7 +137,8 @@
 
   void AddResourceTiming(const ResourceTimingInfo&) override;
   bool AllowImage(bool images_enabled, const KURL&) const override;
-  bool IsControlledByServiceWorker() const override;
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+      const override;
   int64_t ServiceWorkerID() const override;
   int ApplicationCacheHostID() const override;
 
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index b89f86a..a75285b3 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -1456,7 +1456,8 @@
 TEST_F(FrameFetchContextTest, IsControlledByServiceWorkerWhenDetached) {
   dummy_page_holder = nullptr;
 
-  EXPECT_FALSE(fetch_context->IsControlledByServiceWorker());
+  EXPECT_EQ(blink::mojom::ControllerServiceWorkerMode::kNoController,
+            fetch_context->IsControlledByServiceWorker());
 }
 
 TEST_F(FrameFetchContextTest, IsMainFrameWhenDetached) {
diff --git a/third_party/blink/renderer/core/loader/history_item.cc b/third_party/blink/renderer/core/loader/history_item.cc
index 4be64ce..ee6baf6 100644
--- a/third_party/blink/renderer/core/loader/history_item.cc
+++ b/third_party/blink/renderer/core/loader/history_item.cc
@@ -30,6 +30,7 @@
 
 #include "third_party/blink/renderer/core/html/forms/form_controller.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 #include "third_party/blink/renderer/platform/wtf/text/cstring.h"
diff --git a/third_party/blink/renderer/core/loader/ping_loader_test.cc b/third_party/blink/renderer/core/loader/ping_loader_test.cc
index e8eacea5..1eec52d 100644
--- a/third_party/blink/renderer/core/loader/ping_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/ping_loader_test.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/loader/frame_loader.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/loader/fetch/substitute_data.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
diff --git a/third_party/blink/renderer/core/loader/threadable_loader_test.cc b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
index cb7050a3..3cd88bf 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader_test.cc
@@ -250,7 +250,10 @@
   }
 
   void WillSendRequest(WebURLRequest&) override {}
-  bool IsControlledByServiceWorker() const override { return false; }
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+      const override {
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  }
   WebURL SiteForCookies() const override { return site_for_cookies_; }
 
  private:
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
index cbe78cd..5aa4aab 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -277,7 +277,8 @@
   return url_loader_factory_->CreateURLLoader(wrapped, task_runner);
 }
 
-bool WorkerFetchContext::IsControlledByServiceWorker() const {
+blink::mojom::ControllerServiceWorkerMode
+WorkerFetchContext::IsControlledByServiceWorker() const {
   return web_context_->IsControlledByServiceWorker();
 }
 
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h
index fa3b70ae..74da2bdc 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include "base/single_thread_task_runner.h"
 #include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/loader/base_fetch_context.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -73,7 +74,8 @@
       scoped_refptr<base::SingleThreadTaskRunner>,
       const ResourceLoaderOptions&) override;
   void PrepareRequest(ResourceRequest&, RedirectType) override;
-  bool IsControlledByServiceWorker() const override;
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+      const override;
   int ApplicationCacheHostID() const override;
   void AddAdditionalRequestHeaders(ResourceRequest&,
                                    FetchResourceType) override;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index 02115456..0959ac4 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -32,8 +32,7 @@
                                     const NGPaintFragment& paint_fragment) {
   const WritingMode writing_mode = paint_fragment.Style().GetWritingMode();
   const TextDirection text_direction =
-      ToNGPhysicalTextFragmentOrDie(paint_fragment.PhysicalFragment())
-          .ResolvedDirection();
+      paint_fragment.PhysicalFragment().ResolvedDirection();
   const NGPhysicalSize outer_size = paint_fragment.Size();
   const NGLogicalOffset logical_offset = physical_rect.offset.ConvertToLogical(
       writing_mode, text_direction, outer_size, physical_rect.size);
@@ -47,8 +46,7 @@
     const NGPaintFragment& paint_fragment) {
   const WritingMode writing_mode = paint_fragment.Style().GetWritingMode();
   const TextDirection text_direction =
-      ToNGPhysicalTextFragmentOrDie(paint_fragment.PhysicalFragment())
-          .ResolvedDirection();
+      paint_fragment.PhysicalFragment().ResolvedDirection();
   const NGPhysicalSize outer_size = paint_fragment.Size();
   const NGPhysicalSize physical_size =
       logical_rect.size.ConvertToPhysical(writing_mode);
@@ -169,6 +167,16 @@
   return paint_fragment;
 }
 
+bool NGPaintFragment::IsDescendantOfNotSelf(
+    const NGPaintFragment& ancestor) const {
+  for (const NGPaintFragment* fragment = Parent(); fragment;
+       fragment = fragment->Parent()) {
+    if (fragment == &ancestor)
+      return true;
+  }
+  return false;
+}
+
 bool NGPaintFragment::HasSelfPaintingLayer() const {
   return physical_fragment_->IsBox() &&
          ToNGPhysicalBoxFragment(*physical_fragment_).HasSelfPaintingLayer();
@@ -374,7 +382,7 @@
     line_box->SetShouldDoFullPaintInvalidationRecursively();
 }
 
-NGPhysicalOffsetRect NGPaintFragment::ComputeLocalSelectionRect(
+NGPhysicalOffsetRect NGPaintFragment::ComputeLocalSelectionRectForText(
     const LayoutSelectionStatus& selection_status) const {
   const NGPhysicalTextFragment& text_fragment =
       ToNGPhysicalTextFragmentOrDie(PhysicalFragment());
@@ -402,6 +410,18 @@
   return physical_rect;
 }
 
+NGPhysicalOffsetRect NGPaintFragment::ComputeLocalSelectionRectForReplaced()
+    const {
+  DCHECK(GetLayoutObject()->IsLayoutReplaced());
+  const NGPhysicalOffsetRect selection_rect = PhysicalFragment().LocalRect();
+  NGLogicalRect logical_rect = ComputeLogicalRectFor(selection_rect, *this);
+  const NGLogicalRect line_height_expanded_rect =
+      ExpandSelectionRectToLineHeight(logical_rect, *this);
+  const NGPhysicalOffsetRect physical_rect =
+      ComputePhysicalRectFor(line_height_expanded_rect, *this);
+  return physical_rect;
+}
+
 PositionWithAffinity NGPaintFragment::PositionForPointInText(
     const NGPhysicalOffset& point) const {
   DCHECK(PhysicalFragment().IsText());
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
index 65d2fd5..42f4b9c 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -50,6 +50,10 @@
   const Vector<std::unique_ptr<NGPaintFragment>>& Children() const {
     return children_;
   }
+  // Note, as the name implies, |IsDescendantOfNotSelf| returns false for the
+  // same object. This is different from |LayoutObject::IsDescendant| but is
+  // same as |Node::IsDescendant|.
+  bool IsDescendantOfNotSelf(const NGPaintFragment&) const;
 
   // Returns the first line box for a block-level container.
   NGPaintFragment* FirstLineBox() const;
@@ -89,8 +93,9 @@
   // Union of children's ink overflows.
   LayoutRect ChildrenInkOverflow() const;
 
-  NGPhysicalOffsetRect ComputeLocalSelectionRect(
+  NGPhysicalOffsetRect ComputeLocalSelectionRectForText(
       const LayoutSelectionStatus&) const;
+  NGPhysicalOffsetRect ComputeLocalSelectionRectForReplaced() const;
 
   // Set ShouldDoFullPaintInvalidation flag in the corresponding LayoutObject
   // recursively.
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
index 614854c6..8decf77 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
@@ -143,8 +143,93 @@
   return {fragment.parent, fragment.index + 1};
 }
 
+unsigned IndexOfChild(const NGPaintFragment& parent,
+                      const NGPaintFragment& fragment) {
+  const auto& children = parent.Children();
+  const auto* it = std::find_if(
+      children.begin(), children.end(),
+      [&fragment](const auto& child) { return &fragment == child.get(); });
+  DCHECK(it != children.end());
+  return std::distance(children.begin(), it);
+}
+
 }  // namespace
 
+NGPaintFragmentTraversal::NGPaintFragmentTraversal(const NGPaintFragment& root)
+    : root_(root) {
+  Push(root, 0);
+}
+
+NGPaintFragmentTraversal::NGPaintFragmentTraversal(const NGPaintFragment& root,
+                                                   const NGPaintFragment& start)
+    : root_(root) {
+  MoveTo(start);
+}
+
+void NGPaintFragmentTraversal::Push(const NGPaintFragment& parent,
+                                    unsigned index) {
+  stack_.push_back(ParentAndIndex{&parent, index});
+  current_ = parent.Children()[index].get();
+}
+
+void NGPaintFragmentTraversal::Push(const NGPaintFragment& fragment) {
+  const NGPaintFragment* parent = fragment.Parent();
+  DCHECK(parent);
+  Push(*parent, IndexOfChild(*parent, fragment));
+}
+
+void NGPaintFragmentTraversal::MoveTo(const NGPaintFragment& fragment) {
+  DCHECK(fragment.IsDescendantOfNotSelf(root_));
+
+  // Because we may not traverse all descendants of |root_|, just push the
+  // specified fragment. Computing its ancestors up to |root_| is deferred to
+  // |MoveToNextSiblingOrAncestor()|.
+  stack_.resize(0);
+  Push(fragment);
+}
+
+void NGPaintFragmentTraversal::MoveToNext() {
+  if (IsAtEnd())
+    return;
+
+  if (!current_->Children().IsEmpty()) {
+    Push(*current_, 0);
+    return;
+  }
+
+  MoveToNextSiblingOrAncestor();
+}
+
+void NGPaintFragmentTraversal::MoveToNextSiblingOrAncestor() {
+  if (IsAtEnd())
+    return;
+
+  while (true) {
+    // Check if we have a next sibling.
+    auto& stack_top = stack_.back();
+    if (++stack_top.index < stack_top.parent->Children().size()) {
+      current_ = stack_top.parent->Children()[stack_top.index].get();
+      return;
+    }
+
+    // Check the next parent in the stack. If the stack is not empty, traverse
+    // its next sibiling.
+    stack_.pop_back();
+    if (!stack_.IsEmpty())
+      continue;
+
+    // We might have started with |MoveTo()|, and thus computing parent stack
+    // was deferred. Check parents until we reach the |root_|.
+    const NGPaintFragment* parent = current_->Parent();
+    DCHECK(parent);
+    if (parent == &root_) {
+      current_ = nullptr;
+      return;
+    }
+    Push(*parent);
+  }
+}
+
 Vector<NGPaintFragmentWithContainerOffset>
 NGPaintFragmentTraversal::DescendantsOf(const NGPaintFragment& container) {
   Vector<NGPaintFragmentWithContainerOffset> result;
@@ -198,14 +283,7 @@
     const NGPaintFragment* fragment) {
   if (!fragment)
     return NGPaintFragmentTraversalContext();
-
-  DCHECK(fragment->Parent());
-  const auto& siblings = fragment->Parent()->Children();
-  const auto* self_iter = std::find_if(
-      siblings.begin(), siblings.end(),
-      [&fragment](const auto& sibling) { return fragment == sibling.get(); });
-  DCHECK_NE(self_iter, siblings.end());
-  return {fragment->Parent(), self_iter - siblings.begin()};
+  return {fragment->Parent(), IndexOfChild(*fragment->Parent(), *fragment)};
 }
 
 NGPaintFragmentTraversalContext NGPaintFragmentTraversal::PreviousInlineLeafOf(
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
index 6006268..9b53d6c 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
@@ -41,10 +41,51 @@
 };
 
 // Utility class for traversing the paint fragment tree.
+//
+// This class has two groups of functions; one is a traversing cursor, by
+// instantiating and using instance functions. The other is a set of static
+// functions that are similar to DOM traversal functions.
 class CORE_EXPORT NGPaintFragmentTraversal {
-  STATIC_ONLY(NGPaintFragmentTraversal);
+  STACK_ALLOCATED();
 
  public:
+  // Create an instance to traverse descendants of |root|.
+  explicit NGPaintFragmentTraversal(const NGPaintFragment& root);
+
+  // Create an instance to traverse descendants of |root|, starting at |start|.
+  // Same as constructing with |root| and then |MoveTo()|.
+  NGPaintFragmentTraversal(const NGPaintFragment& root,
+                           const NGPaintFragment& start);
+
+  bool IsAtEnd() const { return !current_; }
+  explicit operator bool() const { return !IsAtEnd(); }
+
+  const NGPaintFragment* get() const {
+    DCHECK(current_);
+    return current_;
+  }
+  const NGPaintFragment& operator*() const { return *get(); }
+  const NGPaintFragment* operator->() const { return get(); }
+
+  // Move to the specified fragment. The fragment must be a descendant of
+  // |root|. This function is O(n) where |n| is the number of senior siblings
+  // before |fragment|.
+  void MoveTo(const NGPaintFragment& fragment);
+
+  // Move to the next node using the pre-order depth-first-search.
+  void MoveToNext();
+
+  // Move to the next sibling, or next ancestor node using the pre-order
+  // depth-first-search, skipping children of the current node.
+  void MoveToNextSiblingOrAncestor();
+
+  //
+  // Following functions are static, similar to DOM traversal utilities.
+  //
+  // Because fragments have children as a vector, not a two-way list, static
+  // functions are not as cheap as their DOM versions. When traversing more than
+  // once, instace functions are recommended.
+
   // Returns descendants without paint layer in preorder.
   static Vector<NGPaintFragmentWithContainerOffset> DescendantsOf(
       const NGPaintFragment&);
@@ -73,6 +114,28 @@
       const NGPaintFragmentTraversalContext&);
   static NGPaintFragmentTraversalContext NextInlineLeafOfIgnoringLineBreak(
       const NGPaintFragmentTraversalContext&);
+
+ private:
+  void Push(const NGPaintFragment& parent, unsigned index);
+  void Push(const NGPaintFragment& fragment);
+
+  const NGPaintFragment* current_ = nullptr;
+  const NGPaintFragment& root_;
+
+  // The stack of parent and its child index up to the root. Each stack entry
+  // represents the current node, and thus
+  // |stack_.back().parent->Children()[stack_.back().index] == current_|.
+  //
+  // Computing ancestors maybe deferred until |MoveToNextSiblingOrAncestor()|
+  // when |Moveto()| is used. In that case, the |stack_| does not contain all
+  // fragments to the |root_|.
+  struct ParentAndIndex {
+    const NGPaintFragment* parent;
+    unsigned index;
+  };
+  Vector<ParentAndIndex, 4> stack_;
+
+  DISALLOW_COPY_AND_ASSIGN(NGPaintFragmentTraversal);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
index 6482613..f1d0ecd 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
@@ -4,12 +4,15 @@
 
 #include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h"
 
+#include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 
 namespace blink {
 
+using testing::ElementsAreArray;
+
 class NGPaintFragmentTraversalTest : public RenderingTest,
                                      private ScopedLayoutNGForTest {
  public:
@@ -28,10 +31,98 @@
     return root_fragment_->Children();
   }
 
+  Vector<const NGPaintFragment*> ToDepthFirstList(
+      NGPaintFragmentTraversal* traversal) const {
+    Vector<const NGPaintFragment*> results;
+    for (; *traversal; traversal->MoveToNext()) {
+      const NGPaintFragment& fragment = **traversal;
+      results.push_back(&fragment);
+    }
+    return results;
+  }
+
   LayoutBlockFlow* layout_block_flow_;
   NGPaintFragment* root_fragment_;
 };
 
+TEST_F(NGPaintFragmentTraversalTest, MoveToNext) {
+  SetUpHtml("t", R"HTML(
+    <div id=t>
+      line0
+      <span style="background: red">red</span>
+      <br>
+      line1
+    </div>
+  )HTML");
+  NGPaintFragmentTraversal traversal(*root_fragment_);
+  NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+  NGPaintFragment* line1 = root_fragment_->Children()[1].get();
+  NGPaintFragment* span = line0->Children()[1].get();
+  NGPaintFragment* br = line0->Children()[2].get();
+  EXPECT_THAT(ToDepthFirstList(&traversal),
+              ElementsAreArray({line0, line0->Children()[0].get(), span,
+                                span->Children()[0].get(), br, line1,
+                                line1->Children()[0].get()}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveToNextWithRoot) {
+  SetUpHtml("t", R"HTML(
+    <div id=t>
+      line0
+      <span style="background: red">red</span>
+      <br>
+      line1
+    </div>
+  )HTML");
+  NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+  NGPaintFragment* span = line0->Children()[1].get();
+  NGPaintFragment* br = line0->Children()[2].get();
+  NGPaintFragmentTraversal traversal(*line0);
+  EXPECT_THAT(ToDepthFirstList(&traversal),
+              ElementsAreArray({line0->Children()[0].get(), span,
+                                span->Children()[0].get(), br}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveTo) {
+  SetUpHtml("t", R"HTML(
+    <div id=t>
+      line0
+      <span style="background: red">red</span>
+      <br>
+      line1
+    </div>
+  )HTML");
+  NGPaintFragmentTraversal traversal(*root_fragment_);
+  NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+  NGPaintFragment* line1 = root_fragment_->Children()[1].get();
+  NGPaintFragment* span = line0->Children()[1].get();
+  NGPaintFragment* br = line0->Children()[2].get();
+  traversal.MoveTo(*span);
+  EXPECT_EQ(span, &*traversal);
+  EXPECT_THAT(ToDepthFirstList(&traversal),
+              ElementsAreArray({span, span->Children()[0].get(), br, line1,
+                                line1->Children()[0].get()}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveToWithRoot) {
+  SetUpHtml("t", R"HTML(
+    <div id=t>
+      line0
+      <span style="background: red">red</span>
+      <br>
+      line1
+    </div>
+  )HTML");
+  NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+  NGPaintFragment* span = line0->Children()[1].get();
+  NGPaintFragment* br = line0->Children()[2].get();
+  NGPaintFragmentTraversal traversal(*line0);
+  traversal.MoveTo(*span);
+  EXPECT_EQ(span, &*traversal);
+  EXPECT_THAT(ToDepthFirstList(&traversal),
+              ElementsAreArray({span, span->Children()[0].get(), br}));
+}
+
 TEST_F(NGPaintFragmentTraversalTest, PreviousLineOf) {
   SetUpHtml("t", "<div id=t>foo<br>bar</div>");
   ASSERT_EQ(2u, RootChildren().size());
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
index 4e7061d..60f0aa6 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
@@ -248,7 +248,7 @@
   const Color color =
       SelectionBackgroundColor(document, style, text_fragment, text_color);
   const NGPhysicalOffsetRect selection_rect =
-      paint_fragment.ComputeLocalSelectionRect(selection_status);
+      paint_fragment.ComputeLocalSelectionRectForText(selection_status);
   PaintRect(context, NGPhysicalOffset(box_rect.Location()), selection_rect,
             color);
 }
@@ -310,12 +310,12 @@
 
   // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
   // include selection and composition highlights.
-  // Since NGPaintFragment::ComputeLocalSelectionRect() returns
+  // Since NGPaintFragment::ComputeLocalSelectionRectForText() returns
   // NGPhysicalOffsetRect rather than NGLogicalRect, we should paint selection
   // before GraphicsContext flip.
   // TODO(yoichio): Make NGPhysicalTextFragment::LocalRect and
-  // NGPaintFragment::ComputeLocalSelectionRect logical so that we can paint
-  // selection in same fliped dimention as NGTextPainter.
+  // NGPaintFragment::ComputeLocalSelectionRectForText logical so that we can
+  // paint selection in same fliped dimention as NGTextPainter.
   const DocumentMarkerVector& markers_to_paint =
       ComputeMarkersToPaint(fragment_);
   if (paint_info.phase != PaintPhase::kSelection &&
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc
index 4ffc6c7..96cb5bd 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -261,7 +261,7 @@
       frame_selection.ComputeLayoutSelectionStatus(fragment);
   if (status.start == status.end)
     return LayoutRect();
-  return fragment.ComputeLocalSelectionRect(status).ToLayoutRect();
+  return fragment.ComputeLocalSelectionRectForText(status).ToLayoutRect();
 }
 
 LayoutRect PaintInvalidator::MapFragmentLocalRectToVisualRect(
diff --git a/third_party/blink/renderer/core/trustedtypes/BUILD.gn b/third_party/blink/renderer/core/trustedtypes/BUILD.gn
new file mode 100644
index 0000000..36b86dc
--- /dev/null
+++ b/third_party/blink/renderer/core/trustedtypes/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/core/core.gni")
+
+blink_core_sources("trustedtypes") {
+  sources = [
+    "trusted_html.cc",
+    "trusted_html.h",
+    "trusted_script_url.cc",
+    "trusted_script_url.h",
+    "trusted_url.cc",
+    "trusted_url.h",
+  ]
+}
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.cc b/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
similarity index 93%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_html.cc
rename to third_party/blink/renderer/core/trustedtypes/trusted_html.cc
index e1f872d..2b1cf3fa06 100644
--- a/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
 
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h b/third_party/blink/renderer/core/trustedtypes/trusted_html.h
similarity index 80%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h
rename to third_party/blink/renderer/core/trustedtypes/trusted_html.h
index a327102..f9cf7a8b2 100644
--- a/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_html.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_HTML_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_HTML_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_HTML_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_HTML_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -35,4 +35,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_HTML_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_HTML_H_
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.idl b/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
similarity index 100%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_html.idl
rename to third_party/blink/renderer/core/trustedtypes/trusted_html.idl
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.cc b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc
similarity index 90%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.cc
rename to third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc
index 3956b19..bfc4cd9 100644
--- a/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
 
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
similarity index 79%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h
rename to third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
index 4f22b32d..708400d 100644
--- a/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -35,4 +35,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.idl b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
similarity index 100%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.idl
rename to third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.cc b/third_party/blink/renderer/core/trustedtypes/trusted_url.cc
similarity index 92%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_url.cc
rename to third_party/blink/renderer/core/trustedtypes/trusted_url.cc
index ff620436..aca934a 100644
--- a/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.cc
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_url.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
 
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h b/third_party/blink/renderer/core/trustedtypes/trusted_url.h
similarity index 81%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h
rename to third_party/blink/renderer/core/trustedtypes/trusted_url.h
index 2b2f994..09fcec5 100644
--- a/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h
+++ b/third_party/blink/renderer/core/trustedtypes/trusted_url.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_URL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_URL_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_URL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_URL_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -34,4 +34,4 @@
 
 }  // namespace blink
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_URL_H_
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_URL_H_
diff --git a/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.idl b/third_party/blink/renderer/core/trustedtypes/trusted_url.idl
similarity index 100%
rename from third_party/blink/renderer/core/dom/trustedtypes/trusted_url.idl
rename to third_party/blink/renderer/core/trustedtypes/trusted_url.idl
diff --git a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
index 6fbcb7f..166b5d5 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
@@ -2118,12 +2118,9 @@
         break;
       case 'Enter':
         // Accept any available autocompletions and advance to the next field.
-        if (this.textWithCurrentSuggestion() !== this.text()) {
-          this.tabKeyPressed();
-          event.preventDefault();
-          return;
-        }
-        break;
+        this.tabKeyPressed();
+        event.preventDefault();
+        return;
     }
 
     super.onKeyDown(event);
diff --git a/third_party/blink/renderer/modules/battery/battery_manager.cc b/third_party/blink/renderer/modules/battery/battery_manager.cc
index aea017e..826039ea 100644
--- a/third_party/blink/renderer/modules/battery/battery_manager.cc
+++ b/third_party/blink/renderer/modules/battery/battery_manager.cc
@@ -113,8 +113,10 @@
 
 bool BatteryManager::HasPendingActivity() const {
   // Prevent V8 from garbage collecting the wrapper object if there are
-  // event listeners attached to it.
-  return GetExecutionContext() && HasEventListeners();
+  // event listeners or pending promises attached to it.
+  return HasEventListeners() ||
+         (battery_property_ &&
+          battery_property_->GetState() == ScriptPromisePropertyBase::kPending);
 }
 
 void BatteryManager::Trace(blink::Visitor* visitor) {
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
index abe165da..142009f 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
@@ -38,7 +38,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue_impl.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
 #include "third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.h"
@@ -329,7 +329,8 @@
                                  MediaKeys* media_keys,
                                  WebEncryptedMediaSessionType session_type)
     : ContextLifecycleObserver(ExecutionContext::From(script_state)),
-      async_event_queue_(MediaElementEventQueue::Create(GetExecutionContext())),
+      async_event_queue_(EventQueueImpl::Create(GetExecutionContext(),
+                                                TaskType::kMediaElementEvent)),
       media_keys_(media_keys),
       session_type_(session_type),
       expiration_(std::numeric_limits<double>::quiet_NaN()),
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h
index fab052f..caaca9c 100644
--- a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h
+++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h
@@ -41,7 +41,7 @@
 namespace blink {
 
 class DOMException;
-class MediaElementEventQueue;
+class EventQueue;
 class MediaKeys;
 
 // References are held by JS only. However, even if all JS references are
@@ -135,7 +135,7 @@
   void KeysStatusesChange(const WebVector<WebEncryptedMediaKeyInformation>&,
                           bool has_additional_usable_key) override;
 
-  Member<MediaElementEventQueue> async_event_queue_;
+  Member<EventQueue> async_event_queue_;
   std::unique_ptr<WebContentDecryptionModuleSession> session_;
 
   // Used to determine if MediaKeys is still active.
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
index 2cb7c02a..9ea7f8b 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -611,7 +611,6 @@
       transaction_->UnregisterRequest(this);
   }
 
-  event_queue_->CancelAllEvents();
   if (source_.IsIDBCursor())
     source_.GetAsIDBCursor()->ContextWillBeDestroyed();
   if (result_)
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
index d6dadb2..f9a607d 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
@@ -205,6 +205,8 @@
   stopped_ = false;
 }
 
+MediaRecorder::~MediaRecorder() = default;
+
 String MediaRecorder::state() const {
   return StateToString(state_);
 }
diff --git a/third_party/blink/renderer/modules/mediarecorder/media_recorder.h b/third_party/blink/renderer/modules/mediarecorder/media_recorder.h
index 9545319..7597107 100644
--- a/third_party/blink/renderer/modules/mediarecorder/media_recorder.h
+++ b/third_party/blink/renderer/modules/mediarecorder/media_recorder.h
@@ -42,7 +42,7 @@
                                const MediaRecorderOptions& options,
                                ExceptionState& exception_state);
 
-  ~MediaRecorder() override = default;
+  ~MediaRecorder() override;
 
   MediaStream* stream() const { return stream_.Get(); }
   const String& mimeType() const { return mime_type_; }
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.cc b/third_party/blink/renderer/modules/mediasource/media_source.cc
index c79d960..376cadc 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -36,7 +36,7 @@
 #include "third_party/blink/public/platform/web_media_source.h"
 #include "third_party/blink/public/platform/web_source_buffer.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue_impl.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/use_counter.h"
 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
@@ -113,7 +113,8 @@
 MediaSource::MediaSource(ExecutionContext* context)
     : ContextLifecycleObserver(context),
       ready_state_(ClosedKeyword()),
-      async_event_queue_(MediaElementEventQueue::Create(context)),
+      async_event_queue_(
+          EventQueueImpl::Create(context, TaskType::kMediaElementEvent)),
       attached_element_(nullptr),
       source_buffers_(SourceBufferList::Create(GetExecutionContext(),
                                                async_event_queue_.Get())),
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.h b/third_party/blink/renderer/modules/mediasource/media_source.h
index 2e48d65..3b8078b 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.h
+++ b/third_party/blink/renderer/modules/mediasource/media_source.h
@@ -46,8 +46,8 @@
 
 namespace blink {
 
+class EventQueue;
 class ExceptionState;
-class MediaElementEventQueue;
 class WebSourceBuffer;
 
 class MediaSource final : public EventTargetWithInlineData,
@@ -146,7 +146,7 @@
 
   std::unique_ptr<WebMediaSource> web_media_source_;
   AtomicString ready_state_;
-  Member<MediaElementEventQueue> async_event_queue_;
+  Member<EventQueue> async_event_queue_;
   WeakMember<HTMLMediaElement> attached_element_;
 
   Member<SourceBufferList> source_buffers_;
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.cc b/third_party/blink/renderer/modules/mediasource/source_buffer.cc
index 91a2523..5fe52c2 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer.cc
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer.cc
@@ -37,7 +37,7 @@
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_source_buffer.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue_impl.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/use_counter.h"
@@ -106,7 +106,7 @@
 SourceBuffer* SourceBuffer::Create(
     std::unique_ptr<WebSourceBuffer> web_source_buffer,
     MediaSource* source,
-    MediaElementEventQueue* async_event_queue) {
+    EventQueue* async_event_queue) {
   SourceBuffer* source_buffer =
       new SourceBuffer(std::move(web_source_buffer), source, async_event_queue);
   source_buffer->PauseIfNeeded();
@@ -115,7 +115,7 @@
 
 SourceBuffer::SourceBuffer(std::unique_ptr<WebSourceBuffer> web_source_buffer,
                            MediaSource* source,
-                           MediaElementEventQueue* async_event_queue)
+                           EventQueue* async_event_queue)
     : PausableObject(source->GetExecutionContext()),
       web_source_buffer_(std::move(web_source_buffer)),
       source_(source),
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer.h b/third_party/blink/renderer/modules/mediasource/source_buffer.h
index bfb3458..981ed05a 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer.h
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer.h
@@ -47,8 +47,8 @@
 class AudioTrackList;
 class DOMArrayBuffer;
 class DOMArrayBufferView;
+class EventQueue;
 class ExceptionState;
-class MediaElementEventQueue;
 class MediaSource;
 class TimeRanges;
 class VideoTrackList;
@@ -65,7 +65,7 @@
  public:
   static SourceBuffer* Create(std::unique_ptr<WebSourceBuffer>,
                               MediaSource*,
-                              MediaElementEventQueue*);
+                              EventQueue*);
   static const AtomicString& SegmentsKeyword();
   static const AtomicString& SequenceKeyword();
 
@@ -119,9 +119,7 @@
   void Trace(blink::Visitor*) override;
 
  private:
-  SourceBuffer(std::unique_ptr<WebSourceBuffer>,
-               MediaSource*,
-               MediaElementEventQueue*);
+  SourceBuffer(std::unique_ptr<WebSourceBuffer>, MediaSource*, EventQueue*);
   void Dispose();
 
   bool IsRemoved() const;
@@ -160,7 +158,7 @@
   std::unique_ptr<WebSourceBuffer> web_source_buffer_;
   Member<MediaSource> source_;
   Member<TrackDefaultList> track_defaults_;
-  Member<MediaElementEventQueue> async_event_queue_;
+  Member<EventQueue> async_event_queue_;
 
   AtomicString mode_;
   bool updating_;
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc b/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc
index e52c53cf..7c86cfe 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc
@@ -30,14 +30,14 @@
 
 #include "third_party/blink/renderer/modules/mediasource/source_buffer_list.h"
 
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue.h"
 #include "third_party/blink/renderer/modules/event_modules.h"
 #include "third_party/blink/renderer/modules/mediasource/source_buffer.h"
 
 namespace blink {
 
 SourceBufferList::SourceBufferList(ExecutionContext* context,
-                                   MediaElementEventQueue* async_event_queue)
+                                   EventQueue* async_event_queue)
     : ContextClient(context), async_event_queue_(async_event_queue) {}
 
 SourceBufferList::~SourceBufferList() = default;
diff --git a/third_party/blink/renderer/modules/mediasource/source_buffer_list.h b/third_party/blink/renderer/modules/mediasource/source_buffer_list.h
index ee7d52f..1a5fa60 100644
--- a/third_party/blink/renderer/modules/mediasource/source_buffer_list.h
+++ b/third_party/blink/renderer/modules/mediasource/source_buffer_list.h
@@ -37,8 +37,8 @@
 
 namespace blink {
 
+class EventQueue;
 class SourceBuffer;
-class MediaElementEventQueue;
 
 class SourceBufferList final : public EventTargetWithInlineData,
                                public ContextClient {
@@ -47,7 +47,7 @@
 
  public:
   static SourceBufferList* Create(ExecutionContext* context,
-                                  MediaElementEventQueue* async_event_queue) {
+                                  EventQueue* async_event_queue) {
     return new SourceBufferList(context, async_event_queue);
   }
   ~SourceBufferList() override;
@@ -79,11 +79,11 @@
   void Trace(blink::Visitor*) override;
 
  private:
-  SourceBufferList(ExecutionContext*, MediaElementEventQueue*);
+  SourceBufferList(ExecutionContext*, EventQueue*);
 
   void ScheduleEvent(const AtomicString&);
 
-  Member<MediaElementEventQueue> async_event_queue_;
+  Member<EventQueue> async_event_queue_;
 
   HeapVector<Member<SourceBuffer>> list_;
 };
diff --git a/third_party/blink/renderer/modules/presentation/presentation_connection.h b/third_party/blink/renderer/modules/presentation/presentation_connection.h
index 0cda9903..4012e75 100644
--- a/third_party/blink/renderer/modules/presentation/presentation_connection.h
+++ b/third_party/blink/renderer/modules/presentation/presentation_connection.h
@@ -28,6 +28,7 @@
 class PresentationController;
 class PresentationReceiver;
 class PresentationRequest;
+class WebString;
 
 class PresentationConnection : public EventTargetWithInlineData,
                                public ContextLifecycleObserver,
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc
index 036547f..f736e3d 100644
--- a/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -37,6 +37,8 @@
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/noncopyable.h"
 
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc
index d71441a..ce7888f 100644
--- a/third_party/blink/renderer/platform/heap/heap_page.cc
+++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -1770,4 +1770,67 @@
 }
 #endif
 
+ALWAYS_INLINE uint32_t RotateLeft16(uint32_t x) {
+#if defined(COMPILER_MSVC)
+  return _lrotr(x, 16);
+#else
+  // http://blog.regehr.org/archives/1063
+  return (x << 16) | (x >> (-16 & 31));
+#endif
+}
+
+uint32_t ComputeRandomMagic() {
+// Ignore C4319: It is OK to 0-extend into the high-order bits of the uintptr_t
+// on 64-bit, in this case.
+#if defined(COMPILER_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4319)
+#endif
+
+  const uintptr_t random1 = ~(RotateLeft16(reinterpret_cast<uintptr_t>(
+      base::trace_event::MemoryAllocatorDump::kNameSize)));
+
+#if defined(OS_WIN)
+  const uintptr_t random2 =
+      ~(RotateLeft16(reinterpret_cast<uintptr_t>(::ReadFile)));
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+  const uintptr_t random2 =
+      ~(RotateLeft16(reinterpret_cast<uintptr_t>(::read)));
+#endif
+
+#if defined(ARCH_CPU_64_BITS)
+  static_assert(sizeof(uintptr_t) == sizeof(uint64_t),
+                "uintptr_t is not uint64_t");
+  const uint32_t random = static_cast<uint32_t>(
+      (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL));
+#elif defined(ARCH_CPU_32_BITS)
+  // Although we don't use heap metadata canaries on 32-bit due to memory
+  // pressure, keep this code around just in case we do, someday.
+  static_assert(sizeof(uintptr_t) == sizeof(uint32_t),
+                "uintptr_t is not uint32_t");
+  const uint32_t random = (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL);
+#else
+#error architecture not supported
+#endif
+
+#if defined(COMPILER_MSVC)
+#pragma warning(pop)
+#endif
+
+  return random;
+}
+
+#if defined(ARCH_CPU_64_BITS)
+// Returns a random magic value.
+uint32_t HeapObjectHeader::GetMagic() {
+  static const uint32_t magic = ComputeRandomMagic() ^ 0x6e0b6ead;
+  return magic;
+}
+#endif  // defined(ARCH_CPU_64_BITS)
+
+uint32_t BasePage::GetMagic() {
+  static const uint32_t magic = ComputeRandomMagic() ^ 0xba5e4a9e;
+  return magic;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/heap_page.h b/third_party/blink/renderer/platform/heap/heap_page.h
index 860fb45..462a294 100644
--- a/third_party/blink/renderer/platform/heap/heap_page.h
+++ b/third_party/blink/renderer/platform/heap/heap_page.h
@@ -33,7 +33,6 @@
 
 #include <stdint.h>
 #include "base/bits.h"
-#include "base/trace_event/memory_allocator_dump.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/heap/blink_gc.h"
 #include "third_party/blink/renderer/platform/heap/gc_info.h"
@@ -47,6 +46,12 @@
 #include "third_party/blink/renderer/platform/wtf/container_annotations.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
+namespace base {
+namespace trace_event {
+class MemoryAllocatorDump;
+}  // namespace trace_event
+}  // namespace base
+
 namespace blink {
 
 // TODO(palmer): Document the reason for 17.
@@ -136,7 +141,7 @@
 // should be fast and small, and should have the benefit of requiring
 // attackers to discover and use 2 independent weak infoleak bugs, or 1
 // arbitrary infoleak bug (used twice).
-inline uint32_t GetRandomMagic();
+uint32_t ComputeRandomMagic();
 
 // HeapObjectHeader is a 64-bit (64-bit platforms) or 32-bit (32-bit platforms)
 // object that has the following layout:
@@ -247,7 +252,7 @@
 
 #if defined(ARCH_CPU_64_BITS)
   // Returns a random magic value.
-  uint32_t GetMagic() const { return GetRandomMagic() ^ 0x6e0b6ead; }
+  static uint32_t GetMagic();
   uint32_t magic_;
 #endif  // defined(ARCH_CPU_64_BITS)
 
@@ -418,7 +423,7 @@
 
  private:
   // Returns a random magic value.
-  uint32_t GetMagic() const { return GetRandomMagic() ^ 0xba5e4a9e; }
+  PLATFORM_EXPORT static uint32_t GetMagic();
 
   uint32_t const magic_;
   PageMemory* const storage_;
@@ -951,57 +956,6 @@
   (void)FromPayload(payload);
 }
 
-ALWAYS_INLINE uint32_t RotateLeft16(uint32_t x) {
-#if defined(COMPILER_MSVC)
-  return _lrotr(x, 16);
-#else
-  // http://blog.regehr.org/archives/1063
-  return (x << 16) | (x >> (-16 & 31));
-#endif
-}
-
-inline uint32_t GetRandomMagic() {
-// Ignore C4319: It is OK to 0-extend into the high-order bits of the uintptr_t
-// on 64-bit, in this case.
-#if defined(COMPILER_MSVC)
-#pragma warning(push)
-#pragma warning(disable : 4319)
-#endif
-
-  static const uintptr_t random1 = ~(RotateLeft16(reinterpret_cast<uintptr_t>(
-      base::trace_event::MemoryAllocatorDump::kNameSize)));
-
-#if defined(OS_WIN)
-  static const uintptr_t random2 =
-      ~(RotateLeft16(reinterpret_cast<uintptr_t>(::ReadFile)));
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
-  static const uintptr_t random2 =
-      ~(RotateLeft16(reinterpret_cast<uintptr_t>(::read)));
-#endif
-
-#if defined(ARCH_CPU_64_BITS)
-  static_assert(sizeof(uintptr_t) == sizeof(uint64_t),
-                "uintptr_t is not uint64_t");
-  static const uint32_t random = static_cast<uint32_t>(
-      (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL));
-#elif defined(ARCH_CPU_32_BITS)
-  // Although we don't use heap metadata canaries on 32-bit due to memory
-  // pressure, keep this code around just in case we do, someday.
-  static_assert(sizeof(uintptr_t) == sizeof(uint32_t),
-                "uintptr_t is not uint32_t");
-  static const uint32_t random =
-      (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL);
-#else
-#error architecture not supported
-#endif
-
-#if defined(COMPILER_MSVC)
-#pragma warning(pop)
-#endif
-
-  return random;
-}
-
 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsWrapperHeaderMarked()
     const {
   CheckHeader();
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index a691142..acb593e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -34,6 +34,7 @@
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/resource_request_blocked_reason.h"
@@ -197,7 +198,10 @@
     return ResourceRequestBlockedReason::kOther;
   }
 
-  virtual bool IsControlledByServiceWorker() const { return false; }
+  virtual blink::mojom::ControllerServiceWorkerMode
+  IsControlledByServiceWorker() const {
+    return blink::mojom::ControllerServiceWorkerMode::kNoController;
+  }
   virtual int64_t ServiceWorkerID() const { return -1; }
   virtual int ApplicationCacheHostID() const {
     return WebApplicationCacheHost::kAppCacheNoHostId;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index b3271e8..89b84a0 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -51,6 +51,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
 #include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
 #include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/network/network_instrumentation.h"
 #include "third_party/blink/renderer/platform/network/network_utils.h"
 #include "third_party/blink/renderer/platform/probe/platform_probes.h"
@@ -387,7 +388,8 @@
   resources_from_previous_fetcher_.clear();
 }
 
-bool ResourceFetcher::IsControlledByServiceWorker() const {
+blink::mojom::ControllerServiceWorkerMode
+ResourceFetcher::IsControlledByServiceWorker() const {
   return Context().IsControlledByServiceWorker();
 }
 
@@ -909,7 +911,8 @@
   DCHECK(resource->IsLoaded());
   DCHECK(resource->CanUseCacheValidator());
   DCHECK(!resource->IsCacheValidator());
-  DCHECK(!Context().IsControlledByServiceWorker());
+  DCHECK(Context().IsControlledByServiceWorker() ==
+         blink::mojom::ControllerServiceWorkerMode::kNoController);
   // RawResource doesn't support revalidation.
   CHECK(!IsRawResource(*resource));
 
@@ -1275,8 +1278,14 @@
     // is controlled by the ServiceWorker, we choose the Reload policy because
     // the revalidation headers should not be exposed to the
     // ServiceWorker.(crbug.com/429570)
+    //
+    // TODO(falken): If the controller has no fetch event handler, we probably
+    // can treat it as not being controlled in the S13nSW case. In the
+    // non-S13nSW, we don't know what controller the request will ultimately go
+    // to (due to skipWaiting) so be conservative.
     if (existing_resource.CanUseCacheValidator() &&
-        !Context().IsControlledByServiceWorker()) {
+        Context().IsControlledByServiceWorker() ==
+            blink::mojom::ControllerServiceWorkerMode::kNoController) {
       // If the resource is already a cache validator but not started yet, the
       // |Use| policy should be applied to subsequent requests.
       if (existing_resource.IsCacheValidator()) {
@@ -1686,7 +1695,8 @@
 }
 
 String ResourceFetcher::GetCacheIdentifier() const {
-  if (Context().IsControlledByServiceWorker())
+  if (Context().IsControlledByServiceWorker() !=
+      blink::mojom::ControllerServiceWorkerMode::kNoController)
     return String::Number(Context().ServiceWorkerID());
   return MemoryCache::DefaultCacheIdentifier();
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 2ce6fc7..f3cc44f 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -28,6 +28,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_FETCHER_H_
 
 #include <memory>
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
@@ -141,7 +142,7 @@
   void HandleLoaderError(Resource*,
                          const ResourceError&,
                          uint32_t inflight_keepalive_bytes);
-  bool IsControlledByServiceWorker() const;
+  blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const;
 
   String GetCacheIdentifier() const;
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index b3da008..d12e78c 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -825,8 +825,10 @@
     return;
 
   // Don't activate if the page is controlled by service worker.
-  if (fetcher_->IsControlledByServiceWorker())
+  if (fetcher_->IsControlledByServiceWorker() !=
+      blink::mojom::ControllerServiceWorkerMode::kNoController) {
     return;
+  }
 
   is_cache_aware_loading_activated_ = true;
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
index 8a6ac54..aabeebe9 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -30,6 +30,7 @@
 
 #include "base/unguessable_token.h"
 #include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/network/http_names.h"
 #include "third_party/blink/renderer/platform/network/network_utils.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -128,6 +129,8 @@
 
 ResourceRequest::ResourceRequest(const ResourceRequest&) = default;
 
+ResourceRequest::~ResourceRequest() = default;
+
 ResourceRequest& ResourceRequest::operator=(const ResourceRequest&) = default;
 
 std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
@@ -470,4 +473,8 @@
   return true;
 }
 
+CrossThreadResourceRequestData::CrossThreadResourceRequestData() = default;
+
+CrossThreadResourceRequestData::~CrossThreadResourceRequestData() = default;
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index 1a05755..cebfb98 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -41,13 +41,11 @@
 #include "third_party/blink/public/platform/web_content_security_policy_struct.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
-#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
 #include "third_party/blink/renderer/platform/network/http_header_map.h"
 #include "third_party/blink/renderer/platform/network/http_names.h"
 #include "third_party/blink/renderer/platform/network/http_parsers.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/weborigin/referrer.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 
 namespace blink {
@@ -80,6 +78,8 @@
   ResourceRequest(const ResourceRequest&);
   ResourceRequest& operator=(const ResourceRequest&);
 
+  ~ResourceRequest();
+
   // Constructs a new ResourceRequest for a redirect from this instance.
   std::unique_ptr<ResourceRequest> CreateRedirectRequest(
       const KURL& new_url,
@@ -448,12 +448,14 @@
 //    threads (e.g., AtomicString)
 //  - Non-simple members need explicit copying (e.g., String::IsolatedCopy,
 //    KURL::Copy) rather than the copy constructor or the assignment operator.
-struct CrossThreadResourceRequestData {
+struct PLATFORM_EXPORT CrossThreadResourceRequestData {
   WTF_MAKE_NONCOPYABLE(CrossThreadResourceRequestData);
   USING_FAST_MALLOC(CrossThreadResourceRequestData);
 
  public:
-  CrossThreadResourceRequestData() = default;
+  CrossThreadResourceRequestData();
+  ~CrossThreadResourceRequestData();
+
   KURL url_;
 
   mojom::FetchCacheMode cache_mode_;
diff --git a/third_party/closure_compiler/compiled_resources2.gyp b/third_party/closure_compiler/compiled_resources2.gyp
index 7eddef4..1ab2cdf 100644
--- a/third_party/closure_compiler/compiled_resources2.gyp
+++ b/third_party/closure_compiler/compiled_resources2.gyp
@@ -14,10 +14,6 @@
       'target_name': 'compiled_resources2',
       'type': 'none',
       'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_components/compiled_resources2.gyp:*',
-        '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:*',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:*',
-        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:*',
       ],
     },
   ]
diff --git a/third_party/closure_compiler/externs/accessibility_private.js b/third_party/closure_compiler/externs/accessibility_private.js
index 7cb7cf0..903fdf8 100644
--- a/third_party/closure_compiler/externs/accessibility_private.js
+++ b/third_party/closure_compiler/externs/accessibility_private.js
@@ -21,7 +21,6 @@
  * @typedef {{
  *   message: string
  * }}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-AlertInfo
  */
 chrome.accessibilityPrivate.AlertInfo;
 
@@ -33,13 +32,11 @@
  *   width: number,
  *   height: number
  * }}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-ScreenRect
  */
 chrome.accessibilityPrivate.ScreenRect;
 
 /**
  * @enum {string}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-Gesture
  */
 chrome.accessibilityPrivate.Gesture = {
   CLICK: 'click',
@@ -63,7 +60,6 @@
 
 /**
  * @enum {string}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-SyntheticKeyboardEventType
  */
 chrome.accessibilityPrivate.SyntheticKeyboardEventType = {
   KEYUP: 'keyup',
@@ -77,7 +73,6 @@
  *   search: (boolean|undefined),
  *   shift: (boolean|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-SyntheticKeyboardModifiers
  */
 chrome.accessibilityPrivate.SyntheticKeyboardModifiers;
 
@@ -87,13 +82,11 @@
  *   keyCode: number,
  *   modifiers: (!chrome.accessibilityPrivate.SyntheticKeyboardModifiers|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-SyntheticKeyboardEvent
  */
 chrome.accessibilityPrivate.SyntheticKeyboardEvent;
 
 /**
  * @enum {string}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-KeyboardMode
  */
 chrome.accessibilityPrivate.KeyboardMode = {
   FULL_WIDTH: 'FULL_WIDTH',
@@ -102,7 +95,6 @@
 
 /**
  * @enum {string}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#type-SelectToSpeakState
  */
 chrome.accessibilityPrivate.SelectToSpeakState = {
   SELECTING: 'selecting',
@@ -115,7 +107,6 @@
  * the calling extension to provide accessibility for web contents.
  * @param {boolean} enabled True if native accessibility support should be
  *     enabled.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-setNativeAccessibilityEnabled
  */
 chrome.accessibilityPrivate.setNativeAccessibilityEnabled = function(enabled) {};
 
@@ -125,7 +116,6 @@
  *     rectangles to draw the accessibility focus ring around.
  * @param {string=} color CSS-style hex color string beginning with # like
  *     #FF9982 or #EEE.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-setFocusRing
  */
 chrome.accessibilityPrivate.setFocusRing = function(rects, color) {};
 
@@ -135,7 +125,6 @@
  *     rectangles to draw the highlight around.
  * @param {string} color CSS-style hex color string beginning with # like
  *     #FF9982 or #EEE.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-setHighlights
  */
 chrome.accessibilityPrivate.setHighlights = function(rects, color) {};
 
@@ -149,14 +138,12 @@
  * @param {boolean} capture True if key events should be swallowed natively and
  *     not propagated if preventDefault() gets called by the extension's
  *     background page.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-setKeyboardListener
  */
 chrome.accessibilityPrivate.setKeyboardListener = function(enabled, capture) {};
 
 /**
  * Darkens or undarkens the screen.
  * @param {boolean} enabled True to darken screen; false to undarken screen.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-darkenScreen
  */
 chrome.accessibilityPrivate.darkenScreen = function(enabled) {};
 
@@ -164,14 +151,12 @@
  * Change the keyboard keys captured by Switch Access.
  * @param {!Array<number>} key_codes The key codes for the keys that will be
  *     captured.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-setSwitchAccessKeys
  */
 chrome.accessibilityPrivate.setSwitchAccessKeys = function(key_codes) {};
 
 /**
  * Sets current ARC app to use native ARC support.
  * @param {boolean} enabled True for ChromeVox (native), false for TalkBack.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-setNativeChromeVoxArcSupportForCurrentApp
  */
 chrome.accessibilityPrivate.setNativeChromeVoxArcSupportForCurrentApp = function(enabled) {};
 
@@ -179,14 +164,12 @@
  * Sends a fabricated key event.
  * @param {!chrome.accessibilityPrivate.SyntheticKeyboardEvent} keyEvent The
  *     event to send.
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-sendSyntheticKeyEvent
  */
 chrome.accessibilityPrivate.sendSyntheticKeyEvent = function(keyEvent) {};
 
 /**
  * Fired whenever ChromeVox should output introduction.
  * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#event-onIntroduceChromeVox
  */
 chrome.accessibilityPrivate.onIntroduceChromeVox;
 
@@ -194,7 +177,6 @@
  * Fired when an accessibility gesture is detected by the touch exploration
  * controller.
  * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#event-onAccessibilityGesture
  */
 chrome.accessibilityPrivate.onAccessibilityGesture;
 
@@ -202,7 +184,6 @@
  * Fired when we first detect two fingers are held down, which can be used to
  * toggle spoken feedback on some touch-only devices.
  * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#event-onTwoFingerTouchStart
  */
 chrome.accessibilityPrivate.onTwoFingerTouchStart;
 
@@ -210,7 +191,6 @@
  * Fired when  the user is no longer holding down two fingers (including
  * releasing one, holding down three, or moving them).
  * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#event-onTwoFingerTouchStop
  */
 chrome.accessibilityPrivate.onTwoFingerTouchStop;
 
@@ -219,7 +199,6 @@
  * between selecting with the mouse, speaking, and inactive.
  * @param {!chrome.accessibilityPrivate.SelectToSpeakState} state The current
  *    state of the Select-to-Speak extension
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#method-onSelectToSpeakStateChanged
  */
 chrome.accessibilityPrivate.onSelectToSpeakStateChanged = function(state) {};
 
@@ -227,6 +206,5 @@
  * Called when Chrome OS wants to toggle the Select-to-Speak state, between selecting
  * with the mouse, speaking, and inactive
  * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/accessibilityPrivate#event-onSelectToSpeakStateChangeRequested
  */
 chrome.accessibilityPrivate.onSelectToSpeakStateChangeRequested;
diff --git a/third_party/closure_compiler/externs/autofill_private.js b/third_party/closure_compiler/externs/autofill_private.js
index e069ae9..40baff7 100644
--- a/third_party/closure_compiler/externs/autofill_private.js
+++ b/third_party/closure_compiler/externs/autofill_private.js
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2018 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.
 
@@ -18,7 +18,6 @@
 
 /**
  * @enum {string}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressField
  */
 chrome.autofillPrivate.AddressField = {
   FULL_NAME: 'FULL_NAME',
@@ -39,7 +38,6 @@
  *   isLocal: (boolean|undefined),
  *   isCached: (boolean|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-AutofillMetadata
  */
 chrome.autofillPrivate.AutofillMetadata;
 
@@ -60,7 +58,6 @@
  *   languageCode: (string|undefined),
  *   metadata: (!chrome.autofillPrivate.AutofillMetadata|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressEntry
  */
 chrome.autofillPrivate.AddressEntry;
 
@@ -69,7 +66,6 @@
  *   name: (string|undefined),
  *   countryCode: (string|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-CountryEntry
  */
 chrome.autofillPrivate.CountryEntry;
 
@@ -80,7 +76,6 @@
  *   isLongField: boolean,
  *   placeholder: (string|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressComponent
  */
 chrome.autofillPrivate.AddressComponent;
 
@@ -88,7 +83,6 @@
  * @typedef {{
  *   row: !Array<!chrome.autofillPrivate.AddressComponent>
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressComponentRow
  */
 chrome.autofillPrivate.AddressComponentRow;
 
@@ -97,7 +91,6 @@
  *   components: !Array<!chrome.autofillPrivate.AddressComponentRow>,
  *   languageCode: string
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressComponents
  */
 chrome.autofillPrivate.AddressComponents;
 
@@ -110,7 +103,6 @@
  *   expirationYear: (string|undefined),
  *   metadata: (!chrome.autofillPrivate.AutofillMetadata|undefined)
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-CreditCardEntry
  */
 chrome.autofillPrivate.CreditCardEntry;
 
@@ -120,7 +112,6 @@
  *   indexOfNewNumber: number,
  *   countryCode: string
  * }}
- * @see https://developer.chrome.com/extensions/autofillPrivate#type-ValidatePhoneParams
  */
 chrome.autofillPrivate.ValidatePhoneParams;
 
@@ -129,7 +120,6 @@
  * be assigned a new one and added as a new entry.
  * @param {!chrome.autofillPrivate.AddressEntry} address The address entry to
  *     save.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-saveAddress
  */
 chrome.autofillPrivate.saveAddress = function(address) {};
 
@@ -137,7 +127,6 @@
  * Gets the list of all countries.
  * @param {function(!Array<!chrome.autofillPrivate.CountryEntry>):void} callback
  *     Callback which will be called with the countries.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-getCountryList
  */
 chrome.autofillPrivate.getCountryList = function(callback) {};
 
@@ -148,7 +137,6 @@
  *     for a     list of valid codes.
  * @param {function(!chrome.autofillPrivate.AddressComponents):void} callback
  *     Callback which will be called with components.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-getAddressComponents
  */
 chrome.autofillPrivate.getAddressComponents = function(countryCode, callback) {};
 
@@ -156,7 +144,6 @@
  * Gets the list of addresses.
  * @param {function(!Array<!chrome.autofillPrivate.AddressEntry>):void} callback
  *     Callback which will be called with the list of addresses.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-getAddressList
  */
 chrome.autofillPrivate.getAddressList = function(callback) {};
 
@@ -164,14 +151,12 @@
  * Saves the given credit card. If |card| has an empty string as its ID, it will
  * be assigned a new one and added as a new entry.
  * @param {!chrome.autofillPrivate.CreditCardEntry} card The card entry to save.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-saveCreditCard
  */
 chrome.autofillPrivate.saveCreditCard = function(card) {};
 
 /**
  * Removes the entry (address or credit card) with the given ID.
  * @param {string} guid ID of the entry to remove.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-removeEntry
  */
 chrome.autofillPrivate.removeEntry = function(guid) {};
 
@@ -183,7 +168,6 @@
  *     this function.
  * @param {function(!Array<string>):void} callback Callback which will be called
  *     with validated phone numbers.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-validatePhoneNumbers
  */
 chrome.autofillPrivate.validatePhoneNumbers = function(params, callback) {};
 
@@ -191,7 +175,6 @@
  * Gets the list of credit cards.
  * @param {function(!Array<!chrome.autofillPrivate.CreditCardEntry>):void}
  *     callback Callback which will be called with the list of credit cards.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-getCreditCardList
  */
 chrome.autofillPrivate.getCreditCardList = function(callback) {};
 
@@ -199,7 +182,6 @@
  * Clears the data associated with a wallet card which was saved locally so that
  * the saved copy is masked (e.g., "Card ending in 1234").
  * @param {string} guid GUID of the credit card to mask.
- * @see https://developer.chrome.com/extensions/autofillPrivate#method-maskCreditCard
  */
 chrome.autofillPrivate.maskCreditCard = function(guid) {};
 
@@ -207,7 +189,6 @@
  * Fired when the address list has changed, meaning that an entry has been
  * added, removed, or changed. |entries| The updated list of entries.
  * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/autofillPrivate#event-onAddressListChanged
  */
 chrome.autofillPrivate.onAddressListChanged;
 
@@ -215,6 +196,5 @@
  * Fired when the credit card list has changed, meaning that an entry has been
  * added, removed, or changed. |entries| The updated list of entries.
  * @type {!ChromeEvent}
- * @see https://developer.chrome.com/extensions/autofillPrivate#event-onCreditCardListChanged
  */
 chrome.autofillPrivate.onCreditCardListChanged;
diff --git a/third_party/closure_compiler/externs/compiled_resources2.gyp b/third_party/closure_compiler/externs/compiled_resources2.gyp
deleted file mode 100644
index 3ebf158..0000000
--- a/third_party/closure_compiler/externs/compiled_resources2.gyp
+++ /dev/null
@@ -1,157 +0,0 @@
-# Copyright 2018 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.
-
-########################################################
-#    NOTE: THIS FILE IS GENERATED. DO NOT EDIT IT!     #
-# Instead, run create_include_gyp.py to regenerate it. #
-########################################################
-{
-  'targets': [
-    {
-      'target_name': 'accessibility_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'autofill_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'automation',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'bluetooth',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'bluetooth_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'bookmark_manager_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'chrome',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'chrome_extensions',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'chrome_send',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'clipboard',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'command_line_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'developer_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'file_manager_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'input_method_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'language_settings_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'management',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'media_player_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'metrics_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'mime_handler_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'mojo',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'networking_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'passwords_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'pending',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'polymer-1.0',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'quick_unlock_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'settings_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'system_display',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'system_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'users_private',
-      'dependencies': ['chrome'],
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'web_animations',
-      'includes': ['../include_js.gypi'],
-    },
-  ],
-}
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js
index fb3103e..bb81dcd 100644
--- a/third_party/closure_compiler/externs/file_manager_private.js
+++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -898,7 +898,7 @@
  * Requests fetching list of actions for the specified set of entries. If not
  * possible, then returns an error via chrome.runtime.lastError.
  * @param {!Array<!Entry>} entries
- * @param {function((!Array<!EntryAction>|undefined))} callback
+ * @param {function((!Array<!chrome.fileSystemProvider.Action>|undefined))} callback
  */
 chrome.fileManagerPrivate.getCustomActions = function(entries, callback) {};
 
@@ -967,17 +967,3 @@
 
 /** @type {!ChromeEvent} */
 chrome.fileManagerPrivate.onAppsUpdated;
-
-/* The declaration below (EntryAction) doesn't have any corresponding entry in
- * the file_manager_private.idl file.
- *
- * TODO(nigeltao): delete it.
- */
-
-/**
- * @typedef {{
- *   id: string,
- *   title: (string|undefined)
- * }}
- */
-var EntryAction;
diff --git a/third_party/closure_compiler/interfaces/compiled_resources2.gyp b/third_party/closure_compiler/interfaces/compiled_resources2.gyp
deleted file mode 100644
index 2c985b7..0000000
--- a/third_party/closure_compiler/interfaces/compiled_resources2.gyp
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-########################################################
-#    NOTE: THIS FILE IS GENERATED. DO NOT EDIT IT!     #
-# Instead, run create_include_gyp.py to regenerate it. #
-########################################################
-{
-  'targets': [
-    {
-      'target_name': 'bluetooth_interface',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'bluetooth_private_interface',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'input_method_private_interface',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'language_settings_private_interface',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'networking_private_interface',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'quick_unlock_private_interface',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'settings_private_interface',
-      'includes': ['../include_js.gypi'],
-    },
-    {
-      'target_name': 'system_display_interface',
-      'includes': ['../include_js.gypi'],
-    },
-  ],
-}
diff --git a/third_party/jstemplate/compiled_resources2.gyp b/third_party/jstemplate/compiled_resources2.gyp
deleted file mode 100644
index b193c46..0000000
--- a/third_party/jstemplate/compiled_resources2.gyp
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'util',
-      'includes': ['../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'jsevalcontext',
-      'dependencies': ['util'],
-      'includes': ['../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'jstemplate',
-      'dependencies': ['jsevalcontext'],
-      'includes': ['../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp
deleted file mode 100644
index c3171eb..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-a11y-announcer/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-a11y-announcer-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp
deleted file mode 100644
index a1d06147..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-a11y-keys-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/compiled_resources2.gyp
deleted file mode 100644
index 0de5ffaa..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-a11y-keys/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-a11y-keys-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/compiled_resources2.gyp
deleted file mode 100644
index 402c2ad..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-autogrow-textarea/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-autogrow-textarea-extracted',
-      'dependencies': [
-        '../iron-behaviors/compiled_resources2.gyp:iron-control-state-extracted',
-        '../iron-validatable-behavior/compiled_resources2.gyp:iron-validatable-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp
deleted file mode 100644
index fdf697c..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-button-state-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        'iron-control-state-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-control-state-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/compiled_resources2.gyp
deleted file mode 100644
index b4d42c0..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-checked-element-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-checked-element-behavior-extracted',
-      'dependencies': [
-        '../iron-form-element-behavior/compiled_resources2.gyp:iron-form-element-behavior-extracted',
-        '../iron-validatable-behavior/compiled_resources2.gyp:iron-validatable-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-collapse/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-collapse/compiled_resources2.gyp
deleted file mode 100644
index 0600d09..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-collapse/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-collapse-extracted',
-      'dependencies': [
-        '../iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-dropdown/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-dropdown/compiled_resources2.gyp
deleted file mode 100644
index 35bb339..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-dropdown/compiled_resources2.gyp
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-dropdown-extracted',
-      'dependencies': [
-        '../iron-behaviors/compiled_resources2.gyp:iron-control-state-extracted',
-        '../iron-overlay-behavior/compiled_resources2.gyp:iron-overlay-behavior-extracted',
-        '../neon-animation/compiled_resources2.gyp:neon-animation-runner-behavior-extracted',
-        'iron-dropdown-scroll-manager-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-dropdown-scroll-manager-extracted',
-      'dependencies': [
-        '../iron-overlay-behavior/compiled_resources2.gyp:iron-scroll-manager-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/compiled_resources2.gyp
deleted file mode 100644
index b6399e8..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-fit-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-fit-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/compiled_resources2.gyp
deleted file mode 100644
index e3fba416..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-form-element-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-form-element-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-icon/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-icon/compiled_resources2.gyp
deleted file mode 100644
index 906834e3..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-icon/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-icon-extracted',
-      'dependencies': [
-        '../iron-meta/compiled_resources2.gyp:iron-meta-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-iconset-svg/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-iconset-svg/compiled_resources2.gyp
deleted file mode 100644
index 55dea74..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-iconset-svg/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-iconset-svg-extracted',
-      'dependencies': [
-        '../iron-meta/compiled_resources2.gyp:iron-meta-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-input/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-input/compiled_resources2.gyp
deleted file mode 100644
index ad85f88f..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-input/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-input-extracted',
-      'dependencies': [
-        '../iron-a11y-announcer/compiled_resources2.gyp:iron-a11y-announcer-extracted',
-        '../iron-validatable-behavior/compiled_resources2.gyp:iron-validatable-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-list/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-list/compiled_resources2.gyp
deleted file mode 100644
index 2fd96ad..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-list/compiled_resources2.gyp
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-list-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        '../iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-        '../iron-scroll-target-behavior/compiled_resources2.gyp:iron-scroll-target-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-location/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-location/compiled_resources2.gyp
deleted file mode 100644
index 705961b9..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-location/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-location-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-query-params-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-media-query/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-media-query/compiled_resources2.gyp
deleted file mode 100644
index f24eb4bd..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-media-query/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-media-query-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/compiled_resources2.gyp
deleted file mode 100644
index c7cae75..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-menu-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-menu-behavior-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        '../iron-selector/compiled_resources2.gyp:iron-multi-selectable-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-menubar-behavior-extracted',
-      'dependencies': [
-        'iron-menu-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-meta/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-meta/compiled_resources2.gyp
deleted file mode 100644
index 8e262ac..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-meta/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-meta-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/compiled_resources2.gyp
deleted file mode 100644
index 4c6ff9bb..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-overlay-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-focusables-helper-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-overlay-backdrop-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-overlay-behavior-extracted',
-      'dependencies': [
-        '../iron-fit-behavior/compiled_resources2.gyp:iron-fit-behavior-extracted',
-        '../iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-        'iron-focusables-helper-extracted',
-        'iron-overlay-manager-extracted',
-        'iron-scroll-manager-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-overlay-manager-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        'iron-overlay-backdrop-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-scroll-manager-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-pages/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-pages/compiled_resources2.gyp
deleted file mode 100644
index bc1c5137..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-pages/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-pages-extracted',
-      'dependencies': [
-        '../iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-        '../iron-selector/compiled_resources2.gyp:iron-selectable-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-range-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-range-behavior/compiled_resources2.gyp
deleted file mode 100644
index 5c8604d9..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-range-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-range-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp
deleted file mode 100644
index 36d56c3..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-resizable-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-scroll-target-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-scroll-target-behavior/compiled_resources2.gyp
deleted file mode 100644
index 5b0bb128..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-scroll-target-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-scroll-target-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-scroll-threshold/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-scroll-threshold/compiled_resources2.gyp
deleted file mode 100644
index 56ca9ee..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-scroll-threshold/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-scroll-threshold-extracted',
-      'dependencies': [
-        '../iron-scroll-target-behavior/compiled_resources2.gyp:iron-scroll-target-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-selector/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-selector/compiled_resources2.gyp
deleted file mode 100644
index 3f658447..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-selector/compiled_resources2.gyp
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-multi-selectable-extracted',
-      'dependencies': [
-        'iron-selectable-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-selectable-extracted',
-      'dependencies': [
-        'iron-selection-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-selection-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'iron-selector-extracted',
-      'dependencies': [
-        'iron-multi-selectable-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/iron-validatable-behavior/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/iron-validatable-behavior/compiled_resources2.gyp
deleted file mode 100644
index 01bca05..0000000
--- a/third_party/polymer/v1_0/components-chromium/iron-validatable-behavior/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'iron-validatable-behavior-extracted',
-      'dependencies': [
-        '../iron-meta/compiled_resources2.gyp:iron-meta-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/neon-animation/animations/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/neon-animation/animations/compiled_resources2.gyp
deleted file mode 100644
index a8b59c5..0000000
--- a/third_party/polymer/v1_0/components-chromium/neon-animation/animations/compiled_resources2.gyp
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'cascaded-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'fade-in-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'fade-out-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'hero-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-shared-element-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'opaque-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'reverse-ripple-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-shared-element-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'ripple-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-shared-element-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'scale-down-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'scale-up-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-down-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-from-bottom-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-from-left-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-from-right-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-from-top-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-left-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-right-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'slide-up-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'transform-animation-extracted',
-      'dependencies': [
-        '../compiled_resources2.gyp:neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp
deleted file mode 100644
index a72fc50d..0000000
--- a/third_party/polymer/v1_0/components-chromium/neon-animation/compiled_resources2.gyp
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'neon-animatable-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'neon-animatable-extracted',
-      'dependencies': [
-        '../iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-        'neon-animatable-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'neon-animated-pages-extracted',
-      'dependencies': [
-        '../iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-        '../iron-selector/compiled_resources2.gyp:iron-selectable-extracted',
-        'neon-animation-runner-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'neon-animation-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'neon-animation-runner-behavior-extracted',
-      'dependencies': [
-        'neon-animatable-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'neon-shared-element-animatable-behavior-extracted',
-      'dependencies': [
-        'neon-animatable-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'neon-shared-element-animation-behavior-extracted',
-      'dependencies': [
-        'neon-animation-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp
deleted file mode 100644
index 7d3adf7..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-button-behavior-extracted',
-      'dependencies': [
-        '../iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
-        'paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-checked-element-behavior-extracted',
-      'dependencies': [
-        '../iron-checked-element-behavior/compiled_resources2.gyp:iron-checked-element-behavior-extracted',
-        'paper-inky-focus-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-inky-focus-behavior-extracted',
-      'dependencies': [
-        '../iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
-        'paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-ripple-behavior-extracted',
-      'dependencies': [
-        '../iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
-        '../paper-ripple/compiled_resources2.gyp:paper-ripple-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp
deleted file mode 100644
index abb8bfe..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-button-extracted',
-      'dependencies': [
-        '../paper-behaviors/compiled_resources2.gyp:paper-button-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-fab/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-fab/compiled_resources2.gyp
deleted file mode 100644
index 3672d0f..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-fab/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-fab-extracted',
-      'dependencies': [
-        '../iron-icon/compiled_resources2.gyp:iron-icon-extracted',
-        '../paper-behaviors/compiled_resources2.gyp:paper-button-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-icon-button/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-icon-button/compiled_resources2.gyp
deleted file mode 100644
index d7a5698c..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-icon-button/compiled_resources2.gyp
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-icon-button-extracted',
-      'dependencies': [
-        '../iron-icon/compiled_resources2.gyp:iron-icon-extracted',
-        '../paper-behaviors/compiled_resources2.gyp:paper-inky-focus-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-icon-button-light-extracted',
-      'dependencies': [
-        '../paper-behaviors/compiled_resources2.gyp:paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp
deleted file mode 100644
index 022a6240..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-input-addon-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-input-behavior-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        '../iron-behaviors/compiled_resources2.gyp:iron-control-state-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-input-char-counter-extracted',
-      'dependencies': [
-        'paper-input-addon-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-input-container-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-input-error-extracted',
-      'dependencies': [
-        'paper-input-addon-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-input-extracted',
-      'dependencies': [
-        '../iron-form-element-behavior/compiled_resources2.gyp:iron-form-element-behavior-extracted',
-        '../iron-input/compiled_resources2.gyp:iron-input-extracted',
-        'paper-input-behavior-extracted',
-        'paper-input-char-counter-extracted',
-        'paper-input-container-extracted',
-        'paper-input-error-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-textarea-extracted',
-      'dependencies': [
-        '../iron-autogrow-textarea/compiled_resources2.gyp:iron-autogrow-textarea-extracted',
-        '../iron-form-element-behavior/compiled_resources2.gyp:iron-form-element-behavior-extracted',
-        'paper-input-behavior-extracted',
-        'paper-input-char-counter-extracted',
-        'paper-input-container-extracted',
-        'paper-input-error-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-item/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-item/compiled_resources2.gyp
deleted file mode 100644
index 89c97b4..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-item/compiled_resources2.gyp
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-icon-item-extracted',
-      'dependencies': [
-        'paper-item-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-item-behavior-extracted',
-      'dependencies': [
-        '../iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
-        '../iron-behaviors/compiled_resources2.gyp:iron-control-state-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-item-body-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-item-extracted',
-      'dependencies': [
-        'paper-item-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-listbox/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-listbox/compiled_resources2.gyp
deleted file mode 100644
index 42ab6d3..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-listbox/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-listbox-extracted',
-      'dependencies': [
-        '../iron-menu-behavior/compiled_resources2.gyp:iron-menu-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-progress/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-progress/compiled_resources2.gyp
deleted file mode 100644
index ed7c923e..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-progress/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-progress-extracted',
-      'dependencies': [
-        '../iron-range-behavior/compiled_resources2.gyp:iron-range-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-radio-group/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-radio-group/compiled_resources2.gyp
deleted file mode 100644
index 964a102d..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-radio-group/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-radio-group-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        '../iron-menu-behavior/compiled_resources2.gyp:iron-menubar-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-ripple/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-ripple/compiled_resources2.gyp
deleted file mode 100644
index a982d68..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-ripple/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-ripple-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-slider/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-slider/compiled_resources2.gyp
deleted file mode 100644
index dd65ee4..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-slider/compiled_resources2.gyp
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-slider-extracted',
-      'dependencies': [
-        '../iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted',
-        '../iron-form-element-behavior/compiled_resources2.gyp:iron-form-element-behavior-extracted',
-        '../iron-range-behavior/compiled_resources2.gyp:iron-range-behavior-extracted',
-        '../paper-behaviors/compiled_resources2.gyp:paper-inky-focus-behavior-extracted',
-        '../paper-input/compiled_resources2.gyp:paper-input-extracted',
-        '../paper-progress/compiled_resources2.gyp:paper-progress-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-spinner/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-spinner/compiled_resources2.gyp
deleted file mode 100644
index db899d91..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-spinner/compiled_resources2.gyp
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-spinner-behavior-extracted',
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-spinner-lite-extracted',
-      'dependencies': [
-        'paper-spinner-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tabs/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-tabs/compiled_resources2.gyp
deleted file mode 100644
index bd3d6df..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-tabs/compiled_resources2.gyp
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-tab-extracted',
-      'dependencies': [
-        '../iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
-        '../iron-behaviors/compiled_resources2.gyp:iron-control-state-extracted',
-        '../paper-behaviors/compiled_resources2.gyp:paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'paper-tabs-extracted',
-      'dependencies': [
-        '../iron-icon/compiled_resources2.gyp:iron-icon-extracted',
-        '../iron-menu-behavior/compiled_resources2.gyp:iron-menubar-behavior-extracted',
-        '../iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-        '../paper-icon-button/compiled_resources2.gyp:paper-icon-button-extracted',
-        'paper-tab-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/components-chromium/paper-tooltip/compiled_resources2.gyp b/third_party/polymer/v1_0/components-chromium/paper-tooltip/compiled_resources2.gyp
deleted file mode 100644
index d839e1c7..0000000
--- a/third_party/polymer/v1_0/components-chromium/paper-tooltip/compiled_resources2.gyp
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2018 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.
-#
-# NOTE: Created with generate_compiled_resources_gyp.py, please do not edit.
-{
-  'targets': [
-    {
-      'target_name': 'paper-tooltip-extracted',
-      'dependencies': [
-        '../neon-animation/animations/compiled_resources2.gyp:fade-in-animation-extracted',
-        '../neon-animation/animations/compiled_resources2.gyp:fade-out-animation-extracted',
-        '../neon-animation/compiled_resources2.gyp:neon-animation-runner-behavior-extracted',
-      ],
-      'includes': ['../../../../closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/third_party/polymer/v1_0/generate_gyp.sh b/third_party/polymer/v1_0/generate_gyp.sh
deleted file mode 100755
index 1d25aaa..0000000
--- a/third_party/polymer/v1_0/generate_gyp.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-# 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.
-
-dirs=$(find components-chromium -type d | grep -v 'components-chromium/polymer')
-
-for dir in $dirs; do
-  htmls=$(\ls $dir/*.html 2>/dev/null)
-  if [ "$htmls" ]; then
-    echo "Analyzing $dir"
-    gyp_file="$dir/compiled_resources2.gyp"
-    content=$(../../../tools/polymer/generate_compiled_resources_gyp.py $htmls)
-    if [ "$content" ]; then
-      echo "Writing $gyp_file"
-      echo "$content" > "$gyp_file"
-    elif [ -f "$gyp_file" ]; then
-      echo "Removing $gyp_file"
-      rm "$gyp_file"
-    fi
-    echo
-  fi
-done
diff --git a/third_party/polymer/v1_0/reproduce.sh b/third_party/polymer/v1_0/reproduce.sh
index 0fc1976d..2c0b1cf 100755
--- a/third_party/polymer/v1_0/reproduce.sh
+++ b/third_party/polymer/v1_0/reproduce.sh
@@ -122,9 +122,6 @@
 echo 'Creating a summary of components...'
 python create_components_summary.py > components_summary.txt
 
-echo 'Creating GYP files for interfaces and externs...'
-./generate_gyp.sh
-
 echo 'Creating GN files for interfaces and externs...'
 ./generate_gn.sh
 
diff --git a/third_party/polymer/v1_0/rsync_exclude.txt b/third_party/polymer/v1_0/rsync_exclude.txt
index a5a0be5..64c447c7 100644
--- a/third_party/polymer/v1_0/rsync_exclude.txt
+++ b/third_party/polymer/v1_0/rsync_exclude.txt
@@ -1,7 +1,7 @@
 .bower.json
 build.log
 build.sh
-compiled_resources*.gyp
+BUILD.gn
 */demo/
 demo*.html
 */demos/
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index 43317d3..c657b6f 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -693,7 +693,7 @@
     apk_path: Path to the .apk file to measure.
     tool_prefix: Prefix for c++filt & nm.
     output_directory: Build output directory.
-    linker_name: "gold", "lld", or None
+    linker_name: 'gold', 'lld_v#' (# is a number), 'lld-lto_v#', or None.
 
   Returns:
     None if |elf_path| is not supplied. Otherwise returns dict mapping string
@@ -747,7 +747,7 @@
 
 
 def _ParseElfInfo(map_path, elf_path, tool_prefix, track_string_literals,
-                  outdir_context=None):
+                  outdir_context=None, linker_name=None):
   """Adds ELF section sizes and symbols."""
   if elf_path:
     # Run nm on the elf file to retrieve the list of symbol names per-address.
@@ -773,7 +773,7 @@
   logging.info('Parsing Linker Map')
   with _OpenMaybeGz(map_path) as map_file:
     section_sizes, raw_symbols = (
-        linker_map_parser.MapFileParser().Parse(map_file))
+        linker_map_parser.MapFileParser().Parse(linker_name, map_file))
 
     if outdir_context and outdir_context.thin_archives:
       _ResolveThinArchivePaths(raw_symbols, outdir_context.thin_archives)
@@ -1125,7 +1125,7 @@
 def CreateSectionSizesAndSymbols(
       map_path=None, tool_prefix=None, output_directory=None, elf_path=None,
       apk_path=None, track_string_literals=True, metadata=None,
-      apk_so_path=None, pak_files=None, pak_info_file=None,
+      apk_so_path=None, pak_files=None, pak_info_file=None, linker_name=None,
       knobs=SectionSizeKnobs()):
   """Creates sections sizes and symbols for a SizeInfo.
 
@@ -1184,7 +1184,8 @@
         thin_archives=thin_archives)
 
   section_sizes, raw_symbols = _ParseElfInfo(
-      map_path, elf_path, tool_prefix, track_string_literals, outdir_context)
+      map_path, elf_path, tool_prefix, track_string_literals,
+      outdir_context=outdir_context, linker_name=linker_name)
   elf_overhead_size = _CalculateElfOverhead(section_sizes, elf_path)
 
   pak_symbols_by_id = None
@@ -1318,7 +1319,7 @@
 
 def _DetectLinkerName(map_path):
   with _OpenMaybeGz(map_path) as map_file:
-    return linker_map_parser.DetectLinkerNameFromMapFileHeader(next(map_file))
+    return linker_map_parser.DetectLinkerNameFromMapFile(map_file)
 
 
 def _ElfInfoFromApk(apk_path, apk_so_path, tool_prefix):
@@ -1439,6 +1440,7 @@
                    'linker map file.')
 
   linker_name = _DetectLinkerName(map_path)
+  logging.info('Linker name: %s' % linker_name)
   tool_prefix_finder = path_util.ToolPrefixFinder(
       value=args.tool_prefix,
       output_directory_finder=output_directory_finder,
@@ -1470,7 +1472,8 @@
       apk_path=apk_path, output_directory=output_directory,
       track_string_literals=args.track_string_literals,
       metadata=metadata, apk_so_path=apk_so_path,
-      pak_files=args.pak_file, pak_info_file=args.pak_info_file, knobs=knobs)
+      pak_files=args.pak_file, pak_info_file=args.pak_info_file,
+      linker_name=linker_name, knobs=knobs)
   size_info = CreateSizeInfo(
       section_sizes, raw_symbols, metadata=metadata, normalize_names=False)
 
diff --git a/tools/binary_size/libsupersize/integration_test.py b/tools/binary_size/libsupersize/integration_test.py
index 5e761b0..f18d63f 100755
--- a/tools/binary_size/libsupersize/integration_test.py
+++ b/tools/binary_size/libsupersize/integration_test.py
@@ -183,16 +183,18 @@
         pak_files = [_TEST_APK_PAK_PATH]
         pak_info_file = _TEST_PAK_INFO_PATH
       metadata = None
+      linker_name = 'gold'
       if use_elf:
         with _AddMocksToPath():
           metadata = archive.CreateMetadata(
               _TEST_MAP_PATH, elf_path, apk_path, _TEST_TOOL_PREFIX,
-              output_directory, 'gold')
+              output_directory, linker_name)
       section_sizes, raw_symbols = archive.CreateSectionSizesAndSymbols(
           map_path=_TEST_MAP_PATH, tool_prefix=_TEST_TOOL_PREFIX,
           elf_path=elf_path, output_directory=output_directory,
           apk_path=apk_path, apk_so_path=apk_so_path, metadata=metadata,
-          pak_files=pak_files, pak_info_file=pak_info_file, knobs=knobs)
+          pak_files=pak_files, pak_info_file=pak_info_file,
+          linker_name=linker_name, knobs=knobs)
       IntegrationTest.cached_size_info[cache_key] = archive.CreateSizeInfo(
           section_sizes, raw_symbols, metadata=metadata)
     return copy.deepcopy(IntegrationTest.cached_size_info[cache_key])
diff --git a/tools/binary_size/libsupersize/linker_map_parser.py b/tools/binary_size/libsupersize/linker_map_parser.py
index edd0f91..6bee8bf1 100644
--- a/tools/binary_size/libsupersize/linker_map_parser.py
+++ b/tools/binary_size/libsupersize/linker_map_parser.py
@@ -287,6 +287,7 @@
   _LINE_RE_V0 = re.compile(r'([0-9a-f]+)\s+([0-9a-f]+)\s+(\d+) ( *)(.*)')
   _LINE_RE_V1 = re.compile(
       r'\s*[0-9a-f]+\s+([0-9a-f]+)\s+([0-9a-f]+)\s+(\d+) ( *)(.*)')
+  _LINE_RE = [_LINE_RE_V0, _LINE_RE_V1]
 
   def __init__(self, linker_name):
     self._linker_name = linker_name
@@ -325,13 +326,13 @@
 # 00000000002010c0 0000000000000000     0                 frame_dummy
 # 00000000002010ed 0000000000000071     1         a.o:(.text)
 # 00000000002010ed 0000000000000071     0                 main
+    # Extract e.g., 'lld_v0' -> 0, or 'lld-lto_v1' -> 1.
+    map_file_version = int(self._linker_name.split('_v')[1])
+    pattern = MapFileParserLld._LINE_RE[map_file_version]
+
     sym_maker = _SymbolMaker()
     cur_section = None
     cur_section_is_useful = None
-    if self._linker_name.endswith('v1'):
-      pattern = self._LINE_RE_V1
-    else:
-      pattern = self._LINE_RE_V0
 
     for line in lines:
       m = pattern.match(line)
@@ -391,19 +392,58 @@
     return self._section_sizes, sym_maker.syms
 
 
-def DetectLinkerNameFromMapFileHeader(first_line):
+def _DetectLto(lines):
+  """Scans LLD linker map file and returns whether LTO was used."""
+  # It's assumed that the first line in |lines| was consumed to determine that
+  # LLD was used. Seek 'thinlto-cache' prefix within an "indicator section" as
+  # indicator for LTO.
+  found_indicator_section = False
+  # Potential names of "main section". Only one gets used.
+  indicator_section_set = set(['.rodata', '.ARM.exidx'])
+  start_pos = -1
+  for line in lines:
+    # Shortcut to avoid regex: The first line seen (second line in file) should
+    # start a section, and start with '.', e.g.:
+    #     194      194       13     1 .interp
+    # Assign |start_pos| as position of '.', and trim everything before!
+    if start_pos < 0:
+      start_pos = line.index('.')
+    if len(line) < start_pos:
+      continue
+    line = line[start_pos:]
+    tok = line.lstrip()  # Allow whitespace at right.
+    indent_size = len(line) - len(tok)
+    if indent_size == 0:  # Section change.
+      if found_indicator_section:  # Exit if just visited "main section".
+        break
+      if tok.strip() in indicator_section_set:
+        found_indicator_section = True
+    elif indent_size == 8:
+      if found_indicator_section:
+        if tok.startswith('thinlto-cache'):
+          return True
+  return False
+
+
+def DetectLinkerNameFromMapFile(lines):
+  """Scans linker map file, and returns a coded linker name."""
+  first_line = next(lines)
+
   if first_line.startswith('Address'):
-    return 'lld_v0'
-  elif first_line.lstrip().startswith('VMA'):
-    return 'lld_v1'
+    return 'lld-lto_v0' if _DetectLto(lines) else 'lld_v0'
+
+  if first_line.lstrip().startswith('VMA'):
+    return 'lld-lto_v1' if _DetectLto(lines) else 'lld_v1'
+
   if first_line.startswith('Archive member'):
     return 'gold'
+
   raise Exception('Invalid map file: ' + first_line)
 
 
 class MapFileParser(object):
   """Parses a linker map file, with heuristic linker detection."""
-  def Parse(self, lines):
+  def Parse(self, linker_name, lines):
     """Parses a linker map file.
 
     Args:
@@ -412,7 +452,7 @@
     Returns:
       A tuple of (section_sizes, symbols).
     """
-    linker_name = DetectLinkerNameFromMapFileHeader(next(lines))
+    next(lines)  # Consume the first line of headers.
     if linker_name.startswith('lld'):
       inner_parser = MapFileParserLld(linker_name)
     elif linker_name == 'gold':
diff --git a/tools/json_schema_compiler/js_externs_generator.py b/tools/json_schema_compiler/js_externs_generator.py
index d0011e07..af7d190 100644
--- a/tools/json_schema_compiler/js_externs_generator.py
+++ b/tools/json_schema_compiler/js_externs_generator.py
@@ -83,11 +83,11 @@
   def _AppendEnumJsDoc(self, c, js_type):
     """ Given an Enum Type object, generates the Code for the enum's definition.
     """
-    (c.Sblock(line='/**', line_prefix=' * ')
-      .Append('@enum {string}')
-      .Append(self._js_util.GetSeeLink(self._namespace.name, 'type',
-                                       js_type.simple_name))
-      .Eblock(' */'))
+    c.Sblock(line='/**', line_prefix=' * ')
+    c.Append('@enum {string}')
+    self._js_util.AppendSeeLink(c, self._namespace.name, 'type',
+                                js_type.simple_name)
+    c.Eblock(' */')
     c.Append('%s.%s = {' % (self._GetNamespace(), js_type.name))
 
     def get_property_name(e):
@@ -136,8 +136,8 @@
     else:
       self._AppendTypedef(c, js_type.properties)
 
-    c.Append(self._js_util.GetSeeLink(self._namespace.name, 'type',
-                                      js_type.simple_name))
+    self._js_util.AppendSeeLink(c, self._namespace.name, 'type',
+                                js_type.simple_name)
     c.Eblock(' */')
 
     var = '%s.%s' % (self._GetNamespace(), js_type.simple_name)
@@ -192,8 +192,7 @@
     if (event.description):
       c.Comment(event.description, comment_prefix='')
     c.Append('@type {!ChromeEvent}')
-    c.Append(self._js_util.GetSeeLink(self._namespace.name, 'event',
-                                      event.name))
+    self._js_util.AppendSeeLink(c, self._namespace.name, 'event', event.name)
     c.Eblock(' */')
     c.Append('%s.%s;' % (self._GetNamespace(), event.name))
     c.Append()
diff --git a/tools/json_schema_compiler/js_externs_generator_test.py b/tools/json_schema_compiler/js_externs_generator_test.py
index 5036257..ac8f677 100755
--- a/tools/json_schema_compiler/js_externs_generator_test.py
+++ b/tools/json_schema_compiler/js_externs_generator_test.py
@@ -89,7 +89,7 @@
 """
 
 # The output we expect from our fake idl file.
-expected_output = """// Copyright %s The Chromium Authors. All rights reserved.
+fake_idl_expected = """// Copyright %s 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.
 
@@ -221,6 +221,73 @@
  */
 chrome.fakeApi.onTrapDetected;""" % datetime.now().year
 
+# A subset of fake_idl. The key difference is that the namespace is private,
+# which means that @see links shouldn't be generated.
+fake_private_idl = """
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A totally fake API.
+namespace fakeApiPrivate {
+  enum Greek {
+    ALPHA,
+    BETA,
+    GAMMA,
+    DELTA
+  };
+
+  dictionary Bar {
+    long num;
+  };
+
+  interface Events {
+    // Fired when we realize it's a trap!
+    static void onTrapDetected(Baz baz);
+  };
+};
+"""
+
+fake_private_idl_expected = """// Copyright %s The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file was generated by:
+//   tools/json_schema_compiler/compiler.py.
+// NOTE: The format of types has changed. 'FooType' is now
+//   'chrome.fakeApiPrivate.FooType'.
+// Please run the closure compiler before committing changes.
+// See https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md
+
+/** @fileoverview Externs generated from namespace: fakeApiPrivate */
+
+/**
+ * @const
+ */
+chrome.fakeApiPrivate = {};
+
+/**
+ * @enum {string}
+ */
+chrome.fakeApiPrivate.Greek = {
+  ALPHA: 'ALPHA',
+  BETA: 'BETA',
+  GAMMA: 'GAMMA',
+  DELTA: 'DELTA',
+};
+
+/**
+ * @typedef {{
+ *   num: number
+ * }}
+ */
+chrome.fakeApiPrivate.Bar;
+
+/**
+ * Fired when we realize it's a trap!
+ * @type {!ChromeEvent}
+ */
+chrome.fakeApiPrivate.onTrapDetected;""" % datetime.now().year
 
 fake_json = """// Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -296,7 +363,7 @@
   }
 ]"""
 
-json_expected = """// Copyright %s The Chromium Authors. All rights reserved.
+fake_json_expected = """// Copyright %s 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.
 
@@ -361,12 +428,18 @@
 
   def testBasic(self):
     namespace = self._GetNamespace(fake_idl, 'fake_api.idl', True)
-    self.assertMultiLineEqual(expected_output,
+    self.assertMultiLineEqual(fake_idl_expected,
+                              JsExternsGenerator().Generate(namespace).Render())
+
+  def testPrivate(self):
+    namespace = self._GetNamespace(fake_private_idl, 'fake_api_private.idl',
+                                   True)
+    self.assertMultiLineEqual(fake_private_idl_expected,
                               JsExternsGenerator().Generate(namespace).Render())
 
   def testJsonWithInlineObjects(self):
     namespace = self._GetNamespace(fake_json, 'fake_api.json', False)
-    self.assertMultiLineEqual(json_expected,
+    self.assertMultiLineEqual(fake_json_expected,
                               JsExternsGenerator().Generate(namespace).Render())
 
 
diff --git a/tools/json_schema_compiler/js_interface_generator.py b/tools/json_schema_compiler/js_interface_generator.py
index e6c892a8..b84c717 100644
--- a/tools/json_schema_compiler/js_interface_generator.py
+++ b/tools/json_schema_compiler/js_interface_generator.py
@@ -92,8 +92,7 @@
     if (event.description):
       c.Comment(event.description, comment_prefix='')
     c.Append('@type {!ChromeEvent}')
-    c.Append(self._js_util.GetSeeLink(self._namespace.name, 'event',
-                                      event.name))
+    self._js_util.AppendSeeLink(c, self._namespace.name, 'event', event.name)
     c.Eblock(' */')
 
     c.Append('%s.prototype.%s;' % (self._interface, event.name))
diff --git a/tools/json_schema_compiler/js_interface_generator_test.py b/tools/json_schema_compiler/js_interface_generator_test.py
index 90837d7..f2d5df5 100755
--- a/tools/json_schema_compiler/js_interface_generator_test.py
+++ b/tools/json_schema_compiler/js_interface_generator_test.py
@@ -72,7 +72,7 @@
 """
 
 # The output we expect from our fake idl file.
-expected_output = ("""// Copyright %s The Chromium Authors. All rights reserved.
+fake_idl_output = ("""// Copyright %s 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.
 
@@ -126,7 +126,7 @@
   def testBasic(self):
     namespace = self._GetNamespace(fake_idl, 'fake_api.idl')
     self.assertMultiLineEqual(
-        expected_output,
+        fake_idl_output,
         JsInterfaceGenerator().Generate(namespace).Render())
 
 
diff --git a/tools/json_schema_compiler/js_util.py b/tools/json_schema_compiler/js_util.py
index e043f2e..285ece1d 100644
--- a/tools/json_schema_compiler/js_util.py
+++ b/tools/json_schema_compiler/js_util.py
@@ -97,7 +97,7 @@
     if function.deprecated:
       c.Append('@deprecated %s' % function.deprecated)
 
-    c.Append(self.GetSeeLink(namespace_name, 'method', function.name))
+    self.AppendSeeLink(c, namespace_name, 'method', function.name)
 
     c.Eblock(' */')
 
@@ -174,14 +174,22 @@
       return Code().Append(js_type.property_type.name)
     return Code().Append('?') # TODO(tbreisacher): Make this more specific.
 
-  def GetSeeLink(self, namespace_name, object_type, object_name):
-    """Returns a @see link for a given API 'object' (type, method, or event).
+  def AppendSeeLink(self, c, namespace_name, object_type, object_name):
+    """Appends a @see link for a given API 'object' (type, method, or event).
     """
 
+    # TODO(nigeltao): this should actually be gated on if there is
+    # documentation, rather than if it's a private API. Most private APIs
+    # aren't documented, but some are. For example:
+    #  - https://developer.chrome.com/apps/developerPrivate exists
+    #  - https://developer.chrome.com/apps/screenlockPrivate does not
+    if namespace_name.endswith('Private'):
+      return
+
     # NOTE(devlin): This is kind of a hack. Some APIs will be hosted on
     # developer.chrome.com/apps/ instead of /extensions/, and some APIs have
     # '.'s in them (like app.window), which should resolve to 'app_window'.
     # Luckily, the doc server has excellent url resolution, and knows exactly
     # what we mean. This saves us from needing any complicated logic here.
-    return ('@see https://developer.chrome.com/extensions/%s#%s-%s' %
-                (namespace_name, object_type, object_name))
+    c.Append('@see https://developer.chrome.com/extensions/%s#%s-%s' %
+             (namespace_name, object_type, object_name))
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d4ba306..b77f53fd 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -27538,6 +27538,7 @@
   <int value="-699767107" label="enable-sync-app-list"/>
   <int value="-699198009" label="KeyboardShortcutViewer:enabled"/>
   <int value="-697751423" label="disable-quickoffice-component-app"/>
+  <int value="-694372915" label="enable-ephemeral-flash-permission"/>
   <int value="-684900739" label="disable-merge-key-char-events"/>
   <int value="-684223908" label="enable-android-wallpapers-app"/>
   <int value="-680787130" label="ExperimentalVRFeatures:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 6fe75051..da00e84 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -122423,10 +122423,10 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="SafeBrowsing.V4Store.Metrics" separator=".">
-  <suffix name="AnyIpMalware" label="(Obsolete. Was: AnyIpMalware)"/>
+  <suffix name="AnyIpMalware" label="(Obsolete, not recorded)"/>
   <suffix name="CertCsdDownloadWhitelist"/>
   <suffix name="ChromeExtMalware"/>
-  <suffix name="ChromeFilenameClientIncident"/>
+  <suffix name="ChromeFilenameClientIncident" label="(Obsolete, not recorded)"/>
   <suffix name="ChromeUrlClientIncident"/>
   <suffix name="IpMalware"/>
   <suffix name="UrlCsdDownloadWhitelist"/>
@@ -122436,6 +122436,7 @@
   <suffix name="UrlSoceng"/>
   <suffix name="UrlSubresourceFilter"/>
   <suffix name="UrlSuspiciousSite"/>
+  <suffix name="UrlSuspiciousSiteId" label="(Obsolete, UrlSuspiciousSite)"/>
   <suffix name="UrlUws"/>
   <affected-histogram name="SafeBrowsing.V4Database.Size"/>
   <affected-histogram
diff --git a/tools/perf/contrib/cros_benchmarks/cros_utils.py b/tools/perf/contrib/cros_benchmarks/cros_utils.py
index 34f7d85..400c0421 100644
--- a/tools/perf/contrib/cros_benchmarks/cros_utils.py
+++ b/tools/perf/contrib/cros_benchmarks/cros_utils.py
@@ -6,6 +6,7 @@
 import logging
 import os
 import subprocess
+import time
 
 import py_utils
 
@@ -13,8 +14,34 @@
 from telemetry.value import histogram_util
 
 
-def _RunRemoteCommand(dut_ip, cmd):
-  return os.system('ssh root@%s %s' % (dut_ip, cmd))
+def _RunCommand(dut_ip, cmd):
+  """Runs command on the DUT.
+
+  Args:
+    dut_ip: IP of the DUT. If it's None, runs command locally.
+    cmd: The command to run.
+  """
+  if dut_ip:
+    # Commands via ssh shall be double-quoted to escape special characters.
+    cmd = '"%s"' % cmd
+    return os.system('ssh root@%s %s' % (dut_ip, cmd))
+  else:
+    return os.system(cmd)
+
+
+def _Popen(dut_ip, cmd_list):
+  """Popen to run a command on DUT."""
+  if dut_ip:
+    cmd_list = ['ssh', 'root@' + dut_ip] + cmd_list
+  return subprocess.Popen(cmd_list, stdout=subprocess.PIPE)
+
+
+def _CopyToDUT(dut_ip, local_path, dut_path):
+  """Copies file to the DUT path."""
+  if dut_ip:
+    os.system('scp -q %s root@%s:%s' % (local_path, dut_ip, dut_path))
+  else:
+    os.system('cp %s %s' % (local_path, dut_path))
 
 
 def _GetTabSwitchHistogram(browser):
@@ -108,7 +135,6 @@
       dut_ip: DUT IP or hostname.
     """
     self._dut_ip = dut_ip
-    self._root_dut_ip = 'root@' + dut_ip
     self._key_device_name = None
 
   def _StartRemoteKeyboardEmulator(self):
@@ -122,18 +148,23 @@
     """
     kbd_prop_filename = '/usr/local/autotest/cros/input_playback/keyboard.prop'
 
-    ret = _RunRemoteCommand(self._dut_ip, 'test -e %s' % kbd_prop_filename)
+    ret = _RunCommand(self._dut_ip, 'test -e %s' % kbd_prop_filename)
     if ret != 0:
       raise RuntimeError('Keyboard property file does not exist.')
 
-    cmd = ['ssh', self._root_dut_ip, 'evemu-device', kbd_prop_filename]
-    ssh_process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+    process = _Popen(self._dut_ip, ['evemu-device', kbd_prop_filename])
 
     # The evemu-device output format:
     # Emulated Keyboard: /dev/input/event10
-    output = ssh_process.stdout.readline()
-    # The remote process would live when the ssh process was terminated.
-    ssh_process.kill()
+    output = process.stdout.readline()
+    if self._dut_ip:
+      # The remote process would live when the ssh process was terminated.
+      process.kill()
+    else:
+      # Needs extra sleep when running locally, otherwise the first key may not
+      # dispatch.
+      # TODO(cywang): crbug.com/852702
+      time.sleep(1)
     if not output.startswith('Emulated Keyboard:'):
       raise RuntimeError('Keyboard emulation failed.')
     key_device_name = output.split()[2]
@@ -143,9 +174,8 @@
     """Uploads the script to send key to switch tabs."""
     cur_dir = os.path.dirname(os.path.abspath(__file__))
     log_key_filename = os.path.join(cur_dir, 'data', 'log_key_tab_switch')
-    os.system('scp -q %s %s:%s' %
-              (log_key_filename, self._root_dut_ip,
-               KeyboardEmulator.REMOTE_LOG_KEY_FILENAME))
+    _CopyToDUT(self._dut_ip, log_key_filename,
+               KeyboardEmulator.REMOTE_LOG_KEY_FILENAME)
 
   def __enter__(self):
     self._key_device_name = self._StartRemoteKeyboardEmulator()
@@ -154,14 +184,14 @@
 
   def SwitchTab(self):
     """Sending Ctrl-tab key to trigger tab switching."""
-    cmd = ('"evemu-play --insert-slot0 %s < %s"' %
+    cmd = ('evemu-play --insert-slot0 %s < %s' %
            (self._key_device_name,
             KeyboardEmulator.REMOTE_LOG_KEY_FILENAME))
-    _RunRemoteCommand(self._dut_ip, cmd)
+    _RunCommand(self._dut_ip, cmd)
 
   def __exit__(self, exc_type, exc_value, traceback):
-    # Kills the remote emulator process explicitly.
-    _RunRemoteCommand(self._dut_ip, 'pkill evemu-device')
+    # Kills the emulator process explicitly.
+    _RunCommand(self._dut_ip, 'pkill evemu-device')
 
 
 def NoScreenOff(dut_ip):
@@ -170,5 +200,5 @@
   Args:
     dut_ip: DUT IP or hostname.
   """
-  _RunRemoteCommand(dut_ip, 'set_power_policy --ac_screen_off_delay=3600')
-  _RunRemoteCommand(dut_ip, 'set_power_policy --ac_screen_dim_delay=3600')
+  _RunCommand(dut_ip, 'set_power_policy --ac_screen_off_delay=3600')
+  _RunCommand(dut_ip, 'set_power_policy --ac_screen_dim_delay=3600')
diff --git a/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py b/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py
index de0a1a0..5b47991 100644
--- a/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py
+++ b/tools/perf/contrib/cros_benchmarks/tab_switching_bench.py
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 import os
-import logging
 
 from core import perf_benchmark
 
@@ -42,9 +41,10 @@
                       help='pause between tab creation and tab switch')
 
   def CreateStorySet(self, options):
-    if not options.cros_remote:
-      # Raise exception here would fail the presubmit check.
-      logging.error('Must specify --remote=DUT_IP to run this test.')
+    # When running this test with test_that, fetch_benchmark_deps.py would
+    # invoke this method. Options doesn't have attribute cros_remote in this
+    # case.
+    cros_remote = getattr(options, 'cros_remote', None)
     story_set = story.StorySet(
         archive_data_file='data/tab_switching.json',
         base_dir=os.path.dirname(os.path.abspath(__file__)),
@@ -52,7 +52,7 @@
     # May not have pause_after_creation attribute in presubmit check.
     pause_after_creation = getattr(options, 'pause_after_creation', 0)
     story_set.AddStory(tab_switching_stories.CrosMultiTabTypical24Story(
-        story_set, options.cros_remote, options.tabset_repeat,
+        story_set, cros_remote, options.tabset_repeat,
         pause_after_creation))
     return story_set
 
diff --git a/tools/perf/contrib/cros_benchmarks/tab_switching_stories.py b/tools/perf/contrib/cros_benchmarks/tab_switching_stories.py
index 914e2ad..31018d6 100644
--- a/tools/perf/contrib/cros_benchmarks/tab_switching_stories.py
+++ b/tools/perf/contrib/cros_benchmarks/tab_switching_stories.py
@@ -22,14 +22,16 @@
     super(CrosMultiTabStory, self).__init__(
         shared_page_state_class=shared_page_state.SharedPageState,
         page_set=story_set, name=self.NAME, url=self.URL)
+    # cros_remote is the DUT IP or None if running locally.
     self._cros_remote = cros_remote
     self._tabset_repeat = tabset_repeat
     self._pause_after_creation = pause_after_creation
 
   def RunNavigateSteps(self, action_runner):
     """Opening tabs and waiting for them to load."""
-    if not self._cros_remote:
-      raise ValueError('Must specify --remote=DUT_IP to run this test.')
+    if not self._cros_remote and not py_utils.IsRunningOnCrosDevice():
+      raise ValueError('Must specify --remote=DUT_IP to run this test, '
+                       'or run it on CrOS locally.')
 
     # As this story may run for a long time, adjusting screen off time to
     # avoid screen off.
diff --git a/tools/polymer/generate_compiled_resources_gyp.py b/tools/polymer/generate_compiled_resources_gyp.py
deleted file mode 100755
index 2aa86a2..0000000
--- a/tools/polymer/generate_compiled_resources_gyp.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-from bs4 import BeautifulSoup
-from datetime import date
-import os.path as path
-import sys
-
-
-_SRC = path.join(path.dirname(path.abspath(__file__)), "..", "..")
-_COMPILE_JS = path.join(
-    _SRC, "third_party", "closure_compiler", "compile_js2.gypi")
-_POLYMERS = ["polymer%s.html" % p for p in "", "-mini", "-micro"]
-_WEB_ANIMATIONS_BASE = "web-animations.html"
-_WEB_ANIMATIONS_TARGET = "<(EXTERNS_GYP):web_animations"
-_COMPILED_RESOURCES_TEMPLATE = """
-# Copyright %d 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.
-#
-# NOTE: Created with %s, please do not edit.
-{
-  'targets': [
-    %s
-  ],
-}
-""".strip()
-
-
-def main(created_by, html_files):
-  targets = ""
-
-  def _html_to_extracted(html_file):
-    assert html_file.endswith(".html")
-    return html_file[:-len(".html")] + "-extracted"
-
-  def _target_name(target_file):
-    return _html_to_extracted(path.basename(target_file))
-
-  def _has_extracted_js(html_file):
-    return path.isfile(_html_to_extracted(html_file) + ".js")
-
-  html_files = filter(_has_extracted_js, html_files)
-
-  for html_file in sorted(html_files, key=_target_name):
-    html_base = path.basename(html_file)
-    if html_base in _POLYMERS:
-      continue
-
-    parsed = BeautifulSoup(open(html_file), "html.parser")
-    imports = set(i.get("href") for i in parsed.find_all("link", rel="import"))
-
-    html_dir = path.dirname(html_file)
-    dependencies = []
-
-    for html_import in sorted(imports):
-      import_dir, import_base = path.split(html_import.encode("ascii"))
-      if import_base in _POLYMERS:
-        continue
-
-      if import_base == _WEB_ANIMATIONS_BASE:
-        dependencies.append(_WEB_ANIMATIONS_TARGET)
-        continue
-
-      # Only exclude these after appending web animations externs.
-      if not _has_extracted_js(path.join(html_dir, html_import)):
-        continue
-
-      target = _target_name(import_base)
-
-      if import_dir:
-        target = "compiled_resources2.gyp:" + target
-
-      dependencies.append(path.join(import_dir, target))
-
-    path_to_compile_js = path.relpath(_COMPILE_JS, html_dir)
-
-    targets += "\n    {"
-    targets += "\n      'target_name': '%s-extracted'," % html_base[:-5]
-    if dependencies:
-      targets += "\n      'dependencies': ["
-      targets += "\n        '%s'," % "',\n        '".join(dependencies)
-      targets += "\n      ],"
-    targets += "\n      'includes': ['%s']," % path_to_compile_js
-    targets += "\n    },"
-
-  targets = targets.strip()
-
-  if targets:
-    current_year = date.today().year
-    print _COMPILED_RESOURCES_TEMPLATE % (current_year, created_by, targets)
-
-
-if __name__ == "__main__":
-  main(path.basename(sys.argv[0]), sys.argv[1:])
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn
index 495b8cf..a644c64 100644
--- a/ui/events/BUILD.gn
+++ b/ui/events/BUILD.gn
@@ -19,6 +19,7 @@
 static_library("dom_keycode_converter") {
   public = [
     "keycodes/dom/dom_code.h",
+    "keycodes/dom/dom_codes.h",
     "keycodes/dom/dom_key.h",
     "keycodes/dom/keycode_converter.h",
   ]
@@ -36,11 +37,6 @@
   if (!is_ios) {
     deps += [ "//ipc:param_traits" ]
   }
-
-  # TODO(joedow): Remove the ash friend.  There is a cc file in that directory
-  # which includes the private inc file, we should expose the funcitonality they
-  # need in the KeycodeConverter and then clean this up.
-  friend = [ "//ash/components/shortcut_viewer:lib" ]
 }
 
 static_library("dom_keyboard_layout") {
@@ -92,8 +88,6 @@
 
 component("events_base") {
   sources = [
-    "android/scroller.cc",
-    "android/scroller.h",
     "base_event_utils.cc",
     "base_event_utils.h",
     "event_switches.cc",
@@ -118,6 +112,8 @@
     "keycodes/keyboard_code_conversion_win.cc",
     "keycodes/keyboard_code_conversion_win.h",
     "keycodes/keyboard_codes.h",
+    "mobile_scroller.cc",
+    "mobile_scroller.h",
   ]
 
   defines = [ "EVENTS_BASE_IMPLEMENTATION" ]
@@ -441,7 +437,6 @@
 if (!is_ios) {
   test("events_unittests") {
     sources = [
-      "android/scroller_unittest.cc",
       "blink/blink_event_util_unittest.cc",
       "blink/fling_booster_unittest.cc",
       "blink/input_handler_proxy_unittest.cc",
@@ -474,6 +469,7 @@
       "keycodes/dom/keycode_converter_unittest.cc",
       "keycodes/keyboard_code_conversion_unittest.cc",
       "keycodes/platform_key_map_win_unittest.cc",
+      "mobile_scroller_unittest.cc",
       "mojo/struct_traits_unittest.cc",
       "platform/platform_event_source_unittest.cc",
       "scoped_target_handler_unittest.cc",
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.cc b/ui/events/gestures/blink/web_gesture_curve_impl.cc
index cc8d67e..b97c63d0 100644
--- a/ui/events/gestures/blink/web_gesture_curve_impl.cc
+++ b/ui/events/gestures/blink/web_gesture_curve_impl.cc
@@ -15,14 +15,11 @@
 #include "third_party/blink/public/platform/web_gesture_curve_target.h"
 #include "ui/events/gestures/fixed_velocity_curve.h"
 #include "ui/events/gestures/fling_curve.h"
+#include "ui/events/mobile_scroller.h"
 #include "ui/gfx/geometry/safe_integer_conversions.h"
 #include "ui/gfx/geometry/vector2d.h"
 #include "ui/gfx/geometry/vector2d_f.h"
 
-#if defined(OS_ANDROID)
-#include "ui/events/android/scroller.h"
-#endif
-
 #if !defined(OS_ANDROID) && defined(CHROMECAST_BUILD)
 #include "ui/events/chromecast/scroller.h"
 #endif
@@ -34,25 +31,26 @@
 
 std::unique_ptr<GestureCurve> CreateDefaultPlatformCurve(
     blink::WebGestureDevice device_source,
-    const gfx::Vector2dF& initial_velocity) {
+    const gfx::Vector2dF& initial_velocity,
+    bool use_mobile_fling_curve) {
   if (device_source == blink::kWebGestureDeviceSyntheticAutoscroll) {
     return std::make_unique<FixedVelocityCurve>(initial_velocity,
                                                 base::TimeTicks());
   }
 
-#if defined(OS_ANDROID) || defined(CHROMECAST_BUILD)
+#if defined(CHROMECAST_BUILD)
   auto scroller = std::make_unique<Scroller>(Scroller::Config());
-  scroller->Fling(0,
-                  0,
-                  initial_velocity.x(),
-                  initial_velocity.y(),
-                  INT_MIN,
-                  INT_MAX,
-                  INT_MIN,
-                  INT_MAX,
-                  base::TimeTicks());
+  scroller->Fling(0, 0, initial_velocity.x(), initial_velocity.y(), INT_MIN,
+                  INT_MAX, INT_MIN, INT_MAX, base::TimeTicks());
   return std::move(scroller);
 #else
+  if (use_mobile_fling_curve) {
+    auto scroller = std::make_unique<MobileScroller>(MobileScroller::Config());
+    scroller->Fling(0, 0, initial_velocity.x(), initial_velocity.y(), INT_MIN,
+                    INT_MAX, INT_MIN, INT_MAX, base::TimeTicks());
+    return std::move(scroller);
+  }
+
   return std::make_unique<FlingCurve>(initial_velocity, base::TimeTicks());
 #endif
 }
@@ -65,9 +63,11 @@
     blink::WebGestureDevice device_source,
     const gfx::Vector2dF& initial_velocity,
     const gfx::Vector2dF& initial_offset,
-    bool on_main_thread) {
+    bool on_main_thread,
+    bool use_mobile_fling_curve) {
   return std::unique_ptr<WebGestureCurve>(new WebGestureCurveImpl(
-      CreateDefaultPlatformCurve(device_source, initial_velocity),
+      CreateDefaultPlatformCurve(device_source, initial_velocity,
+                                 use_mobile_fling_curve),
       initial_offset, on_main_thread ? ThreadType::MAIN : ThreadType::IMPL));
 }
 
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.h b/ui/events/gestures/blink/web_gesture_curve_impl.h
index ede9a03..d74cd04 100644
--- a/ui/events/gestures/blink/web_gesture_curve_impl.h
+++ b/ui/events/gestures/blink/web_gesture_curve_impl.h
@@ -24,7 +24,8 @@
       blink::WebGestureDevice device_source,
       const gfx::Vector2dF& initial_velocity,
       const gfx::Vector2dF& initial_offset,
-      bool on_main_thread);
+      bool on_main_thread,
+      bool use_mobile_fling_curve);
   static std::unique_ptr<blink::WebGestureCurve> CreateFromUICurveForTesting(
       std::unique_ptr<GestureCurve> curve,
       const gfx::Vector2dF& initial_offset);
diff --git a/ui/events/keycodes/dom/dom_codes.h b/ui/events/keycodes/dom/dom_codes.h
new file mode 100644
index 0000000..2728dc95
--- /dev/null
+++ b/ui/events/keycodes/dom/dom_codes.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_KEYCODES_DOM_DOM_CODES_H_
+#define UI_EVENTS_KEYCODES_DOM_DOM_CODES_H_
+
+#include "ui/events/keycodes/dom/dom_code.h"
+
+namespace ui {
+
+#define DOM_CODE_TYPE(x) static_cast<DomCode>(x)
+#define USB_KEYMAP(usb, evdev, xkb, win, mac, code, id) DOM_CODE_TYPE(usb)
+#define USB_KEYMAP_DECLARATION constexpr DomCode dom_codes[] =
+#include "ui/events/keycodes/dom/keycode_converter_data.inc"
+#undef DOM_CODE_TYPE
+#undef USB_KEYMAP
+#undef USB_KEYMAP_DECLARATION
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_KEYCODES_DOM_DOM_CODES_H_
diff --git a/ui/events/android/scroller.cc b/ui/events/mobile_scroller.cc
similarity index 79%
rename from ui/events/android/scroller.cc
rename to ui/events/mobile_scroller.cc
index 32835f14..794bbdc 100644
--- a/ui/events/android/scroller.cc
+++ b/ui/events/mobile_scroller.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ui/events/android/scroller.h"
+#include "ui/events/mobile_scroller.h"
 
 #include <cmath>
 
@@ -158,11 +158,10 @@
 
 }  // namespace
 
-Scroller::Config::Config()
-    : fling_friction(kDefaultFriction), flywheel_enabled(false) {
-}
+MobileScroller::Config::Config()
+    : fling_friction(kDefaultFriction), flywheel_enabled(false) {}
 
-Scroller::Scroller(const Config& config)
+MobileScroller::MobileScroller(const Config& config)
     : mode_(UNDEFINED),
       start_x_(0),
       start_y_(0),
@@ -186,15 +185,13 @@
       distance_(0),
       fling_friction_(config.fling_friction),
       deceleration_(ComputeDeceleration(fling_friction_)),
-      tuning_coeff_(ComputeDeceleration(0.84f)) {
-}
+      tuning_coeff_(ComputeDeceleration(0.84f)) {}
 
-Scroller::~Scroller() {
-}
+MobileScroller::~MobileScroller() {}
 
-bool Scroller::ComputeScrollOffset(base::TimeTicks time,
-                                   gfx::Vector2dF* offset,
-                                   gfx::Vector2dF* velocity) {
+bool MobileScroller::ComputeScrollOffset(base::TimeTicks time,
+                                         gfx::Vector2dF* offset,
+                                         gfx::Vector2dF* velocity) {
   DCHECK(offset);
   DCHECK(velocity);
   if (!ComputeScrollOffsetInternal(time)) {
@@ -208,25 +205,21 @@
   return true;
 }
 
-void Scroller::StartScroll(float start_x,
-                           float start_y,
-                           float dx,
-                           float dy,
-                           base::TimeTicks start_time) {
-  StartScroll(start_x,
-              start_y,
-              dx,
-              dy,
-              start_time,
+void MobileScroller::StartScroll(float start_x,
+                                 float start_y,
+                                 float dx,
+                                 float dy,
+                                 base::TimeTicks start_time) {
+  StartScroll(start_x, start_y, dx, dy, start_time,
               base::TimeDelta::FromMilliseconds(kDefaultDurationMs));
 }
 
-void Scroller::StartScroll(float start_x,
-                           float start_y,
-                           float dx,
-                           float dy,
-                           base::TimeTicks start_time,
-                           base::TimeDelta duration) {
+void MobileScroller::StartScroll(float start_x,
+                                 float start_y,
+                                 float dx,
+                                 float dy,
+                                 base::TimeTicks start_time,
+                                 base::TimeDelta duration) {
   DCHECK_GT(duration, base::TimeDelta());
   mode_ = SCROLL_MODE;
   finished_ = false;
@@ -241,15 +234,15 @@
   curr_time_ = start_time_;
 }
 
-void Scroller::Fling(float start_x,
-                     float start_y,
-                     float velocity_x,
-                     float velocity_y,
-                     float min_x,
-                     float max_x,
-                     float min_y,
-                     float max_y,
-                     base::TimeTicks start_time) {
+void MobileScroller::Fling(float start_x,
+                           float start_y,
+                           float velocity_x,
+                           float velocity_y,
+                           float min_x,
+                           float max_x,
+                           float min_y,
+                           float max_y,
+                           base::TimeTicks start_time) {
   DCHECK(velocity_x || velocity_y);
 
   // Continue a scroll or fling in progress.
@@ -297,26 +290,26 @@
   RecomputeDeltas();
 }
 
-void Scroller::ExtendDuration(base::TimeDelta extend) {
+void MobileScroller::ExtendDuration(base::TimeDelta extend) {
   base::TimeDelta passed = GetTimePassed();
   duration_ = passed + extend;
   duration_seconds_reciprocal_ = 1.0 / duration_.InSecondsF();
   finished_ = false;
 }
 
-void Scroller::SetFinalX(float new_x) {
+void MobileScroller::SetFinalX(float new_x) {
   final_x_ = new_x;
   finished_ = false;
   RecomputeDeltas();
 }
 
-void Scroller::SetFinalY(float new_y) {
+void MobileScroller::SetFinalY(float new_y) {
   final_y_ = new_y;
   finished_ = false;
   RecomputeDeltas();
 }
 
-void Scroller::AbortAnimation() {
+void MobileScroller::AbortAnimation() {
   curr_x_ = final_x_;
   curr_y_ = final_y_;
   curr_velocity_ = 0;
@@ -324,31 +317,31 @@
   finished_ = true;
 }
 
-void Scroller::ForceFinished(bool finished) {
+void MobileScroller::ForceFinished(bool finished) {
   finished_ = finished;
 }
 
-bool Scroller::IsFinished() const {
+bool MobileScroller::IsFinished() const {
   return finished_;
 }
 
-base::TimeDelta Scroller::GetTimePassed() const {
+base::TimeDelta MobileScroller::GetTimePassed() const {
   return curr_time_ - start_time_;
 }
 
-base::TimeDelta Scroller::GetDuration() const {
+base::TimeDelta MobileScroller::GetDuration() const {
   return duration_;
 }
 
-float Scroller::GetCurrX() const {
+float MobileScroller::GetCurrX() const {
   return curr_x_;
 }
 
-float Scroller::GetCurrY() const {
+float MobileScroller::GetCurrY() const {
   return curr_y_;
 }
 
-float Scroller::GetCurrVelocity() const {
+float MobileScroller::GetCurrVelocity() const {
   if (finished_)
     return 0;
   if (mode_ == FLING_MODE)
@@ -356,36 +349,36 @@
   return velocity_ - deceleration_ * GetTimePassed().InSecondsF() * 0.5f;
 }
 
-float Scroller::GetCurrVelocityX() const {
+float MobileScroller::GetCurrVelocityX() const {
   return delta_x_norm_ * GetCurrVelocity();
 }
 
-float Scroller::GetCurrVelocityY() const {
+float MobileScroller::GetCurrVelocityY() const {
   return delta_y_norm_ * GetCurrVelocity();
 }
 
-float Scroller::GetStartX() const {
+float MobileScroller::GetStartX() const {
   return start_x_;
 }
 
-float Scroller::GetStartY() const {
+float MobileScroller::GetStartY() const {
   return start_y_;
 }
 
-float Scroller::GetFinalX() const {
+float MobileScroller::GetFinalX() const {
   return final_x_;
 }
 
-float Scroller::GetFinalY() const {
+float MobileScroller::GetFinalY() const {
   return final_y_;
 }
 
-bool Scroller::IsScrollingInDirection(float xvel, float yvel) const {
+bool MobileScroller::IsScrollingInDirection(float xvel, float yvel) const {
   return !finished_ && Signum(xvel) == Signum(delta_x_) &&
          Signum(yvel) == Signum(delta_y_);
 }
 
-bool Scroller::ComputeScrollOffsetInternal(base::TimeTicks time) {
+bool MobileScroller::ComputeScrollOffsetInternal(base::TimeTicks time) {
   if (finished_)
     return false;
 
@@ -420,8 +413,8 @@
     case FLING_MODE: {
       float distance_coef = 1.f;
       float velocity_coef = 0.f;
-      g_spline_constants.Get().CalculateCoefficients(
-          u, &distance_coef, &velocity_coef);
+      g_spline_constants.Get().CalculateCoefficients(u, &distance_coef,
+                                                     &velocity_coef);
 
       curr_velocity_ = velocity_coef * distance_ * duration_seconds_reciprocal_;
 
@@ -441,7 +434,7 @@
   return !finished_;
 }
 
-void Scroller::RecomputeDeltas() {
+void MobileScroller::RecomputeDeltas() {
   delta_x_ = final_x_ - start_x_;
   delta_y_ = final_y_ - start_y_;
 
@@ -454,12 +447,12 @@
   }
 }
 
-double Scroller::GetSplineDeceleration(float velocity) const {
+double MobileScroller::GetSplineDeceleration(float velocity) const {
   return std::log(kInflexion * std::abs(velocity) /
                   (fling_friction_ * tuning_coeff_));
 }
 
-base::TimeDelta Scroller::GetSplineFlingDuration(float velocity) const {
+base::TimeDelta MobileScroller::GetSplineFlingDuration(float velocity) const {
   const double l = GetSplineDeceleration(velocity);
   const double decel_minus_one = kDecelerationRate - 1.0;
   const double time_seconds = std::exp(l / decel_minus_one);
@@ -467,7 +460,7 @@
                                            base::Time::kMicrosecondsPerSecond);
 }
 
-double Scroller::GetSplineFlingDistance(float velocity) const {
+double MobileScroller::GetSplineFlingDistance(float velocity) const {
   const double l = GetSplineDeceleration(velocity);
   const double decel_minus_one = kDecelerationRate - 1.0;
   return fling_friction_ * tuning_coeff_ *
diff --git a/ui/events/android/scroller.h b/ui/events/mobile_scroller.h
similarity index 92%
rename from ui/events/android/scroller.h
rename to ui/events/mobile_scroller.h
index 37d41cd..9ebd6d7e 100644
--- a/ui/events/android/scroller.h
+++ b/ui/events/mobile_scroller.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef UI_EVENTS_ANDROID_SCROLLER_H_
-#define UI_EVENTS_ANDROID_SCROLLER_H_
+#ifndef UI_EVENTS_MOBILE_SCROLLER_H_
+#define UI_EVENTS_MOBILE_SCROLLER_H_
 
 #include "base/time/time.h"
 #include "ui/events/events_base_export.h"
@@ -15,9 +15,9 @@
 // Native port of android.widget.Scroller.
 // * Change-Id: I4365946f890a76fcfa78ca9d69f2a8e0848095a9
 // * Please update the Change-Id as upstream Android changes are pulled.
-class EVENTS_BASE_EXPORT Scroller : public GestureCurve {
+class EVENTS_BASE_EXPORT MobileScroller : public GestureCurve {
  public:
-  struct Config {
+  struct EVENTS_BASE_EXPORT Config {
     Config();
 
     // Controls fling deceleration. Defaults to 0.015f.
@@ -27,8 +27,8 @@
     bool flywheel_enabled;
   };
 
-  explicit Scroller(const Config& config);
-  ~Scroller() override;
+  explicit MobileScroller(const Config& config);
+  ~MobileScroller() override;
 
   // GestureCurve implementation.
   bool ComputeScrollOffset(base::TimeTicks time,
@@ -148,4 +148,4 @@
 
 }  // namespace ui
 
-#endif  // UI_EVENTS_ANDROID_SCROLLER_H_
+#endif  // UI_EVENTS_MOBILE_SCROLLER_H_
diff --git a/ui/events/android/scroller_unittest.cc b/ui/events/mobile_scroller_unittest.cc
similarity index 74%
rename from ui/events/android/scroller_unittest.cc
rename to ui/events/mobile_scroller_unittest.cc
index 21dae88..d5f4ca58 100644
--- a/ui/events/android/scroller_unittest.cc
+++ b/ui/events/mobile_scroller_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/android/scroller.h"
+#include "ui/events/mobile_scroller.h"
 
 namespace ui {
 namespace {
@@ -19,24 +19,21 @@
 const float kDefaultVelocityY = 220.f;
 const float kEpsilon = 1e-3f;
 
-Scroller::Config DefaultConfig() {
-  return Scroller::Config();
+MobileScroller::Config DefaultConfig() {
+  return MobileScroller::Config();
 }
 
 }  // namespace
 
-class ScrollerTest : public testing::Test {};
+using MobileScrollerTest = testing::Test;
 
-TEST_F(ScrollerTest, Scroll) {
-  Scroller scroller(DefaultConfig());
+TEST_F(MobileScrollerTest, Scroll) {
+  MobileScroller scroller(DefaultConfig());
   base::TimeTicks start_time = base::TimeTicks::Now();
 
   // Start a scroll and verify initialized values.
-  scroller.StartScroll(kDefaultStartX,
-                       kDefaultStartY,
-                       kDefaultDeltaX,
-                       kDefaultDeltaY,
-                       start_time);
+  scroller.StartScroll(kDefaultStartX, kDefaultStartY, kDefaultDeltaX,
+                       kDefaultDeltaY, start_time);
 
   EXPECT_EQ(kDefaultStartX, scroller.GetStartX());
   EXPECT_EQ(kDefaultStartY, scroller.GetStartY());
@@ -50,8 +47,8 @@
   // Advance halfway through the scroll.
   const base::TimeDelta scroll_duration = scroller.GetDuration();
   gfx::Vector2dF offset, velocity;
-  EXPECT_TRUE(scroller.ComputeScrollOffset(
-      start_time + scroll_duration / 2, &offset, &velocity));
+  EXPECT_TRUE(scroller.ComputeScrollOffset(start_time + scroll_duration / 2,
+                                           &offset, &velocity));
 
   // Ensure we've moved in the direction of the delta, but have yet to reach
   // the target.
@@ -72,16 +69,16 @@
   float curr_y = offset.y();
   float curr_velocity_x = velocity.x();
   float curr_velocity_y = velocity.y();
-  EXPECT_TRUE(scroller.ComputeScrollOffset(
-      start_time + scroll_duration / 2, &offset, &velocity));
+  EXPECT_TRUE(scroller.ComputeScrollOffset(start_time + scroll_duration / 2,
+                                           &offset, &velocity));
   EXPECT_EQ(curr_x, offset.x());
   EXPECT_EQ(curr_y, offset.y());
   EXPECT_EQ(curr_velocity_x, velocity.x());
   EXPECT_EQ(curr_velocity_y, velocity.y());
 
   // Advance to the end.
-  EXPECT_FALSE(scroller.ComputeScrollOffset(
-      start_time + scroll_duration, &offset, &velocity));
+  EXPECT_FALSE(scroller.ComputeScrollOffset(start_time + scroll_duration,
+                                            &offset, &velocity));
   EXPECT_EQ(scroller.GetFinalX(), offset.x());
   EXPECT_EQ(scroller.GetFinalY(), offset.y());
   EXPECT_TRUE(scroller.IsFinished());
@@ -90,27 +87,21 @@
   EXPECT_NEAR(0.f, velocity.y(), kEpsilon);
 
   // Try to advance further; nothing should change.
-  EXPECT_FALSE(scroller.ComputeScrollOffset(
-      start_time + scroll_duration * 2, &offset, &velocity));
+  EXPECT_FALSE(scroller.ComputeScrollOffset(start_time + scroll_duration * 2,
+                                            &offset, &velocity));
   EXPECT_EQ(scroller.GetFinalX(), offset.x());
   EXPECT_EQ(scroller.GetFinalY(), offset.y());
   EXPECT_TRUE(scroller.IsFinished());
   EXPECT_EQ(scroll_duration, scroller.GetTimePassed());
 }
 
-TEST_F(ScrollerTest, Fling) {
-  Scroller scroller(DefaultConfig());
+TEST_F(MobileScrollerTest, Fling) {
+  MobileScroller scroller(DefaultConfig());
   base::TimeTicks start_time = base::TimeTicks::Now();
 
   // Start a fling and verify initialized values.
-  scroller.Fling(kDefaultStartX,
-                 kDefaultStartY,
-                 kDefaultVelocityX,
-                 kDefaultVelocityY,
-                 INT_MIN,
-                 INT_MAX,
-                 INT_MIN,
-                 INT_MAX,
+  scroller.Fling(kDefaultStartX, kDefaultStartY, kDefaultVelocityX,
+                 kDefaultVelocityY, INT_MIN, INT_MAX, INT_MIN, INT_MAX,
                  start_time);
 
   EXPECT_EQ(kDefaultStartX, scroller.GetStartX());
@@ -125,8 +116,8 @@
   // Advance halfway through the fling.
   const base::TimeDelta scroll_duration = scroller.GetDuration();
   gfx::Vector2dF offset, velocity;
-  scroller.ComputeScrollOffset(
-      start_time + scroll_duration / 2, &offset, &velocity);
+  scroller.ComputeScrollOffset(start_time + scroll_duration / 2, &offset,
+                               &velocity);
 
   // Ensure we've moved in the direction of the velocity, but have yet to reach
   // the target.
@@ -149,16 +140,16 @@
   float curr_y = offset.y();
   float curr_velocity_x = velocity.x();
   float curr_velocity_y = velocity.y();
-  EXPECT_TRUE(scroller.ComputeScrollOffset(
-      start_time + scroll_duration / 2, &offset, &velocity));
+  EXPECT_TRUE(scroller.ComputeScrollOffset(start_time + scroll_duration / 2,
+                                           &offset, &velocity));
   EXPECT_EQ(curr_x, offset.x());
   EXPECT_EQ(curr_y, offset.y());
   EXPECT_EQ(curr_velocity_x, velocity.x());
   EXPECT_EQ(curr_velocity_y, velocity.y());
 
   // Advance to the end.
-  EXPECT_FALSE(scroller.ComputeScrollOffset(
-      start_time + scroll_duration, &offset, &velocity));
+  EXPECT_FALSE(scroller.ComputeScrollOffset(start_time + scroll_duration,
+                                            &offset, &velocity));
   EXPECT_EQ(scroller.GetFinalX(), offset.x());
   EXPECT_EQ(scroller.GetFinalY(), offset.y());
   EXPECT_TRUE(scroller.IsFinished());
@@ -167,8 +158,8 @@
   EXPECT_NEAR(0.f, velocity.y(), kEpsilon);
 
   // Try to advance further; nothing should change.
-  EXPECT_FALSE(scroller.ComputeScrollOffset(
-      start_time + scroll_duration * 2, &offset, &velocity));
+  EXPECT_FALSE(scroller.ComputeScrollOffset(start_time + scroll_duration * 2,
+                                            &offset, &velocity));
   EXPECT_EQ(scroller.GetFinalX(), offset.x());
   EXPECT_EQ(scroller.GetFinalY(), offset.y());
   EXPECT_TRUE(scroller.IsFinished());
diff --git a/ui/file_manager/audio_player/js/BUILD.gn b/ui/file_manager/audio_player/js/BUILD.gn
index 4130979..4e45a74 100644
--- a/ui/file_manager/audio_player/js/BUILD.gn
+++ b/ui/file_manager/audio_player/js/BUILD.gn
@@ -20,6 +20,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "../../externs/audio_player_foreground.js",
     "../../externs/entry_location.js",
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn
index 60fdb2a..9115dda 100644
--- a/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -41,6 +41,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "../../../externs/background/file_browser_background.js",
     "../../../externs/background/file_browser_background_full.js",
diff --git a/ui/file_manager/file_manager/common/js/BUILD.gn b/ui/file_manager/file_manager/common/js/BUILD.gn
index cbf90af..d696ced 100644
--- a/ui/file_manager/file_manager/common/js/BUILD.gn
+++ b/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -28,6 +28,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "../../../externs/app_window_common.js",
     "../../../externs/background/file_browser_background.js",
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index e5273ea..9c06f70 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -68,6 +68,7 @@
   externs_list = [
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "$externs_path/web_animations.js",
     "../../../externs/app_window_common.js",
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
index 17fdc9a..1498c3f 100644
--- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
@@ -1394,7 +1394,10 @@
     if (i > 0 && !util.isSiblingEntry(entries[0], entries[i]))
       return false;
   }
-  return true;
+  // Check if canCopy is true or undefined, but not false (see
+  // https://crbug.com/849999).
+  return this.metadataModel_.getCache(entries, ['canCopy'])
+      .every(item => item.canCopy !== false);
 };
 
 /**
@@ -1402,8 +1405,18 @@
  * @private
  */
 FileTransferController.prototype.canCutOrDrag_ = function() {
-  return !this.directoryModel_.isReadOnly() &&
-      this.selectionHandler_.selection.entries.length > 0;
+  if (this.directoryModel_.isReadOnly() ||
+      !this.selectionHandler_.isAvailable() ||
+      this.selectionHandler_.selection.entries.length <= 0) {
+    return false;
+  }
+  var entries = this.selectionHandler_.selection.entries;
+  // All entries need the 'canDelete' permission.
+  var metadata = this.metadataModel_.getCache(entries, ['canDelete']);
+  if (metadata.some(item => item.canDelete === false)) {
+    return false;
+  }
+  return true;
 };
 
 /**
@@ -1476,6 +1489,13 @@
       this.isMissingFileContents_(clipboardData))
     return false;
 
+  // Destination entry needs the 'canAddChildren' permission.
+  var metadata =
+      this.metadataModel_.getCache([destinationEntry], ['canAddChildren']);
+  if (metadata[0].canAddChildren === false) {
+    return false;
+  }
+
   return true;
 };
 
@@ -1629,6 +1649,16 @@
     return new DropEffectAndLabel(DropEffectType.NONE,
                                   strf('DEVICE_ACCESS_RESTRICTED'));
   }
+  var destinationMetadata =
+      this.metadataModel_.getCache([destinationEntry], ['canAddChildren']);
+  if (destinationMetadata.length === 1 &&
+      destinationMetadata[0].canAddChildren === false) {
+    // TODO(sashab): Distinguish between copy/move operations and display
+    // corresponding warning text here.
+    return new DropEffectAndLabel(
+        DropEffectType.NONE,
+        strf('DROP_TARGET_FOLDER_NO_MOVE_PERMISSION', destinationEntry.name));
+  }
   if (util.isDropEffectAllowed(event.dataTransfer.effectAllowed, 'move')) {
     if (!util.isDropEffectAllowed(event.dataTransfer.effectAllowed, 'copy'))
       return new DropEffectAndLabel(DropEffectType.MOVE, null);
diff --git a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
index 651f025..3184ff8 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn
@@ -38,6 +38,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "../../../../externs/app_window_common.js",
     "../../../../externs/entry_location.js",
     "../../../../externs/exif_entry.js",
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
index beb0f02..c4b10069 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -45,6 +45,7 @@
   externs_list = [
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "$externs_path/web_animations.js",
     "../../../../externs/app_window_common.js",
diff --git a/ui/file_manager/gallery/js/BUILD.gn b/ui/file_manager/gallery/js/BUILD.gn
index f6b28d1..b3ecb19 100644
--- a/ui/file_manager/gallery/js/BUILD.gn
+++ b/ui/file_manager/gallery/js/BUILD.gn
@@ -29,6 +29,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "$externs_path/web_animations.js",
     "../../externs/entry_location.js",
diff --git a/ui/file_manager/gallery/js/image_editor/BUILD.gn b/ui/file_manager/gallery/js/image_editor/BUILD.gn
index 396ee4aa..84f58f7c 100644
--- a/ui/file_manager/gallery/js/image_editor/BUILD.gn
+++ b/ui/file_manager/gallery/js/image_editor/BUILD.gn
@@ -33,6 +33,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "$externs_path/web_animations.js",
     "../../../externs/app_window_common.js",
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn
index 2975ff0..1b461874 100644
--- a/ui/file_manager/image_loader/BUILD.gn
+++ b/ui/file_manager/image_loader/BUILD.gn
@@ -23,6 +23,7 @@
   externs_list = [
     "$externs_path/chrome_extensions.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/metrics_private.js",
     "//third_party/analytics/externs.js",
   ]
diff --git a/ui/file_manager/integration_tests/file_manager/background.js b/ui/file_manager/integration_tests/file_manager/background.js
index 7a74209..76093225 100644
--- a/ui/file_manager/integration_tests/file_manager/background.js
+++ b/ui/file_manager/integration_tests/file_manager/background.js
@@ -158,8 +158,8 @@
  * @const
  */
 var COMPLEX_DRIVE_ENTRY_SET = [
-  ENTRIES.hello, ENTRIES.readOnlyFolder, ENTRIES.readOnlyDocument,
-  ENTRIES.readOnlyStrictDocument, ENTRIES.readOnlyFile
+  ENTRIES.hello, ENTRIES.photos, ENTRIES.readOnlyFolder,
+  ENTRIES.readOnlyDocument, ENTRIES.readOnlyStrictDocument, ENTRIES.readOnlyFile
 ];
 
 /**
diff --git a/ui/file_manager/integration_tests/file_manager/context_menu.js b/ui/file_manager/integration_tests/file_manager/context_menu.js
index 963c8e3..12b1187 100644
--- a/ui/file_manager/integration_tests/file_manager/context_menu.js
+++ b/ui/file_manager/integration_tests/file_manager/context_menu.js
@@ -71,6 +71,71 @@
 }
 
 /**
+ * Right-clicks on the specified item and selects "Copy".
+ *
+ * @param {string} path Path to the file or folder to copy.
+ * @param {function()=} opt_callback Callback to call after the copy has
+ *     completed.
+ */
+function copyEntryToClipboard(path, opt_callback) {
+  var appId;
+  StepsRunner.run([
+    // Set up Files App.
+    function() {
+      setupAndWaitUntilReady(
+          null, RootPath.DRIVE, this.next, BASIC_LOCAL_ENTRY_SET,
+          COMPLEX_DRIVE_ENTRY_SET);
+    },
+    // Select the file.
+    function(results) {
+      appId = results.windowId;
+      remoteCall.callRemoteTestUtil('selectFile', appId, [path], this.next);
+    },
+    // Wait for the file to be selected.
+    function(result) {
+      chrome.test.assertTrue(result);
+      remoteCall.waitForElement(appId, '.table-row[selected]').then(this.next);
+    },
+    // Right-click on the file.
+    function() {
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseRightClick', appId, ['.table-row[selected]'], this.next);
+    },
+    // Wait for the context menu to appear.
+    function(result) {
+      chrome.test.assertTrue(result);
+      remoteCall.waitForElement(appId, '#file-context-menu:not([hidden])')
+          .then(this.next);
+    },
+    // Wait for the 'copy' command to appear.
+    function() {
+      remoteCall
+          .waitForElement(
+              appId, '[command="#copy"]:not([hidden]):not([disabled])')
+          .then(this.next);
+    },
+    // Select 'copy'.
+    function() {
+      remoteCall.callRemoteTestUtil(
+          'fakeMouseClick', appId,
+          ['[command="#copy"]:not([hidden]):not([disabled])'], this.next);
+    },
+    // Wait for the context menu to disappear.
+    function(result) {
+      chrome.test.assertTrue(result);
+      remoteCall.waitForElement(appId, '#file-context-menu[hidden]')
+          .then(this.next);
+    },
+    // Check for Javascript errors.
+    function() {
+      checkIfNoErrorsOccured(this.next);
+      if (opt_callback)
+        opt_callback();
+    }
+  ]);
+}
+
+/**
  * Tests that the Delete menu item is enabled if a read-write entry is selected.
  */
 testcase.checkDeleteEnabledForReadWriteFile = function() {
@@ -129,3 +194,97 @@
 testcase.checkRenameDisabledForReadOnlyFolder = function() {
   checkContextMenu('rename', 'Read-Only Folder', false);
 };
+
+/**
+ * Tests that the Copy menu item is enabled if a read-write entry is selected.
+ */
+testcase.checkCopyEnabledForReadWriteFile = function() {
+  checkContextMenu('copy', 'hello.txt', true);
+};
+
+/**
+ * Tests that the Copy menu item is enabled if a read-only document is
+ * selected.
+ */
+testcase.checkCopyEnabledForReadOnlyDocument = function() {
+  checkContextMenu('copy', 'Read-Only Doc.gdoc', true);
+};
+
+/**
+ * Tests that the Copy menu item is disabled if a strict (no-copy) read-only
+ * document is selected.
+ */
+testcase.checkCopyDisabledForStrictReadOnlyDocument = function() {
+  checkContextMenu('copy', 'Read-Only Doc.gdoc', true);
+};
+
+/**
+ * Tests that the Copy menu item is enabled if a read-only file is selected.
+ */
+testcase.checkCopyEnabledForReadOnlyFile = function() {
+  checkContextMenu('copy', 'Read-Only File.jpg', true);
+};
+
+/**
+ * Tests that the Copy menu item is enabled if a read-only folder is
+ * selected.
+ */
+testcase.checkCopyEnabledForReadOnlyFolder = function() {
+  checkContextMenu('copy', 'Read-Only Folder', true);
+};
+
+/**
+ * Tests that the Cut menu item is enabled if a read-write entry is selected.
+ */
+testcase.checkCutEnabledForReadWriteFile = function() {
+  checkContextMenu('cut', 'hello.txt', true);
+};
+
+/**
+ * Tests that the Cut menu item is disabled if a read-only document is
+ * selected.
+ */
+testcase.checkCutDisabledForReadOnlyDocument = function() {
+  checkContextMenu('cut', 'Read-Only Doc.gdoc', false);
+};
+
+/**
+ * Tests that the Cut menu item is disabled if a read-only file is selected.
+ */
+testcase.checkCutDisabledForReadOnlyFile = function() {
+  checkContextMenu('cut', 'Read-Only File.jpg', false);
+};
+
+/**
+ * Tests that the Cut menu item is disabled if a read-only folder is
+ * selected.
+ */
+testcase.checkCutDisabledForReadOnlyFolder = function() {
+  checkContextMenu('cut', 'Read-Only Folder', false);
+};
+
+/**
+ * Tests that the Paste into Folder menu item is enabled if a read-write folder
+ * is selected.
+ * TODO(sashab): Make this check happen in the same window.
+ */
+testcase.checkPasteIntoFolderEnabledForReadWriteFolder = function() {
+  copyEntryToClipboard('hello.txt', () => {
+    checkContextMenu('paste-into-folder', 'photos', true);
+  });
+};
+
+/**
+ * Tests that the Paste into Folder menu item is disabled if a read-only folder
+ * is selected.
+ * TODO(sashab): Make this check happen in the same window.
+ */
+testcase.checkPasteIntoFolderDisabledForReadOnlyFolder = function() {
+  copyEntryToClipboard('hello.txt', () => {
+    checkContextMenu('paste-into-folder', 'Read-Only Folder', false);
+  });
+};
+
+/** TODO(sashab): Add tests for copying to/from the directory tree on the LHS.
+ */
+/** TODO(sashab): Add tests for pasting into the current directory. */
diff --git a/ui/file_manager/video_player/js/BUILD.gn b/ui/file_manager/video_player/js/BUILD.gn
index deeeec4..befacf4 100644
--- a/ui/file_manager/video_player/js/BUILD.gn
+++ b/ui/file_manager/video_player/js/BUILD.gn
@@ -21,6 +21,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/media_player_private.js",
     "$externs_path/metrics_private.js",
     "../../externs/chrome_cast.js",
diff --git a/ui/file_manager/video_player/js/cast/BUILD.gn b/ui/file_manager/video_player/js/cast/BUILD.gn
index 2d10b23..2435e5b 100644
--- a/ui/file_manager/video_player/js/cast/BUILD.gn
+++ b/ui/file_manager/video_player/js/cast/BUILD.gn
@@ -20,6 +20,7 @@
     "$externs_path/chrome_extensions.js",
     "$externs_path/command_line_private.js",
     "$externs_path/file_manager_private.js",
+    "$externs_path/file_system_provider.js",
     "$externs_path/media_player_private.js",
     "$externs_path/metrics_private.js",
     "../../../externs/app_window_common.js",
diff --git a/ui/webui/resources/cr_components/certificate_manager/compiled_resources2.gyp b/ui/webui/resources/cr_components/certificate_manager/compiled_resources2.gyp
deleted file mode 100644
index fef217be..0000000
--- a/ui/webui/resources/cr_components/certificate_manager/compiled_resources2.gyp
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'ca_trust_edit_dialog',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_delete_confirmation_dialog',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_entry',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_list',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        'certificate_manager_types',
-        'certificate_subentry',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_manager',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
-        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
-        'certificate_list',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_manager_types',
-      'dependencies': [
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_password_decryption_dialog',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_password_encryption_dialog',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificate_subentry',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_lazy_render/compiled_resources2.gyp:cr_lazy_render',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificates_browser_proxy',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'certificates_error_dialog',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
-        'certificate_manager_types',
-        'certificates_browser_proxy',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_components/chromeos/compiled_resources2.gyp b/ui/webui/resources/cr_components/chromeos/compiled_resources2.gyp
deleted file mode 100644
index 7f8f0726..0000000
--- a/ui/webui/resources/cr_components/chromeos/compiled_resources2.gyp
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'network_resources',
-      'type': 'none',
-      'dependencies': [
-        'network/compiled_resources2.gyp:*',
-      ],
-    },
-    {
-      'target_name': 'quick_unlock_resources',
-      'type': 'none',
-      'dependencies': [
-        'quick_unlock/compiled_resources2.gyp:*',
-      ],
-    },
-    {
-      'target_name': 'bluetooth_dialog',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_input/compiled_resources2.gyp:cr_input',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
-        '<(EXTERNS_GYP):bluetooth',
-        '<(EXTERNS_GYP):bluetooth_private',
-        '<(INTERFACES_GYP):bluetooth_interface',
-        '<(INTERFACES_GYP):bluetooth_private_interface',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp b/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
deleted file mode 100644
index b351da3..0000000
--- a/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
+++ /dev/null
@@ -1,113 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'network_apnlist',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_choose_mobile',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(EXTERNS_GYP):networking_private',
-        '<(INTERFACES_GYP):networking_private_interface',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_config',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(EXTERNS_GYP):networking_private',
-        '<(INTERFACES_GYP):networking_private_interface',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_config_select',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(EXTERNS_GYP):networking_private',
-        '<(INTERFACES_GYP):networking_private_interface',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_ip_config',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_nameservers',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_password_input',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_property_list',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_network_behavior',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_proxy',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_network_behavior',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_proxy_input',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_proxy_exclusions',
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'network_siminfo',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
-        '<(INTERFACES_GYP):networking_private_interface',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/compiled_resources2.gyp b/ui/webui/resources/cr_components/chromeos/quick_unlock/compiled_resources2.gyp
deleted file mode 100644
index 4d592c21..0000000
--- a/ui/webui/resources/cr_components/chromeos/quick_unlock/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'pin_keyboard',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted',
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_input/compiled_resources2.gyp:cr_input',
-       ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_components/compiled_resources2.gyp b/ui/webui/resources/cr_components/compiled_resources2.gyp
deleted file mode 100644
index eb688de..0000000
--- a/ui/webui/resources/cr_components/compiled_resources2.gyp
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_components_resources',
-      'type': 'none',
-      'dependencies': [
-        'chromeos/compiled_resources2.gyp:*',
-        'certificate_manager/compiled_resources2.gyp:*',
-      ],
-    },
-  ]
-}
diff --git a/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp b/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
deleted file mode 100644
index 7181c69..0000000
--- a/ui/webui/resources/cr_elements/chromeos/cr_picture/compiled_resources2.gyp
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'dependencies': [ 'cr_png_behavior' ],
-      'target_name': 'cr_camera',
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-selector/compiled_resources2.gyp:iron-selector-extracted',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        'cr_png_behavior',
-        'cr_picture_types',
-      ],
-      'target_name': 'cr_picture_list',
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'dependencies': [
-        'cr_camera',
-        'cr_png_behavior',
-        'cr_picture_types',
-      ],
-      'target_name': 'cr_picture_pane',
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_picture_types',
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_png_behavior',
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp b/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp
deleted file mode 100644
index d4b7645..0000000
--- a/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_network_icon',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        'cr_onc_types',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_network_icon_externs',
-      'includes': ['../../../../../../third_party/closure_compiler/include_js.gypi'],
-    },
-    {
-      'target_name': 'cr_network_list',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:cr_scrollable_behavior',
-        'cr_network_list_types',
-        'cr_onc_types',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_network_list_item',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_network_behavior',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        'cr_network_list_types',
-        'cr_onc_types',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_network_list_types',
-      'dependencies': [
-        'cr_onc_types',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_network_select',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
-        '<(EXTERNS_GYP):networking_private',
-        'cr_network_list_types',
-        'cr_onc_types',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_onc_types',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
-        '<(EXTERNS_GYP):networking_private',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/compiled_resources2.gyp b/ui/webui/resources/cr_elements/compiled_resources2.gyp
deleted file mode 100644
index fab52d7..0000000
--- a/ui/webui/resources/cr_elements/compiled_resources2.gyp
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_elements_resources',
-      'type': 'none',
-      'dependencies': [
-        'chromeos/cr_picture/compiled_resources2.gyp:*',
-        'chromeos/network/compiled_resources2.gyp:*',
-        'cr_action_menu/compiled_resources2.gyp:*',
-        'cr_checkbox/compiled_resources2.gyp:*',
-        'cr_dialog/compiled_resources2.gyp:*',
-        'cr_drawer/compiled_resources2.gyp:*',
-        'cr_expand_button/compiled_resources2.gyp:*',
-        'cr_link_row/compiled_resources2.gyp:*',
-        'cr_profile_avatar_selector/compiled_resources2.gyp:*',
-        'cr_radio_button/compiled_resources2.gyp:*',
-        'cr_toast/compiled_resources2.gyp:*',
-        'cr_toggle/compiled_resources2.gyp:*',
-        'policy/compiled_resources2.gyp:*',
-      ],
-    },
-    {
-      'target_name': 'cr_scrollable_behavior',
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-list/compiled_resources2.gyp:iron-list-extracted',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_container_shadow_behavior',
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ]
-}
diff --git a/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp
deleted file mode 100644
index 5b542f02..0000000
--- a/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_action_menu',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
-        '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
-        '<(EXTERNS_GYP):pending',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_checkbox/compiled_resources2.gyp
deleted file mode 100644
index 89099ab..0000000
--- a/ui/webui/resources/cr_elements/cr_checkbox/compiled_resources2.gyp
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_checkbox',
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp:paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp
deleted file mode 100644
index abdc3e5..0000000
--- a/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_dialog',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-icon-button/compiled_resources2.gyp:paper-icon-button-extracted',
-        '<(EXTERNS_GYP):web_animations',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_drawer/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_drawer/compiled_resources2.gyp
deleted file mode 100644
index 5f78fe0..0000000
--- a/ui/webui/resources/cr_elements/cr_drawer/compiled_resources2.gyp
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_drawer',
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_expand_button/compiled_resources2.gyp
deleted file mode 100644
index 45d702fe..0000000
--- a/ui/webui/resources/cr_elements/cr_expand_button/compiled_resources2.gyp
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_expand_button',
-      'dependencies': [
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_lazy_render/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_lazy_render/compiled_resources2.gyp
deleted file mode 100644
index f3a5b6ec..0000000
--- a/ui/webui/resources/cr_elements/cr_lazy_render/compiled_resources2.gyp
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_lazy_render',
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_link_row/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_link_row/compiled_resources2.gyp
deleted file mode 100644
index 14b35f6..0000000
--- a/ui/webui/resources/cr_elements/cr_link_row/compiled_resources2.gyp
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_link_row',
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp:paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_profile_avatar_selector/compiled_resources2.gyp
deleted file mode 100644
index c050538..0000000
--- a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/compiled_resources2.gyp
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_profile_avatar_selector',
-      'dependencies': [
-        '../../js/compiled_resources2.gyp:icon',
-        'cr_profile_avatar_selector_grid',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_profile_avatar_selector_grid',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_radio_button/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_radio_button/compiled_resources2.gyp
deleted file mode 100644
index b412b28..0000000
--- a/ui/webui/resources/cr_elements/cr_radio_button/compiled_resources2.gyp
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_radio_button',
-      'dependencies': [
-        'cr_radio_button_behavior'
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_radio_button_behavior',
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp:paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_search_field/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_search_field/compiled_resources2.gyp
deleted file mode 100644
index e7373917..0000000
--- a/ui/webui/resources/cr_elements/cr_search_field/compiled_resources2.gyp
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_search_field_behavior',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_toast/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_toast/compiled_resources2.gyp
deleted file mode 100644
index 4393c4e..0000000
--- a/ui/webui/resources/cr_elements/cr_toast/compiled_resources2.gyp
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_toast',
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_toggle/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_toggle/compiled_resources2.gyp
deleted file mode 100644
index 04592082..0000000
--- a/ui/webui/resources/cr_elements/cr_toggle/compiled_resources2.gyp
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_toggle',
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-behaviors/compiled_resources2.gyp:iron-button-state-extracted',
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-behaviors/compiled_resources2.gyp:paper-ripple-behavior-extracted',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp
deleted file mode 100644
index 48f54b9..0000000
--- a/ui/webui/resources/cr_elements/cr_toolbar/compiled_resources2.gyp
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_toolbar_search_field',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/cr_elements/cr_search_field/compiled_resources2.gyp:cr_search_field_behavior',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_toolbar_selection_overlay',
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-      'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted',
-      ],
-    },
-    {
-      'target_name': 'cr_toolbar',
-      'dependencies': [
-        '<(EXTERNS_GYP):web_animations',
-        'cr_toolbar_search_field',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp b/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp
deleted file mode 100644
index 8b6dede4..0000000
--- a/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'cr_policy_indicator',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-        'cr_policy_indicator_behavior',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_policy_indicator_behavior',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_policy_pref_behavior',
-      'dependencies': [
-        '<(EXTERNS_GYP):settings_private',
-        'cr_policy_indicator_behavior',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_policy_pref_indicator',
-      'dependencies': [
-        '<(EXTERNS_GYP):settings_private',
-        'cr_policy_indicator_behavior',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_policy_network_behavior',
-      'dependencies': [
-        '../chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        'cr_policy_indicator_behavior',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_policy_network_indicator',
-      'dependencies': [
-        '../chromeos/network/compiled_resources2.gyp:cr_onc_types',
-        'cr_policy_indicator_behavior',
-        'cr_policy_network_behavior',
-      ],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr_tooltip_icon',
-      'dependencies': [],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/js/compiled_resources2.gyp b/ui/webui/resources/js/compiled_resources2.gyp
deleted file mode 100644
index fdbd3235..0000000
--- a/ui/webui/resources/js/compiled_resources2.gyp
+++ /dev/null
@@ -1,113 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'action_link',
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'assert',
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'cr',
-      'dependencies': [
-        'promise_resolver',
-        '<(EXTERNS_GYP):chrome_send',
-        'assert',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'event_tracker',
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'webui_listener_tracker',
-      'dependencies': [
-        'cr',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'search_highlight_utils',
-      'dependencies': [
-        'cr',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'icon',
-      'dependencies': [
-        'cr',
-        'util',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'i18n_template_no_process',
-      'dependencies': [
-        'load_time_data',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'i18n_template',
-      'dependencies': [
-        'i18n_template_no_process',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'i18n_behavior',
-      'dependencies': [
-        'load_time_data',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'list_property_update_behavior',
-      'dependencies': [
-        '<(DEPTH)/third_party/jstemplate/compiled_resources2.gyp:jstemplate',
-        'assert',
-        'parse_html_subset',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'load_time_data',
-      'dependencies': [
-        '<(DEPTH)/third_party/jstemplate/compiled_resources2.gyp:jstemplate',
-        'assert',
-        'parse_html_subset',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'parse_html_subset',
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'promise_resolver',
-      'dependencies': ['assert'],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'util',
-      'dependencies': [
-        '<(EXTERNS_GYP):chrome_send',
-        'cr',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'web_ui_listener_behavior',
-      'dependencies': [
-        'cr',
-      ],
-      'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/js/cr/compiled_resources2.gyp b/ui/webui/resources/js/cr/compiled_resources2.gyp
deleted file mode 100644
index d0517c5..0000000
--- a/ui/webui/resources/js/cr/compiled_resources2.gyp
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'event_target',
-      'dependencies': ['../compiled_resources2.gyp:cr'],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'ui',
-      'dependencies': ['../compiled_resources2.gyp:cr'],
-      'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/js/cr/ui/compiled_resources2.gyp b/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
deleted file mode 100644
index f64dd9f..0000000
--- a/ui/webui/resources/js/cr/ui/compiled_resources2.gyp
+++ /dev/null
@@ -1,235 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'array_data_model',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:event_target',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'autocomplete_list',
-      'dependencies': [
-        'list',
-        'list_single_selection_model',
-        'position_util',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'command',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:ui',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'context_menu_button',
-      'dependencies': [
-        'menu_button',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'context_menu_handler',
-      'dependencies': [
-         '../../compiled_resources2.gyp:cr',
-         '../compiled_resources2.gyp:event_target',
-         '../compiled_resources2.gyp:ui',
-         'menu',
-         'menu_button',
-         'position_util',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'dialogs',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'drag_wrapper',
-      'dependencies': [
-        '../../compiled_resources2.gyp:assert',
-        '../../compiled_resources2.gyp:cr',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'focus_grid',
-      'dependencies': [
-        '../../compiled_resources2.gyp:assert',
-        '../../compiled_resources2.gyp:cr',
-        '../../compiled_resources2.gyp:event_tracker',
-        'focus_row',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'focus_manager',
-      'dependencies': ['../../compiled_resources2.gyp:cr'],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'focus_outline_manager',
-      'dependencies': ['../../compiled_resources2.gyp:cr'],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'focus_row',
-      'dependencies': [
-        '../../compiled_resources2.gyp:assert',
-        '../../compiled_resources2.gyp:cr',
-        '../../compiled_resources2.gyp:event_tracker',
-        '../../compiled_resources2.gyp:util',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'focus_without_ink',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:ui',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'grid',
-      'dependencies': [
-        'list',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'list',
-      'dependencies': [
-        'array_data_model',
-        'list_item',
-        'list_selection_controller',
-        'list_selection_model',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'list_item',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'list_selection_controller',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        'list_selection_model',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'list_selection_model',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:event_target',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'list_single_selection_model',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:event_target',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'menu_button',
-      'dependencies': [
-        '../../compiled_resources2.gyp:assert',
-        '../../compiled_resources2.gyp:cr',
-        '../../compiled_resources2.gyp:event_tracker',
-        '../compiled_resources2.gyp:ui',
-        'menu',
-        'menu_item',
-        'position_util',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'menu_item',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../../compiled_resources2.gyp:load_time_data',
-        '../compiled_resources2.gyp:ui',
-        'command',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'menu',
-      'dependencies': [
-        '../../compiled_resources2.gyp:assert',
-        '../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:ui',
-        'menu_item',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'node_utils',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'overlay',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../../compiled_resources2.gyp:util',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'position_util',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'splitter',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:ui',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'table',
-      'dependencies': [
-        'list',
-        'list_single_selection_model',
-        'table/compiled_resources2.gyp:table_column_model',
-        'table/compiled_resources2.gyp:table_header',
-        'table/compiled_resources2.gyp:table_list',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'tree',
-      'dependencies': [
-        '../../compiled_resources2.gyp:cr',
-        '../../compiled_resources2.gyp:util',
-        '../compiled_resources2.gyp:ui',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}
diff --git a/ui/webui/resources/js/cr/ui/table/compiled_resources2.gyp b/ui/webui/resources/js/cr/ui/table/compiled_resources2.gyp
deleted file mode 100644
index 5bb25ad8..0000000
--- a/ui/webui/resources/js/cr/ui/table/compiled_resources2.gyp
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'targets': [
-    {
-      'target_name': 'table_column',
-      'dependencies': [
-        '../../../compiled_resources2.gyp:cr',
-        '../../compiled_resources2.gyp:event_target',
-      ],
-      'includes': ['../../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'table_column_model',
-      'dependencies': [
-        '../../../compiled_resources2.gyp:cr',
-        'table_column',
-      ],
-      'includes': ['../../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'table_header',
-      'dependencies': [
-        '../../../compiled_resources2.gyp:cr',
-        'table_splitter',
-      ],
-      'includes': ['../../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'table_list',
-      'dependencies': [
-        '../../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:list',
-        'table_column_model',
-      ],
-      'includes': ['../../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
-      'target_name': 'table_splitter',
-      'dependencies': [
-        '../../../compiled_resources2.gyp:cr',
-        '../compiled_resources2.gyp:splitter',
-        'table_column_model',
-      ],
-      'includes': ['../../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-  ],
-}