diff --git a/DEPS b/DEPS
index 09e437d..3f4bda79 100644
--- a/DEPS
+++ b/DEPS
@@ -43,7 +43,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '8abf5a71f66954b01b5b1055555f0bf6dc901e82',
+  'v8_revision': 'c66911aa4bec771552e1a32f1ca558509b15d677',
   # 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.
@@ -95,7 +95,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '74b1b4470c7cc4404a524796ef972b47c7b9c8bc',
+  'catapult_revision': '03fbd54d8fdb0defa1a677b71d67a9f46544fa86',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/chrome/VERSION b/chrome/VERSION
index 3f8d5ad..afe9430 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=55
 MINOR=0
-BUILD=2874
+BUILD=2875
 PATCH=0
diff --git a/chrome/android/java/res/drawable-hdpi/instant_badge.png b/chrome/android/java/res/drawable-hdpi/instant_badge.png
deleted file mode 100644
index 2504489a..0000000
--- a/chrome/android/java/res/drawable-hdpi/instant_badge.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/instant_badge.png b/chrome/android/java/res/drawable-mdpi/instant_badge.png
deleted file mode 100644
index 05ae68c3..0000000
--- a/chrome/android/java/res/drawable-mdpi/instant_badge.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/instant_badge.png b/chrome/android/java/res/drawable-xhdpi/instant_badge.png
deleted file mode 100644
index 3b00f804..0000000
--- a/chrome/android/java/res/drawable-xhdpi/instant_badge.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/instant_badge.png b/chrome/android/java/res/drawable-xxhdpi/instant_badge.png
deleted file mode 100644
index 018aa7a..0000000
--- a/chrome/android/java/res/drawable-xxhdpi/instant_badge.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/instant_badge.png b/chrome/android/java/res/drawable-xxxhdpi/instant_badge.png
deleted file mode 100644
index f93cd66..0000000
--- a/chrome/android/java/res/drawable-xxxhdpi/instant_badge.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/layout/infobar_control_two_line_description.xml b/chrome/android/java/res/layout/infobar_control_two_line_description.xml
deleted file mode 100644
index 5db09684..0000000
--- a/chrome/android/java/res/layout/infobar_control_two_line_description.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- Copyright 2016 The Chromium Authors. All rights reserved.
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center_vertical"
-    android:orientation="vertical">
-    <TextView
-        android:id="@+id/description_top_line"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/infobar_control_margin_between_rows"
-        android:drawablePadding="@dimen/infobar_control_margin_between_items"
-        android:textSize="@dimen/infobar_descriptive_text_size"
-        android:textColor="@color/infobar_descriptive_text_color"
-        android:textColorLink="@color/infobar_accent_blue" />
-    <TextView
-        android:id="@+id/description_bottom_line"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="@dimen/infobar_descriptive_text_size"
-        android:textColor="@color/infobar_descriptive_text_color"
-        android:textColorLink="@color/infobar_accent_blue" />
-</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
index 0bf4a074..a7ed074 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ServiceTabLauncher.java
@@ -116,7 +116,7 @@
                 }
             }
         };
-        WebappRegistry.getWebappDataStorageForUrl(context, url, callback);
+        WebappRegistry.getWebappDataStorageForUrl(url, callback);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 2c72f33..b1745197 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -168,7 +168,7 @@
                 // process is complete, call back to native code to start the splash image
                 // download.
                 WebappRegistry.registerWebapp(
-                        context, id, new WebappRegistry.FetchWebappDataStorageCallback() {
+                        id, new WebappRegistry.FetchWebappDataStorageCallback() {
                             @Override
                             public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                                 storage.updateFromShortcutIntent(resultIntent);
@@ -235,8 +235,8 @@
     @SuppressWarnings("unused")
     @CalledByNative
     private static void storeWebappSplashImage(final String id, final Bitmap splashImage) {
-        WebappRegistry.getWebappDataStorage(ContextUtils.getApplicationContext(), id,
-                new WebappRegistry.FetchWebappDataStorageCallback() {
+        WebappRegistry.getWebappDataStorage(
+                id, new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         if (storage == null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarControlLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarControlLayout.java
index 896120e..1f9e7cf0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarControlLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarControlLayout.java
@@ -381,34 +381,6 @@
     }
 
     /**
-     * Creates and adds a full-width control with two lines of additional text describing what
-     * an InfoBar is for. The first line has a left aligned icon at the start of the line.
-     * @param iconResourceId The id for the first line icon.
-     * @param message1 The message following the icon.
-     * @param message2 The second line message.
-     */
-    public View addTwoLineDescription(int iconResourceId,
-            CharSequence message1, CharSequence message2) {
-        ControlLayoutParams params = new ControlLayoutParams();
-        params.mMustBeFullWidth = true;
-
-        View descriptionView = LayoutInflater.from(getContext()).inflate(
-                R.layout.infobar_control_two_line_description, this, false);
-        addView(descriptionView, params);
-
-        TextView topLine = (TextView) descriptionView.findViewById(R.id.description_top_line);
-        topLine.setText(message1);
-        topLine.setMovementMethod(LinkMovementMethod.getInstance());
-        topLine.setCompoundDrawablesWithIntrinsicBounds(iconResourceId, 0, 0, 0);
-
-        TextView bottomLine = (TextView) descriptionView.findViewById(R.id.description_bottom_line);
-        bottomLine.setText(message2);
-        bottomLine.setMovementMethod(LinkMovementMethod.getInstance());
-
-        return descriptionView;
-    }
-
-    /**
      * Creates and adds a control that shows a review rating score.
      *
      * @param rating Fractional rating out of 5 stars.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java
index 69a0c4d..6392813 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBar.java
@@ -11,6 +11,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.instantapps.InstantAppsBannerData;
 import org.chromium.chrome.browser.widget.DualControlLayout;
+import org.chromium.components.url_formatter.UrlFormatter;
 
 /**
  * Infobar that asks the user whether they want to use an instant app for a particular website.
@@ -28,15 +29,14 @@
     public void createContent(InfoBarLayout layout) {
         super.createContent(layout);
 
-        int launchButtonColor = ApiCompatibilityUtils.getColor(getContext().getResources(),
-                R.color.app_banner_install_button_bg);
-
         layout.setIsUsingBigIcon();
         layout.setMessage(mData.getAppName());
-        layout.getMessageLayout().addTwoLineDescription(R.drawable.instant_badge,
-                getContext().getString(R.string.instant_apps_info_bar_label), mData.getHostname());
+        layout.getMessageLayout().addDescription(
+                UrlFormatter.formatUrlForSecurityDisplay(mData.getUrl(), false));
         layout.getPrimaryButton().setText(R.string.instant_apps_open_in_app);
-        layout.getPrimaryButton().setButtonColor(launchButtonColor);
+        layout.getPrimaryButton()
+                .setButtonColor(ApiCompatibilityUtils.getColor(getContext().getResources(),
+                        R.color.app_banner_install_button_bg));
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java
index bcf8a81..39284302 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InstantAppsInfoBarDelegate.java
@@ -16,8 +16,6 @@
 import org.chromium.chrome.browser.instantapps.InstantAppsHandler;
 import org.chromium.content_public.browser.WebContents;
 
-import java.net.URI;
-
 /**
  * Delegate for {@link InstantAppsInfoBar}. Use launch() method to display the infobar.
  */
@@ -26,16 +24,9 @@
 
     private InstantAppsBannerData mData;
 
-    public static void launch(WebContents webContents, String label, Bitmap icon, Intent intent) {
-        String hostname = "";
-        try {
-            URI uri = URI.create(webContents.getUrl());
-            hostname = uri.getRawAuthority();
-        } catch (IllegalArgumentException e) {
-            // not able to parse the URL.
-        }
-        InstantAppsBannerData appsBannerData = new InstantAppsBannerData(
-                label, icon, hostname, intent);
+    public static void launch(WebContents webContents, String url, String label, Bitmap icon,
+            Intent intent) {
+        InstantAppsBannerData appsBannerData = new InstantAppsBannerData(label, icon, url, intent);
         nativeLaunch(webContents, appsBannerData);
     }
 
@@ -54,7 +45,7 @@
         } catch (ActivityNotFoundException e) {
             Log.e(TAG, "No activity found to launch intent " + data.getIntent(), e);
         }
-        InstantAppsHandler.getInstance().recordDefaultOpen(data.getHostname());
+        InstantAppsHandler.getInstance().recordDefaultOpen(data.getUrl());
     }
 
     private static native void nativeLaunch(WebContents webContents, InstantAppsBannerData data);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java
index f60f179..cbcccdb63 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/instantapps/InstantAppsBannerData.java
@@ -13,13 +13,13 @@
 public class InstantAppsBannerData {
     private String mAppName;
     private Bitmap mAppIcon;
-    private String mHostname;
+    private String mUrl;
     private Intent mIntent;
 
-    public InstantAppsBannerData(String appName, Bitmap icon, String hostname, Intent intent) {
+    public InstantAppsBannerData(String appName, Bitmap icon, String url, Intent intent) {
         mAppName = appName;
         mAppIcon = icon;
-        mHostname = hostname;
+        mUrl = url;
         mIntent = intent;
     }
 
@@ -34,8 +34,8 @@
     }
 
     /** @return The host name for the URL. */
-    public String getHostname() {
-        return mHostname;
+    public String getUrl() {
+        return mUrl;
     }
 
     /** @return The intent to launch on "Open App" button click. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
index b7f4436..8c03ea5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -51,8 +51,8 @@
         // Register the WebAPK. It is possible that a WebAPK's meta data was deleted when user
         // cleared Chrome's data. When it is launched again, we know that the WebAPK is still
         // installed, so re-register it.
-        WebappRegistry.registerWebapp(WebApkActivity.this, mWebappInfo.id(),
-                new WebappRegistry.FetchWebappDataStorageCallback() {
+        WebappRegistry.registerWebapp(
+                mWebappInfo.id(), new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         updateStorage(storage);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
index ddda953..01800a7f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
@@ -92,8 +92,7 @@
                         }
                     }
         };
-        WebappRegistry.getWebappDataStorage(
-                ContextUtils.getApplicationContext(), info.id(), callback);
+        WebappRegistry.getWebappDataStorage(info.id(), callback);
     }
 
     @Override
@@ -161,8 +160,7 @@
      */
     @CalledByNative
     private static void onBuiltWebApk(final boolean success, String webapkPackage) {
-        WebappRegistry.getWebappDataStorage(ContextUtils.getApplicationContext(),
-                WebApkConstants.WEBAPK_ID_PREFIX + webapkPackage,
+        WebappRegistry.getWebappDataStorage(WebApkConstants.WEBAPK_ID_PREFIX + webapkPackage,
                 new FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 3d04730f..7022ef3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -199,7 +199,7 @@
         // Kick off the old web app cleanup (if we haven't already) now that we have queued the
         // current web app's storage to be opened.
         if (!mOldWebappCleanupStarted) {
-            WebappRegistry.unregisterOldWebapps(this, System.currentTimeMillis());
+            WebappRegistry.unregisterOldWebapps(System.currentTimeMillis());
             mOldWebappCleanupStarted = true;
         }
     }
@@ -262,8 +262,8 @@
     }
 
     protected void initializeSplashScreenWidgets(final int backgroundColor) {
-        WebappRegistry.getWebappDataStorage(this, mWebappInfo.id(),
-                new WebappRegistry.FetchWebappDataStorageCallback() {
+        WebappRegistry.getWebappDataStorage(
+                mWebappInfo.id(), new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         if (storage == null) {
@@ -280,8 +280,7 @@
                             }
                         });
                     }
-                }
-        );
+                });
     }
 
     protected void onStorageIsNull(int backgroundColor) {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
index d42f7b2..41f8f4d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -10,6 +10,7 @@
 import android.graphics.Bitmap;
 import android.os.AsyncTask;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.blink_public.platform.WebDisplayMode;
@@ -80,11 +81,10 @@
     /**
      * Opens an instance of WebappDataStorage for the web app specified. Must not be run on the UI
      * thread.
-     * @param context  The context to open the SharedPreferences.
      * @param webappId The ID of the web app which is being opened.
      */
-    static WebappDataStorage open(final Context context, final String webappId) {
-        final WebappDataStorage storage = sFactory.create(context, webappId);
+    static WebappDataStorage open(final String webappId) {
+        final WebappDataStorage storage = sFactory.create(webappId);
         if (storage.getLastUsedTime() == LAST_USED_INVALID) {
             // If the last used time is invalid then ensure that there is no data in the
             // WebappDataStorage which needs to be cleaned up.
@@ -96,18 +96,15 @@
     /**
      * Asynchronously retrieves the time which this WebappDataStorage was last opened. Used in
      * testing.
-     * @param context  The context to read the SharedPreferences file.
      * @param webappId The ID of the web app the used time is being read for.
      * @param callback Called when the last used time has been retrieved.
      */
     @VisibleForTesting
-    public static void getLastUsedTime(final Context context, final String webappId,
-            final FetchCallback<Long> callback) {
+    public static void getLastUsedTime(final String webappId, final FetchCallback<Long> callback) {
         new AsyncTask<Void, Void, Long>() {
             @Override
             protected final Long doInBackground(Void... nothing) {
-                long lastUsed = new WebappDataStorage(context.getApplicationContext(), webappId)
-                        .getLastUsedTime();
+                long lastUsed = new WebappDataStorage(webappId).getLastUsedTime();
                 assert lastUsed != LAST_USED_INVALID;
                 return lastUsed;
             }
@@ -123,17 +120,15 @@
     /**
      * Asynchronously retrieves the scope stored in this WebappDataStorage. The scope is the URL
      * over which the web app data is applied to. Used in testing.
-     * @param context  The context to read the SharedPreferences file.
      * @param webappId The ID of the web app the used time is being read for.
      * @param callback Called when the scope has been retrieved.
      */
     @VisibleForTesting
-    public static void getScope(final Context context, final String webappId,
-            final FetchCallback<String> callback) {
+    public static void getScope(final String webappId, final FetchCallback<String> callback) {
         new AsyncTask<Void, Void, String>() {
             @Override
             protected final String doInBackground(Void... nothing) {
-                return new WebappDataStorage(context.getApplicationContext(), webappId).getScope();
+                return new WebappDataStorage(webappId).getScope();
             }
 
             @Override
@@ -146,17 +141,15 @@
 
     /**
      * Asynchronously retrieves the URL stored in this WebappDataStorage. Used in testing.
-     * @param context  The context to read the SharedPreferences file.
      * @param webappId The ID of the web app the used time is being read for.
      * @param callback Called when the URL has been retrieved.
      */
     @VisibleForTesting
-    public static void getUrl(final Context context, final String webappId,
-            final FetchCallback<String> callback) {
+    public static void getUrl(final String webappId, final FetchCallback<String> callback) {
         new AsyncTask<Void, Void, String>() {
             @Override
             protected final String doInBackground(Void... nothing) {
-                return new WebappDataStorage(context.getApplicationContext(), webappId).getUrl();
+                return new WebappDataStorage(webappId).getUrl();
             }
 
             @Override
@@ -170,23 +163,21 @@
     /**
      * Deletes the data for a web app by clearing all the information inside the SharedPreferences
      * file. This does NOT delete the file itself but the file is left empty.
-     * @param context  The context to read the SharedPreferences file.
      * @param webappId The ID of the web app being deleted.
      */
-    static void deleteDataForWebapp(final Context context, final String webappId) {
+    static void deleteDataForWebapp(final String webappId) {
         assert !ThreadUtils.runningOnUiThread();
-        openSharedPreferences(context, webappId).edit().clear().apply();
+        openSharedPreferences(webappId).edit().clear().apply();
     }
 
     /**
      * Deletes the URL and scope, and sets all timestamps to 0 in SharedPreferences.
      * This does not remove the stored splash screen image (if any) for the app.
-     * @param context  The context to read the SharedPreferences file.
      * @param webappId The ID of the web app for which history is being cleared.
      */
-    static void clearHistory(final Context context, final String webappId) {
+    static void clearHistory(final String webappId) {
         assert !ThreadUtils.runningOnUiThread();
-        SharedPreferences.Editor editor = openSharedPreferences(context, webappId).edit();
+        SharedPreferences.Editor editor = openSharedPreferences(webappId).edit();
 
         // The last used time is set to 0 to ensure that a valid value is always present.
         // If the web app is not launched prior to the next cleanup, then its remaining data will be
@@ -216,14 +207,14 @@
         sFactory = factory;
     }
 
-    private static SharedPreferences openSharedPreferences(Context context, String webappId) {
-        return context.getApplicationContext().getSharedPreferences(
+    private static SharedPreferences openSharedPreferences(String webappId) {
+        return ContextUtils.getApplicationContext().getSharedPreferences(
                 SHARED_PREFS_FILE_PREFIX + webappId, Context.MODE_PRIVATE);
     }
 
-    protected WebappDataStorage(Context context, String webappId) {
+    protected WebappDataStorage(String webappId) {
         mId = webappId;
-        mPreferences = openSharedPreferences(context, webappId);
+        mPreferences = openSharedPreferences(webappId);
     }
 
     /**
@@ -491,8 +482,8 @@
         /**
          * Generates a WebappDataStorage class for a specified web app.
          */
-        public WebappDataStorage create(final Context context, final String webappId) {
-            return new WebappDataStorage(context, webappId);
+        public WebappDataStorage create(final String webappId) {
+            return new WebappDataStorage(webappId);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
index 52d6628..629aef6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -10,6 +10,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.AsyncTask;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -58,19 +59,18 @@
     }
 
     /**
-     * Registers the existence of a web app, creates the SharedPreference for it, and runs the
+     * Registers the existence of a web app, creates a SharedPreference entry for it, and runs the
      * supplied callback (if not null) on the UI thread with the resulting WebappDataStorage object.
-     * @param context  Context to open the registry with.
      * @param webappId The id of the web app to register.
      * @param callback The callback to run with the WebappDataStorage argument.
      * @return The storage object for the web app.
      */
-    public static void registerWebapp(final Context context, final String webappId,
+    public static void registerWebapp(final String webappId,
             final FetchWebappDataStorageCallback callback) {
         new AsyncTask<Void, Void, WebappDataStorage>() {
             @Override
             protected final WebappDataStorage doInBackground(Void... nothing) {
-                SharedPreferences preferences = openSharedPreferences(context);
+                SharedPreferences preferences = openSharedPreferences();
                 // The set returned by getRegisteredWebappIds must be treated as immutable, so we
                 // make a copy to edit and save.
                 Set<String> webapps = new HashSet<>(getRegisteredWebappIds(preferences));
@@ -82,7 +82,7 @@
                 // Create the WebappDataStorage and update the last used time, so we can guarantee
                 // that a web app which appears in the registry will have a
                 // last used time != WebappDataStorage.LAST_USED_INVALID.
-                WebappDataStorage storage = new WebappDataStorage(context, webappId);
+                WebappDataStorage storage = new WebappDataStorage(webappId);
                 storage.updateLastUsedTime();
                 return storage;
             }
@@ -97,18 +97,17 @@
     /**
      * Runs the callback, supplying the WebappDataStorage object for webappId, or null if the web
      * app has not been registered.
-     * @param context  Context to open the registry with.
      * @param webappId The id of the web app to register.
      * @return The storage object for the web app, or null if webappId is not registered.
      */
-    public static void getWebappDataStorage(final Context context, final String webappId,
+    public static void getWebappDataStorage(final String webappId,
             final FetchWebappDataStorageCallback callback) {
         new AsyncTask<Void, Void, WebappDataStorage>() {
             @Override
             protected final WebappDataStorage doInBackground(Void... nothing) {
-                SharedPreferences preferences = openSharedPreferences(context);
+                SharedPreferences preferences = openSharedPreferences();
                 if (getRegisteredWebappIds(preferences).contains(webappId)) {
-                    WebappDataStorage storage = WebappDataStorage.open(context, webappId);
+                    WebappDataStorage storage = WebappDataStorage.open(webappId);
                     return storage;
                 }
                 return null;
@@ -126,20 +125,19 @@
      * Runs the callback, supplying the WebappDataStorage object whose scope most closely matches
      * the provided URL, or null if a matching web app cannot be found. The most closely matching
      * scope is the longest scope which has the same prefix as the URL to open.
-     * @param context  Context to open the registry with.
      * @param url      The URL to search for.
      * @return The storage object for the web app, or null if webappId is not registered.
      */
-    public static void getWebappDataStorageForUrl(final Context context, final String url,
+    public static void getWebappDataStorageForUrl(final String url,
             final FetchWebappDataStorageCallback callback) {
         new AsyncTask<Void, Void, WebappDataStorage>() {
             @Override
             protected final WebappDataStorage doInBackground(Void... nothing) {
-                SharedPreferences preferences = openSharedPreferences(context);
+                SharedPreferences preferences = openSharedPreferences();
                 WebappDataStorage bestMatch = null;
                 int largestOverlap = 0;
                 for (String id : getRegisteredWebappIds(preferences)) {
-                    WebappDataStorage storage = WebappDataStorage.open(context, id);
+                    WebappDataStorage storage = WebappDataStorage.open(id);
                     String scope = storage.getScope();
                     if (url.startsWith(scope) && scope.length() > largestOverlap) {
                         bestMatch = storage;
@@ -158,15 +156,14 @@
 
     /**
      * Asynchronously retrieves the list of web app IDs which this registry is aware of.
-     * @param context  Context to open the registry with.
      * @param callback Called when the set has been retrieved. The set may be empty.
      */
     @VisibleForTesting
-    public static void getRegisteredWebappIds(final Context context, final FetchCallback callback) {
+    public static void getRegisteredWebappIds(final FetchCallback callback) {
         new AsyncTask<Void, Void, Set<String>>() {
             @Override
             protected final Set<String> doInBackground(Void... nothing) {
-                return getRegisteredWebappIds(openSharedPreferences(context));
+                return getRegisteredWebappIds(openSharedPreferences());
             }
 
             @Override
@@ -183,23 +180,22 @@
      * used time set to 0 by the user clearing their history. Cleanup is run, at most, once a month.
      * 2. Deletes the data for all WebAPKs that have been uninstalled in the last month.
      *
-     * @param context     Context to open the registry with.
      * @param currentTime The current time which will be checked to decide if the task should be run
      *                    and if a web app should be cleaned up.
      */
-    static void unregisterOldWebapps(final Context context, final long currentTime) {
+    static void unregisterOldWebapps(final long currentTime) {
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected final Void doInBackground(Void... nothing) {
-                SharedPreferences preferences = openSharedPreferences(context);
+                SharedPreferences preferences = openSharedPreferences();
                 long lastCleanup = preferences.getLong(KEY_LAST_CLEANUP, 0);
                 if ((currentTime - lastCleanup) < FULL_CLEANUP_DURATION) return null;
 
                 Set<String> currentWebapps = getRegisteredWebappIds(preferences);
                 Set<String> retainedWebapps = new HashSet<>(currentWebapps);
-                PackageManager pm = context.getPackageManager();
+                PackageManager pm = ContextUtils.getApplicationContext().getPackageManager();
                 for (String id : currentWebapps) {
-                    WebappDataStorage storage = new WebappDataStorage(context, id);
+                    WebappDataStorage storage = new WebappDataStorage(id);
                     String webApkPackage = storage.getWebApkPackageName();
                     if (webApkPackage != null) {
                         if (isWebApkInstalled(pm, webApkPackage)) continue;
@@ -207,7 +203,7 @@
                         long lastUsed = storage.getLastUsedTime();
                         if ((currentTime - lastUsed) < WEBAPP_UNOPENED_CLEANUP_DURATION) continue;
                     }
-                    WebappDataStorage.deleteDataForWebapp(context, id);
+                    WebappDataStorage.deleteDataForWebapp(id);
                     retainedWebapps.remove(id);
                 }
 
@@ -238,18 +234,17 @@
      * tracking those web apps.
      */
     @VisibleForTesting
-    static void unregisterWebappsForUrls(
-            final Context context, final UrlFilter urlFilter, final Runnable callback) {
+    static void unregisterWebappsForUrls(final UrlFilter urlFilter, final Runnable callback) {
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected final Void doInBackground(Void... nothing) {
-                SharedPreferences preferences = openSharedPreferences(context);
+                SharedPreferences preferences = openSharedPreferences();
                 Set<String> registeredWebapps =
                         new HashSet<>(getRegisteredWebappIds(preferences));
                 Set<String> webappsToUnregister = new HashSet<>();
                 for (String id : registeredWebapps) {
-                    if (urlFilter.matchesUrl(WebappDataStorage.open(context, id).getUrl())) {
-                        WebappDataStorage.deleteDataForWebapp(context, id);
+                    if (urlFilter.matchesUrl(WebappDataStorage.open(id).getUrl())) {
+                        WebappDataStorage.deleteDataForWebapp(id);
                         webappsToUnregister.add(id);
                     }
                 }
@@ -277,8 +272,8 @@
 
     @CalledByNative
     static void unregisterWebappsForUrls(
-            Context context, final UrlFilterBridge urlFilter, final long callbackPointer) {
-        unregisterWebappsForUrls(context, urlFilter, new Runnable() {
+            final UrlFilterBridge urlFilter, final long callbackPointer) {
+        unregisterWebappsForUrls(urlFilter, new Runnable() {
             @Override
             public void run() {
                 urlFilter.destroy();
@@ -292,15 +287,14 @@
      * matches |urlFilter|.
      */
     @VisibleForTesting
-    static void clearWebappHistoryForUrls(
-            final Context context, final UrlFilter urlFilter, final Runnable callback) {
+    static void clearWebappHistoryForUrls(final UrlFilter urlFilter, final Runnable callback) {
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected final Void doInBackground(Void... nothing) {
-                SharedPreferences preferences = openSharedPreferences(context);
+                SharedPreferences preferences = openSharedPreferences();
                 for (String id : getRegisteredWebappIds(preferences)) {
-                    if (urlFilter.matchesUrl(WebappDataStorage.open(context, id).getUrl())) {
-                        WebappDataStorage.clearHistory(context, id);
+                    if (urlFilter.matchesUrl(WebappDataStorage.open(id).getUrl())) {
+                        WebappDataStorage.clearHistory(id);
                     }
                 }
                 return null;
@@ -316,8 +310,8 @@
 
     @CalledByNative
     static void clearWebappHistoryForUrls(
-            Context context, final UrlFilterBridge urlFilter, final long callbackPointer) {
-        clearWebappHistoryForUrls(context, urlFilter, new Runnable() {
+            final UrlFilterBridge urlFilter, final long callbackPointer) {
+        clearWebappHistoryForUrls(urlFilter, new Runnable() {
             @Override
             public void run() {
                 urlFilter.destroy();
@@ -326,8 +320,9 @@
         });
     }
 
-    private static SharedPreferences openSharedPreferences(Context context) {
-        return context.getSharedPreferences(REGISTRY_FILE_NAME, Context.MODE_PRIVATE);
+    private static SharedPreferences openSharedPreferences() {
+        return ContextUtils.getApplicationContext().getSharedPreferences(
+                REGISTRY_FILE_NAME, Context.MODE_PRIVATE);
     }
 
     private static Set<String> getRegisteredWebappIds(SharedPreferences preferences) {
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 6afdb03..415bb71 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2589,10 +2589,7 @@
         <ph name="ITEM_NAME">%1$s<ex>item_name</ex></ph> (<ph name="ITEM_ID">%2$s<ex>item id</ex></ph>)
       </message>
 
-      <message name="IDS_INSTANT_APPS_INFO_BAR_LABEL" desc="A sub-heading describing the item as an Instant App">
-        Instant app
-      </message>
-      <message name="IDS_INSTANT_APPS_OPEN_IN_APP" desc="Button label for the user action that will open an Instant App. [CHAR LIMIT=20]">
+      <message name="IDS_INSTANT_APPS_OPEN_IN_APP" desc="Button label for the user action that will open an Instant App.">
         Open app
       </message>
     </messages>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
index 7c3116b..605d76da 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -131,14 +131,14 @@
         public Bitmap mSplashImage;
 
         @Override
-        public WebappDataStorage create(final Context context, final String webappId) {
-            return new WebappDataStorageWrapper(context, webappId);
+        public WebappDataStorage create(final String webappId) {
+            return new WebappDataStorageWrapper(webappId);
         }
 
         private class WebappDataStorageWrapper extends WebappDataStorage {
 
-            public WebappDataStorageWrapper(Context context, String webappId) {
-                super(context, webappId);
+            public WebappDataStorageWrapper(String webappId) {
+                super(webappId);
             }
 
             @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
index 8c0bb08..434c989 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/BrowsingDataRemoverIntegrationTest.java
@@ -70,7 +70,7 @@
         final Intent shortcutIntent = shortcutIntentTask.execute().get();
 
         WebappRegistry.registerWebapp(
-                getActivity(), webappId, new WebappRegistry.FetchWebappDataStorageCallback() {
+                webappId, new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         storage.updateFromShortcutIntent(shortcutIntent);
@@ -100,7 +100,7 @@
         }
 
         // Wait for the registration to finish.
-        WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() {
+        WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() {
             @Override
             public void onWebappIdsRetrieved(Set<String> ids) {
                 assertEquals(apps.keySet(), ids);
@@ -131,7 +131,7 @@
         CriteriaHelper.pollUiThread(new CallbackCriteria());
 
         // The last two webapps should have been unregistered.
-        WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() {
+        WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() {
             @Override
             public void onWebappIdsRetrieved(Set<String> ids) {
                 assertEquals(new HashSet<String>(Arrays.asList("webapp1")), ids);
@@ -158,7 +158,7 @@
         CriteriaHelper.pollUiThread(new CallbackCriteria());
 
         // All webapps should have been unregistered.
-        WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() {
+        WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() {
             @Override
             public void onWebappIdsRetrieved(Set<String> ids) {
                 assertTrue(ids.isEmpty());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
index 065dbcc..e6b92c2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesTest.java
@@ -104,8 +104,8 @@
      */
     @MediumTest
     public void testClearingSiteDataClearsWebapps() throws Exception {
-        WebappRegistry.registerWebapp(getActivity(), "first", null);
-        WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() {
+        WebappRegistry.registerWebapp("first", null);
+        WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() {
             @Override
             public void onWebappIdsRetrieved(Set<String> ids) {
                 assertEquals(new HashSet<String>(Arrays.asList("first")), ids);
@@ -131,7 +131,7 @@
         });
         waitForProgressToComplete(preferences);
 
-        WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() {
+        WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() {
             @Override
             public void onWebappIdsRetrieved(Set<String> ids) {
                 assertTrue(ids.isEmpty());
@@ -155,18 +155,16 @@
         };
         final Intent shortcutIntent = shortcutIntentTask.execute().get();
 
-        WebappRegistry.registerWebapp(getActivity(), "first",
-                new WebappRegistry.FetchWebappDataStorageCallback() {
-                    @Override
-                    public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
-                        storage.updateFromShortcutIntent(shortcutIntent);
-                        mCallbackCalled = true;
-                    }
-                }
-        );
+        WebappRegistry.registerWebapp("first", new WebappRegistry.FetchWebappDataStorageCallback() {
+            @Override
+            public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
+                storage.updateFromShortcutIntent(shortcutIntent);
+                mCallbackCalled = true;
+            }
+        });
         CriteriaHelper.pollUiThread(new CallbackCriteria());
 
-        WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() {
+        WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() {
             @Override
             public void onWebappIdsRetrieved(Set<String> ids) {
                 assertEquals(new HashSet<String>(Arrays.asList("first")), ids);
@@ -193,7 +191,7 @@
         waitForProgressToComplete(preferences);
 
         // The web app should still exist in the registry.
-        WebappRegistry.getRegisteredWebappIds(getActivity(), new WebappRegistry.FetchCallback() {
+        WebappRegistry.getRegisteredWebappIds(new WebappRegistry.FetchCallback() {
             @Override
             public void onWebappIdsRetrieved(Set<String> ids) {
                 assertEquals(new HashSet<String>(Arrays.asList("first")), ids);
@@ -203,39 +201,33 @@
         CriteriaHelper.pollUiThread(new CallbackCriteria());
 
         // URL and scope should be empty.
-        WebappDataStorage.getScope(getActivity(), "first",
-                new WebappDataStorage.FetchCallback<String>() {
-                    @Override
-                    public void onDataRetrieved(String readObject) {
-                        assertEquals(readObject, "");
-                        mCallbackCalled = true;
-                    }
-                }
-        );
+        WebappDataStorage.getScope("first", new WebappDataStorage.FetchCallback<String>() {
+            @Override
+            public void onDataRetrieved(String readObject) {
+                assertEquals(readObject, "");
+                mCallbackCalled = true;
+            }
+        });
         CriteriaHelper.pollUiThread(new CallbackCriteria());
 
-        WebappDataStorage.getUrl(getActivity(), "first",
-                new WebappDataStorage.FetchCallback<String>() {
-                    @Override
-                    public void onDataRetrieved(String readObject) {
-                        assertEquals(readObject, "");
-                        mCallbackCalled = true;
-                    }
-                }
-        );
+        WebappDataStorage.getUrl("first", new WebappDataStorage.FetchCallback<String>() {
+            @Override
+            public void onDataRetrieved(String readObject) {
+                assertEquals(readObject, "");
+                mCallbackCalled = true;
+            }
+        });
         CriteriaHelper.pollUiThread(new CallbackCriteria());
 
         // The last used time should be 0.
-        WebappDataStorage.getLastUsedTime(getActivity(), "first",
-                new WebappDataStorage.FetchCallback<Long>() {
-                    @Override
-                    public void onDataRetrieved(Long readObject) {
-                        long lastUsed = readObject;
-                        assertEquals(lastUsed, 0);
-                        mCallbackCalled = true;
-                    }
-                }
-        );
+        WebappDataStorage.getLastUsedTime("first", new WebappDataStorage.FetchCallback<Long>() {
+            @Override
+            public void onDataRetrieved(Long readObject) {
+                long lastUsed = readObject;
+                assertEquals(lastUsed, 0);
+                mCallbackCalled = true;
+            }
+        });
         CriteriaHelper.pollUiThread(new CallbackCriteria());
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
index cf7ccd1..01aa9621 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenManagerTest.java
@@ -99,14 +99,14 @@
         public Bitmap mSplashImage;
 
         @Override
-        public WebappDataStorage create(final Context context, final String webappId) {
-            return new WebappDataStorageWrapper(context, webappId);
+        public WebappDataStorage create(final String webappId) {
+            return new WebappDataStorageWrapper(webappId);
         }
 
         private class WebappDataStorageWrapper extends WebappDataStorage {
 
-            public WebappDataStorageWrapper(Context context, String webappId) {
-                super(context, webappId);
+            public WebappDataStorageWrapper(String webappId) {
+                super(webappId);
             }
 
             @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java
index 278490ca..ec1f26a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappActivityTestBase.java
@@ -95,14 +95,13 @@
         // Register the webapp so when the data storage is opened, the test doesn't crash. There is
         // no race condition with the retrieval as AsyncTasks are run sequentially on the background
         // thread.
-        WebappRegistry.registerWebapp(getInstrumentation().getTargetContext(), WEBAPP_ID,
-                new WebappRegistry.FetchWebappDataStorageCallback() {
+        WebappRegistry.registerWebapp(
+                WEBAPP_ID, new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         storage.updateFromShortcutIntent(createIntent());
                     }
-                }
-        );
+                });
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
index 74696ef..c29dab6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappModeTest.java
@@ -97,24 +97,22 @@
         // Register the webapps so when the data storage is opened, the test doesn't crash. There is
         // no race condition with the retrieval as AsyncTasks are run sequentially on the background
         // thread.
-        WebappRegistry.registerWebapp(getInstrumentation().getTargetContext(), WEBAPP_1_ID,
-                new WebappRegistry.FetchWebappDataStorageCallback() {
+        WebappRegistry.registerWebapp(
+                WEBAPP_1_ID, new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         storage.updateFromShortcutIntent(createIntent(
                                 WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true));
                     }
-                }
-        );
-        WebappRegistry.registerWebapp(getInstrumentation().getTargetContext(), WEBAPP_2_ID,
-                new WebappRegistry.FetchWebappDataStorageCallback() {
+                });
+        WebappRegistry.registerWebapp(
+                WEBAPP_2_ID, new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         storage.updateFromShortcutIntent(createIntent(
                                 WEBAPP_1_ID, WEBAPP_1_URL, WEBAPP_1_TITLE, WEBAPP_ICON, true));
                     }
-                }
-        );
+                });
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java
index a9128e5..b549b7b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenIconTest.java
@@ -31,10 +31,8 @@
 
     @Override
     protected void setUp() throws Exception {
-        WebappDataStorage.open(getInstrumentation().getTargetContext(), WEBAPP_ID)
-                .updateSplashScreenImageForTests(TEST_SPLASH_ICON);
-
         super.setUp();
+        WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImageForTests(TEST_SPLASH_ICON);
         startWebappActivity();
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
index 6951ff9..1d2271e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappSplashScreenTest.java
@@ -237,7 +237,7 @@
                 R.dimen.webapp_splash_image_size_threshold);
         int bitmapSize = thresholdSize + 1;
         Bitmap splashBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888);
-        WebappDataStorage.open(context, WEBAPP_ID).updateSplashScreenImage(splashBitmap);
+        WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImage(splashBitmap);
 
         startWebappActivity(createIntent());
         ViewGroup splashScreen = waitUntilSplashScreenAppears();
@@ -265,7 +265,7 @@
         int bitmapSize = context.getResources().getDimensionPixelSize(
                 R.dimen.webapp_splash_image_size_minimum);
         Bitmap splashBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888);
-        WebappDataStorage.open(context, WEBAPP_ID).updateSplashScreenImage(splashBitmap);
+        WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImage(splashBitmap);
 
         startWebappActivity(createIntent());
         ViewGroup splashScreen = waitUntilSplashScreenAppears();
@@ -292,7 +292,7 @@
         int bitmapSize = context.getResources().getDimensionPixelSize(
                 R.dimen.webapp_splash_image_size_minimum) - 1;
         Bitmap splashBitmap = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888);
-        WebappDataStorage.open(context, WEBAPP_ID).updateSplashScreenImage(splashBitmap);
+        WebappDataStorage.open(WEBAPP_ID).updateSplashScreenImage(splashBitmap);
 
         Intent intent = createIntent();
         intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_GENERATED, true);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
index 81e01bf..b4a6894 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -13,11 +13,13 @@
 import android.graphics.Bitmap;
 import android.os.AsyncTask;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.blink_public.platform.WebDisplayMode;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.testing.local.BackgroundShadowAsyncTask;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,8 +73,9 @@
 
     @Before
     public void setUp() throws Exception {
-        mSharedPreferences = RuntimeEnvironment.application
-                .getSharedPreferences("webapp_test", Context.MODE_PRIVATE);
+        ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
+        mSharedPreferences = ContextUtils.getApplicationContext().getSharedPreferences(
+                "webapp_test", Context.MODE_PRIVATE);
 
         // Set the last_used as if the web app had been registered by WebappRegistry.
         mSharedPreferences.edit().putLong("last_used", 0).apply();
@@ -80,6 +83,11 @@
         mCallbackCalled = false;
     }
 
+    @After
+    public void tearDown() {
+        mSharedPreferences.edit().clear().apply();
+    }
+
     @Test
     @Feature({"Webapp"})
     public void testBackwardCompat() {
@@ -105,8 +113,7 @@
     public void testLastUsedRetrieval() throws Exception {
         mSharedPreferences.edit().putLong(WebappDataStorage.KEY_LAST_USED, 100L).apply();
 
-        WebappDataStorage.getLastUsedTime(RuntimeEnvironment.application, "test",
-                new FetchCallback<Long>(new Long(100L)));
+        WebappDataStorage.getLastUsedTime("test", new FetchCallback<Long>(new Long(100L)));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -121,7 +128,7 @@
                 .putString(WebappDataStorage.KEY_SPLASH_ICON,
                         ShortcutHelper.encodeBitmapAsString(expected))
                 .commit();
-        WebappDataStorage.open(RuntimeEnvironment.application, "test")
+        WebappDataStorage.open("test")
                 .getSplashScreenImage(new WebappDataStorage.FetchCallback<Bitmap>() {
                     @Override
                     public void onDataRetrieved(Bitmap actual) {
@@ -143,8 +150,7 @@
     @Feature({"Webapp"})
     public void testSplashImageUpdate() throws Exception {
         final Bitmap expectedImage = createBitmap();
-        WebappDataStorage.open(RuntimeEnvironment.application, "test")
-                .updateSplashScreenImage(expectedImage);
+        WebappDataStorage.open("test").updateSplashScreenImage(expectedImage);
         BackgroundShadowAsyncTask.runBackgroundTasks();
 
         assertEquals(ShortcutHelper.encodeBitmapAsString(expectedImage),
@@ -157,8 +163,7 @@
         final String scope = "http://drive.google.com";
         mSharedPreferences.edit().putString(WebappDataStorage.KEY_SCOPE, scope).apply();
 
-        WebappDataStorage.getScope(RuntimeEnvironment.application, "test",
-                new FetchCallback<String>(scope));
+        WebappDataStorage.getScope("test", new FetchCallback<String>(scope));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -171,8 +176,7 @@
         final String url = "https://www.google.com";
         mSharedPreferences.edit().putString(WebappDataStorage.KEY_URL, url).apply();
 
-        WebappDataStorage.getUrl(RuntimeEnvironment.application, "test",
-                new FetchCallback<String>(url));
+        WebappDataStorage.getUrl("test", new FetchCallback<String>(url));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -186,7 +190,7 @@
         WebappDataStorage.setClockForTests(clock);
 
         // Opening a data storage doesn't count as a launch.
-        WebappDataStorage storage = WebappDataStorage.open(RuntimeEnvironment.application, "test");
+        WebappDataStorage storage = WebappDataStorage.open("test");
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(!storage.wasLaunchedRecently());
@@ -257,7 +261,7 @@
         };
         Intent shortcutIntent = shortcutIntentTask.execute().get();
 
-        WebappDataStorage storage = WebappDataStorage.open(RuntimeEnvironment.application, "test");
+        WebappDataStorage storage = WebappDataStorage.open("test");
         storage.updateFromShortcutIntent(shortcutIntent);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
index 65e175c5..7be71cc 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
@@ -13,11 +13,13 @@
 import android.os.AsyncTask;
 import android.text.TextUtils;
 
+import org.chromium.base.ContextUtils;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.browsing_data.UrlFilters;
 import org.chromium.testing.local.BackgroundShadowAsyncTask;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -136,13 +138,19 @@
 
     @Before
     public void setUp() throws Exception {
-        mSharedPreferences = RuntimeEnvironment.application
-                .getSharedPreferences(REGISTRY_FILE_NAME, Context.MODE_PRIVATE);
+        ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
+        mSharedPreferences = ContextUtils.getApplicationContext().getSharedPreferences(
+                REGISTRY_FILE_NAME, Context.MODE_PRIVATE);
         mSharedPreferences.edit().putLong(KEY_LAST_CLEANUP, INITIAL_TIME).commit();
 
         mCallbackCalled = false;
     }
 
+    @After
+    public void tearDown() {
+        mSharedPreferences.edit().clear().apply();
+    }
+
     @Test
     @Feature({"Webapp"})
     public void testBackwardCompatibility() {
@@ -154,7 +162,7 @@
     @Test
     @Feature({"Webapp"})
     public void testWebappRegistrationAddsToSharedPrefs() throws Exception {
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "test", null);
+        WebappRegistry.registerWebapp("test", null);
 
         BackgroundShadowAsyncTask.runBackgroundTasks();
 
@@ -167,12 +175,12 @@
     @Test
     @Feature({"Webapp"})
     public void testWebappRegistrationUpdatesLastUsed() throws Exception {
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "test", null);
+        WebappRegistry.registerWebapp("test", null);
 
         BackgroundShadowAsyncTask.runBackgroundTasks();
         long after = System.currentTimeMillis();
 
-        SharedPreferences webAppPrefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "test", Context.MODE_PRIVATE);
         long actual = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED,
                 WebappDataStorage.LAST_USED_INVALID);
@@ -185,7 +193,7 @@
         final Set<String> expected = addWebappsToRegistry("first", "second");
 
         FetchCallback callback = new FetchCallback(expected);
-        WebappRegistry.getRegisteredWebappIds(RuntimeEnvironment.application, callback);
+        WebappRegistry.getRegisteredWebappIds(callback);
 
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
@@ -199,14 +207,14 @@
         final Set<String> expected = addWebappsToRegistry("first");
 
         FetchCallback callback = new FetchCallback(expected);
-        WebappRegistry.getRegisteredWebappIds(RuntimeEnvironment.application, callback);
+        WebappRegistry.getRegisteredWebappIds(callback);
 
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
         assertTrue(callback.getCallbackCalled());
 
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "second", null);
+        WebappRegistry.registerWebapp("second", null);
 
         BackgroundShadowAsyncTask.runBackgroundTasks();
 
@@ -216,7 +224,7 @@
         secondExpected.add("second");
 
         callback = new FetchCallback(secondExpected);
-        WebappRegistry.getRegisteredWebappIds(RuntimeEnvironment.application, callback);
+        WebappRegistry.getRegisteredWebappIds(callback);
 
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
@@ -228,8 +236,7 @@
     @Feature({"Webapp"})
     public void testUnregisterRunsCallback() throws Exception {
         CallbackRunner callback = new CallbackRunner();
-        WebappRegistry.unregisterWebappsForUrls(
-                RuntimeEnvironment.application, new UrlFilters.AllUrls(), callback);
+        WebappRegistry.unregisterWebappsForUrls(new UrlFilters.AllUrls(), callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -245,8 +252,8 @@
         apps.put("webapp3", "https://www.chrome.com");
 
         for (Map.Entry<String, String> app : apps.entrySet()) {
-            WebappRegistry.registerWebapp(RuntimeEnvironment.application, app.getKey(),
-                    new FetchStorageCallback(createShortcutIntent(app.getValue())));
+            WebappRegistry.registerWebapp(
+                    app.getKey(), new FetchStorageCallback(createShortcutIntent(app.getValue())));
         }
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
@@ -254,7 +261,6 @@
         // Partial deletion.
         CallbackRunner callback = new CallbackRunner();
         WebappRegistry.unregisterWebappsForUrls(
-                RuntimeEnvironment.application,
                 new UrlFilters.OneUrl("http://example.com/index.html"), callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
@@ -269,8 +275,7 @@
 
         // Full deletion.
         callback = new CallbackRunner();
-        WebappRegistry.unregisterWebappsForUrls(
-                RuntimeEnvironment.application, new UrlFilters.AllUrls(), callback);
+        WebappRegistry.unregisterWebappsForUrls(new UrlFilters.AllUrls(), callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -287,37 +292,41 @@
         apps.put("webapp3", "https://www.chrome.com");
 
         for (Map.Entry<String, String> app : apps.entrySet()) {
-            WebappRegistry.registerWebapp(RuntimeEnvironment.application, app.getKey(),
-                    new FetchStorageCallback(createShortcutIntent(app.getValue())));
+            WebappRegistry.registerWebapp(
+                    app.getKey(), new FetchStorageCallback(createShortcutIntent(app.getValue())));
         }
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
         for (String appName : apps.keySet()) {
-            SharedPreferences webAppPrefs = RuntimeEnvironment.application.getSharedPreferences(
-                    WebappDataStorage.SHARED_PREFS_FILE_PREFIX + appName, Context.MODE_PRIVATE);
+            SharedPreferences webAppPrefs =
+                    ContextUtils.getApplicationContext().getSharedPreferences(
+                            WebappDataStorage.SHARED_PREFS_FILE_PREFIX + appName,
+                            Context.MODE_PRIVATE);
             webAppPrefs.edit().putLong(WebappDataStorage.KEY_LAST_USED, 100L).apply();
         }
 
         // Partial deletion.
         WebappRegistry.unregisterWebappsForUrls(
-                RuntimeEnvironment.application,
                 new UrlFilters.OneUrl("http://example.com/index.html"), null);
 
         BackgroundShadowAsyncTask.runBackgroundTasks();
         for (String appName : apps.keySet()) {
-            SharedPreferences webAppPrefs = RuntimeEnvironment.application.getSharedPreferences(
-                    WebappDataStorage.SHARED_PREFS_FILE_PREFIX + appName, Context.MODE_PRIVATE);
+            SharedPreferences webAppPrefs =
+                    ContextUtils.getApplicationContext().getSharedPreferences(
+                            WebappDataStorage.SHARED_PREFS_FILE_PREFIX + appName,
+                            Context.MODE_PRIVATE);
             assertEquals(TextUtils.equals(appName, "webapp1"), webAppPrefs.getAll().isEmpty());
         }
 
         // Full deletion.
-        WebappRegistry.unregisterWebappsForUrls(
-                RuntimeEnvironment.application, new UrlFilters.AllUrls(), null);
+        WebappRegistry.unregisterWebappsForUrls(new UrlFilters.AllUrls(), null);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         for (String appName : apps.keySet()) {
-            SharedPreferences webAppPrefs = RuntimeEnvironment.application.getSharedPreferences(
-                    WebappDataStorage.SHARED_PREFS_FILE_PREFIX + appName, Context.MODE_PRIVATE);
+            SharedPreferences webAppPrefs =
+                    ContextUtils.getApplicationContext().getSharedPreferences(
+                            WebappDataStorage.SHARED_PREFS_FILE_PREFIX + appName,
+                            Context.MODE_PRIVATE);
             assertTrue(webAppPrefs.getAll().isEmpty());
         }
     }
@@ -329,11 +338,11 @@
         long currentTime = INITIAL_TIME + WebappRegistry.FULL_CLEANUP_DURATION - 1;
 
         addWebappsToRegistry("oldWebapp");
-        SharedPreferences webAppPrefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "oldWebapp", Context.MODE_PRIVATE);
         webAppPrefs.edit().putLong(WebappDataStorage.KEY_LAST_USED, Long.MIN_VALUE).apply();
 
-        WebappRegistry.unregisterOldWebapps(RuntimeEnvironment.application, currentTime);
+        WebappRegistry.unregisterOldWebapps(currentTime);
         BackgroundShadowAsyncTask.runBackgroundTasks();
 
         Set<String> actual = mSharedPreferences.getStringSet(
@@ -357,7 +366,7 @@
 
         // Put the last used time just inside the no-cleanup window.
         addWebappsToRegistry("recentWebapp");
-        SharedPreferences webAppPrefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "recentWebapp", Context.MODE_PRIVATE);
         long lastUsed = currentTime - WebappRegistry.WEBAPP_UNOPENED_CLEANUP_DURATION + 1;
         webAppPrefs.edit().putLong(WebappDataStorage.KEY_LAST_USED, lastUsed).apply();
@@ -365,7 +374,7 @@
         // Because the time is just inside the window, there should be a cleanup but the web app
         // should not be deleted as it was used recently. The last cleanup time should also be
         // set to the current time.
-        WebappRegistry.unregisterOldWebapps(RuntimeEnvironment.application, currentTime);
+        WebappRegistry.unregisterOldWebapps(currentTime);
         BackgroundShadowAsyncTask.runBackgroundTasks();
 
         Set<String> actual = mSharedPreferences.getStringSet(
@@ -388,14 +397,14 @@
 
         // Put the last used time just outside the no-cleanup window.
         addWebappsToRegistry("oldWebapp");
-        SharedPreferences webAppPrefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "oldWebapp", Context.MODE_PRIVATE);
         long lastUsed = currentTime - WebappRegistry.WEBAPP_UNOPENED_CLEANUP_DURATION;
         webAppPrefs.edit().putLong(WebappDataStorage.KEY_LAST_USED, lastUsed).apply();
 
         // Because the time is just inside the window, there should be a cleanup of old web apps and
         // the last cleaned up time should be set to the current time.
-        WebappRegistry.unregisterOldWebapps(RuntimeEnvironment.application, currentTime);
+        WebappRegistry.unregisterOldWebapps(currentTime);
         BackgroundShadowAsyncTask.runBackgroundTasks();
 
         Set<String> actual = mSharedPreferences.getStringSet(
@@ -420,14 +429,14 @@
 
         FetchStorageCallback storageCallback1 = new FetchStorageCallback(
                 createWebApkIntent(webappId1, webApkPackage1));
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, webappId1, storageCallback1);
+        WebappRegistry.registerWebapp(webappId1, storageCallback1);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(storageCallback1.getCallbackCalled());
 
         FetchStorageCallback storageCallback2 = new FetchStorageCallback(
                 createWebApkIntent(webappId1, webApkPackage2));
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, webappId2, storageCallback2);
+        WebappRegistry.registerWebapp(webappId2, storageCallback2);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(storageCallback2.getCallbackCalled());
@@ -444,7 +453,7 @@
         // Because the time is just inside the window, there should be a cleanup of
         // uninstalled WebAPKs and the last cleaned up time should be set to the
         // current time.
-        WebappRegistry.unregisterOldWebapps(RuntimeEnvironment.application, currentTime);
+        WebappRegistry.unregisterOldWebapps(currentTime);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -467,15 +476,14 @@
 
         FetchStorageCallback storageCallback = new FetchStorageCallback(
                 createWebApkIntent(webappId, webApkPackage));
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, webappId, storageCallback);
+        WebappRegistry.registerWebapp(webappId, storageCallback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(storageCallback.getCallbackCalled());
 
         FetchStorageCallback storageCallback2 = new FetchStorageCallback(
                 createWebApkIntent(uninstalledWebappId, uninstalledWebApkPackage));
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, uninstalledWebappId,
-                storageCallback2);
+        WebappRegistry.registerWebapp(uninstalledWebappId, storageCallback2);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(storageCallback2.getCallbackCalled());
@@ -494,7 +502,7 @@
         // Because the time is just inside the window, there should be a cleanup of
         // uninstalled WebAPKs and the last cleaned up time should be set to the
         // current time.
-        WebappRegistry.unregisterOldWebapps(RuntimeEnvironment.application, currentTime);
+        WebappRegistry.unregisterOldWebapps(currentTime);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -512,8 +520,7 @@
     @Feature({"Webapp"})
     public void testClearWebappHistoryRunsCallback() throws Exception {
         CallbackRunner callback = new CallbackRunner();
-        WebappRegistry.clearWebappHistoryForUrls(
-                RuntimeEnvironment.application, new UrlFilters.AllUrls(), callback);
+        WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -529,20 +536,20 @@
         Intent shortcutIntent2 = createShortcutIntent(webapp2Url);
 
         FetchStorageCallback storageCallback1 = new FetchStorageCallback(shortcutIntent1);
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp1", storageCallback1);
+        WebappRegistry.registerWebapp("webapp1", storageCallback1);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(storageCallback1.getCallbackCalled());
 
         FetchStorageCallback storageCallback2 = new FetchStorageCallback(shortcutIntent2);
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp2", storageCallback2);
+        WebappRegistry.registerWebapp("webapp2", storageCallback2);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(storageCallback2.getCallbackCalled());
 
-        SharedPreferences webapp1Prefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webapp1Prefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp1", Context.MODE_PRIVATE);
-        SharedPreferences webapp2Prefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webapp2Prefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp2", Context.MODE_PRIVATE);
 
         long webapp1OriginalLastUsed = webapp2Prefs.getLong(
@@ -554,8 +561,7 @@
 
         // Clear data for |webapp1Url|.
         CallbackRunner callback = new CallbackRunner();
-        WebappRegistry.clearWebappHistoryForUrls(
-                RuntimeEnvironment.application, new UrlFilters.OneUrl(webapp1Url), callback);
+        WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.OneUrl(webapp1Url), callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
@@ -592,8 +598,7 @@
 
         // Clear data for all urls.
         callback = new CallbackRunner();
-        WebappRegistry.clearWebappHistoryForUrls(
-                RuntimeEnvironment.application, new UrlFilters.AllUrls(), callback);
+        WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
@@ -624,22 +629,20 @@
     @Test
     @Feature({"Webapp"})
     public void testGetAfterClearWebappHistory() throws Exception {
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp", null);
+        WebappRegistry.registerWebapp("webapp", null);
         BackgroundShadowAsyncTask.runBackgroundTasks();
 
-        SharedPreferences webappPrefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webappPrefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp", Context.MODE_PRIVATE);
         CallbackRunner callback = new CallbackRunner();
-        WebappRegistry.clearWebappHistoryForUrls(
-                RuntimeEnvironment.application, new UrlFilters.AllUrls(), callback);
+        WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
 
         // Open the webapp up to set the last used time.
         FetchStorageCallback storageCallback = new FetchStorageCallback(null);
-        WebappRegistry.getWebappDataStorage(
-                RuntimeEnvironment.application, "webapp", storageCallback);
+        WebappRegistry.getWebappDataStorage("webapp", storageCallback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(storageCallback.getCallbackCalled());
@@ -657,12 +660,11 @@
         final String webappUrl = "http://www.google.com";
         final String webappScope = "http://www.google.com/";
         final Intent shortcutIntent = createShortcutIntent(webappUrl);
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp",
-                new FetchStorageCallback(shortcutIntent));
+        WebappRegistry.registerWebapp("webapp", new FetchStorageCallback(shortcutIntent));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
-        SharedPreferences webappPrefs = RuntimeEnvironment.application.getSharedPreferences(
+        SharedPreferences webappPrefs = ContextUtils.getApplicationContext().getSharedPreferences(
                 WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp", Context.MODE_PRIVATE);
 
         // Verify that the URL and scope match the original in the intent.
@@ -673,14 +675,12 @@
                 WebappDataStorage.KEY_SCOPE, WebappDataStorage.URL_INVALID);
         assertEquals(webappScope, actualScope);
 
-        WebappRegistry.clearWebappHistoryForUrls(
-                RuntimeEnvironment.application, new UrlFilters.AllUrls(), new CallbackRunner());
+        WebappRegistry.clearWebappHistoryForUrls(new UrlFilters.AllUrls(), new CallbackRunner());
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
         // Update the webapp from the intent again.
-        WebappRegistry.getWebappDataStorage(RuntimeEnvironment.application, "webapp",
-                new FetchStorageCallback(shortcutIntent));
+        WebappRegistry.getWebappDataStorage("webapp", new FetchStorageCallback(shortcutIntent));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
@@ -718,62 +718,53 @@
         Intent shortcutIntent4 = createShortcutIntent(webapp4Url);
 
         // Register the four web apps.
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp1",
-                new FetchStorageCallback(shortcutIntent1));
+        WebappRegistry.registerWebapp("webapp1", new FetchStorageCallback(shortcutIntent1));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp2",
-                new FetchStorageCallback(shortcutIntent2));
+        WebappRegistry.registerWebapp("webapp2", new FetchStorageCallback(shortcutIntent2));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp3",
-                new FetchStorageCallback(shortcutIntent3));
+        WebappRegistry.registerWebapp("webapp3", new FetchStorageCallback(shortcutIntent3));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
-        WebappRegistry.registerWebapp(RuntimeEnvironment.application, "webapp4",
-                new FetchStorageCallback(shortcutIntent4));
+        WebappRegistry.registerWebapp("webapp4", new FetchStorageCallback(shortcutIntent4));
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
 
         // test1Url should return webapp1.
         FetchStorageByUrlCallback callback = new FetchStorageByUrlCallback(webapp1Url, webapp1Url);
-        WebappRegistry.getWebappDataStorageForUrl(
-                RuntimeEnvironment.application, test1Url, callback);
+        WebappRegistry.getWebappDataStorageForUrl(test1Url, callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
 
         // test2Url should return webapp3.
         callback = new FetchStorageByUrlCallback(webapp3Url, webapp3Scope);
-        WebappRegistry.getWebappDataStorageForUrl(
-                RuntimeEnvironment.application, test2Url, callback);
+        WebappRegistry.getWebappDataStorageForUrl(test2Url, callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
 
         // test3Url should return webapp4.
         callback = new FetchStorageByUrlCallback(webapp4Url, webapp4Scope);
-        WebappRegistry.getWebappDataStorageForUrl(
-                RuntimeEnvironment.application, test3Url, callback);
+        WebappRegistry.getWebappDataStorageForUrl(test3Url, callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
 
         // test4Url should return webapp4.
         callback = new FetchStorageByUrlCallback(webapp4Url, webapp4Scope);
-        WebappRegistry.getWebappDataStorageForUrl(
-                RuntimeEnvironment.application, test4Url, callback);
+        WebappRegistry.getWebappDataStorageForUrl(test4Url, callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
 
         // test5Url should return webapp2.
         callback = new FetchStorageByUrlCallback(webapp2Url, webapp2Url);
-        WebappRegistry.getWebappDataStorageForUrl(
-                RuntimeEnvironment.application, test5Url, callback);
+        WebappRegistry.getWebappDataStorageForUrl(test5Url, callback);
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(callback.getCallbackCalled());
@@ -782,15 +773,14 @@
         // This must use a member variable; local variables must be final or effectively final to be
         // accessible inside an inner class.
         mCallbackCalled = false;
-        WebappRegistry.getWebappDataStorageForUrl(RuntimeEnvironment.application, test6Url,
-                new WebappRegistry.FetchWebappDataStorageCallback() {
+        WebappRegistry.getWebappDataStorageForUrl(
+                test6Url, new WebappRegistry.FetchWebappDataStorageCallback() {
                     @Override
                     public void onWebappDataStorageRetrieved(WebappDataStorage storage) {
                         assertEquals(null, storage);
                         mCallbackCalled = true;
                     }
-                }
-        );
+                });
         BackgroundShadowAsyncTask.runBackgroundTasks();
         ShadowLooper.runUiThreadTasks();
         assertTrue(mCallbackCalled);
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 34d0ddb..bb368cc 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2081,9 +2081,21 @@
     defines += [ "ENABLE_HOTWORDING" ]
   }
 
-  if (is_linux && use_dbus) {
+  if (is_chromeos && use_dbus) {
     deps += [ "//device/media_transfer_protocol" ]
   }
+  if (is_win || is_mac || (is_chromeos && use_dbus)) {
+    sources += [
+      "media_galleries/fileapi/device_media_async_file_util.cc",
+      "media_galleries/fileapi/device_media_async_file_util.h",
+      "media_galleries/fileapi/mtp_device_async_delegate.cc",
+      "media_galleries/fileapi/mtp_device_async_delegate.h",
+      "media_galleries/fileapi/mtp_device_map_service.cc",
+      "media_galleries/fileapi/mtp_device_map_service.h",
+      "media_galleries/fileapi/mtp_file_stream_reader.cc",
+      "media_galleries/fileapi/mtp_file_stream_reader.h",
+    ]
+  }
 
   if (use_udev) {
     deps += [ "//device/udev_linux" ]
@@ -2649,10 +2661,20 @@
       "lifetime/scoped_keep_alive.h",
       "media/webrtc/tab_desktop_media_list.cc",
       "media/webrtc/tab_desktop_media_list.h",
+      "media_galleries/chromeos/mtp_device_delegate_impl_chromeos.cc",
+      "media_galleries/chromeos/mtp_device_delegate_impl_chromeos.h",
+      "media_galleries/chromeos/mtp_device_object_enumerator.cc",
+      "media_galleries/chromeos/mtp_device_object_enumerator.h",
+      "media_galleries/chromeos/mtp_device_task_helper.cc",
+      "media_galleries/chromeos/mtp_device_task_helper.h",
+      "media_galleries/chromeos/mtp_device_task_helper_map_service.cc",
+      "media_galleries/chromeos/mtp_device_task_helper_map_service.h",
+      "media_galleries/chromeos/mtp_read_file_worker.cc",
+      "media_galleries/chromeos/mtp_read_file_worker.h",
+      "media_galleries/chromeos/snapshot_file_details.cc",
+      "media_galleries/chromeos/snapshot_file_details.h",
       "media_galleries/fileapi/av_scanning_file_validator.cc",
       "media_galleries/fileapi/av_scanning_file_validator.h",
-      "media_galleries/fileapi/device_media_async_file_util.cc",
-      "media_galleries/fileapi/device_media_async_file_util.h",
       "media_galleries/fileapi/iapps_finder.h",
       "media_galleries/fileapi/iapps_finder_impl.cc",
       "media_galleries/fileapi/iapps_finder_impl.h",
@@ -2664,12 +2686,6 @@
       "media_galleries/fileapi/media_file_validator_factory.h",
       "media_galleries/fileapi/media_path_filter.cc",
       "media_galleries/fileapi/media_path_filter.h",
-      "media_galleries/fileapi/mtp_device_async_delegate.cc",
-      "media_galleries/fileapi/mtp_device_async_delegate.h",
-      "media_galleries/fileapi/mtp_device_map_service.cc",
-      "media_galleries/fileapi/mtp_device_map_service.h",
-      "media_galleries/fileapi/mtp_file_stream_reader.cc",
-      "media_galleries/fileapi/mtp_file_stream_reader.h",
       "media_galleries/fileapi/native_media_file_util.cc",
       "media_galleries/fileapi/native_media_file_util.h",
       "media_galleries/fileapi/picasa_finder.cc",
@@ -2690,18 +2706,6 @@
       "media_galleries/gallery_watch_manager_observer.h",
       "media_galleries/imported_media_gallery_registry.cc",
       "media_galleries/imported_media_gallery_registry.h",
-      "media_galleries/linux/mtp_device_delegate_impl_linux.cc",
-      "media_galleries/linux/mtp_device_delegate_impl_linux.h",
-      "media_galleries/linux/mtp_device_object_enumerator.cc",
-      "media_galleries/linux/mtp_device_object_enumerator.h",
-      "media_galleries/linux/mtp_device_task_helper.cc",
-      "media_galleries/linux/mtp_device_task_helper.h",
-      "media_galleries/linux/mtp_device_task_helper_map_service.cc",
-      "media_galleries/linux/mtp_device_task_helper_map_service.h",
-      "media_galleries/linux/mtp_read_file_worker.cc",
-      "media_galleries/linux/mtp_read_file_worker.h",
-      "media_galleries/linux/snapshot_file_details.cc",
-      "media_galleries/linux/snapshot_file_details.h",
       "media_galleries/mac/mtp_device_delegate_impl_mac.h",
       "media_galleries/mac/mtp_device_delegate_impl_mac.mm",
       "media_galleries/media_file_system_registry.cc",
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc
index 37df154..ba03aeaf 100644
--- a/chrome/browser/android/webapk/webapk_installer.cc
+++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -52,6 +52,10 @@
 // complete.
 const int kDownloadTimeoutMs = 60000;
 
+const int kWorldReadableFilePermission = base::FILE_PERMISSION_READ_BY_USER |
+                                         base::FILE_PERMISSION_READ_BY_GROUP |
+                                         base::FILE_PERMISSION_READ_BY_OTHERS;
+
 // Returns the scope from |info| if it is specified. Otherwise, returns the
 // default scope.
 GURL GetScope(const ShortcutInfo& info) {
@@ -128,6 +132,38 @@
               kDefaultWebApkServerUrlResponseType);
 }
 
+// Creates a directory depending on the type of the task, and set permissions.
+// It also creates any parent directory along the path if doesn't exist,
+// and sets permissions as well.
+// The previously downloaded APKs are deleted in order to clean up unused cached
+// data.
+base::FilePath CreateSubDirAndSetPermissionsInBackground(
+    const base::StringPiece& output_dir_name,
+    const std::string& package_name) {
+  base::FilePath output_root_dir;
+  base::android::GetCacheDirectory(&output_root_dir);
+  base::FilePath webapk_dir = output_root_dir.AppendASCII("webapks");
+  // Creating different downloaded directory for install/update cases is
+  // to prevent deleting the APK which is still in use when an install and an
+  // update happen at the same time. However, it doesn't help the cases of when
+  // mutiple installs (or multiple updates) happen at the same time.
+  base::FilePath output_dir = webapk_dir.AppendASCII(output_dir_name);
+  int posix_permissions = kWorldReadableFilePermission |
+                          base::FILE_PERMISSION_WRITE_BY_USER |
+                          base::FILE_PERMISSION_EXECUTE_BY_USER |
+                          base::FILE_PERMISSION_EXECUTE_BY_OTHERS;
+  if (base::PathExists(output_dir))
+    base::DeleteFile(output_dir, true);
+
+  // Creates the directory to download and sets permissions.
+  if (!base::CreateDirectory(output_dir) ||
+      !base::SetPosixFilePermissions(webapk_dir, posix_permissions) ||
+      !base::SetPosixFilePermissions(output_dir, posix_permissions))
+    return base::FilePath();
+
+  return output_dir;
+}
+
 }  // anonymous namespace
 
 WebApkInstaller::WebApkInstaller(const ShortcutInfo& shortcut_info,
@@ -348,12 +384,23 @@
 
 void WebApkInstaller::OnGotWebApkDownloadUrl(const GURL& download_url,
                                              const std::string& package_name) {
-  base::FilePath output_dir;
-  base::android::GetCacheDirectory(&output_dir);
   webapk_package_ = package_name;
-  // TODO(pkotwicz): Download WebAPKs into WebAPK-specific subdirectory
-  // directory.
-  // TODO(pkotwicz): Figure out when downloaded WebAPK should be deleted.
+
+  base::PostTaskAndReplyWithResult(
+      GetBackgroundTaskRunner().get(), FROM_HERE,
+      base::Bind(&CreateSubDirAndSetPermissionsInBackground,
+                 task_type_ == WebApkInstaller::INSTALL ? "install" : "update",
+                 package_name),
+      base::Bind(&WebApkInstaller::OnCreatedSubDirAndSetPermissions,
+                 weak_ptr_factory_.GetWeakPtr(), download_url));
+}
+
+void WebApkInstaller::OnCreatedSubDirAndSetPermissions(
+    const GURL& download_url, const base::FilePath& output_dir) {
+  if (output_dir.empty()) {
+    OnFailure();
+    return;
+  }
 
   timer_.Start(
       FROM_HERE, base::TimeDelta::FromMilliseconds(download_timeout_ms_),
@@ -375,10 +422,9 @@
     return;
   }
 
-  int posix_permissions = base::FILE_PERMISSION_READ_BY_USER |
+  int posix_permissions = kWorldReadableFilePermission |
                           base::FILE_PERMISSION_WRITE_BY_USER |
-                          base::FILE_PERMISSION_READ_BY_GROUP |
-                          base::FILE_PERMISSION_READ_BY_OTHERS;
+                          base::FILE_PERMISSION_EXECUTE_BY_USER;
   base::PostTaskAndReplyWithResult(
       GetBackgroundTaskRunner().get(), FROM_HERE,
       base::Bind(&base::SetPosixFilePermissions, file_path, posix_permissions),
diff --git a/chrome/browser/android/webapk/webapk_installer.h b/chrome/browser/android/webapk/webapk_installer.h
index eb24f5b..d30a83a 100644
--- a/chrome/browser/android/webapk/webapk_installer.h
+++ b/chrome/browser/android/webapk/webapk_installer.h
@@ -149,6 +149,11 @@
   void OnGotWebApkDownloadUrl(const GURL& download_url,
                               const std::string& package_name);
 
+  // Called once the sub directory to store the downloaded WebAPK was
+  // created with permissions set properly or if creation failed.
+  void OnCreatedSubDirAndSetPermissions(const GURL& download_url,
+                                        const base::FilePath& file_path);
+
   // Called once the WebAPK has been downloaded. Makes the downloaded WebAPK
   // world readable and installs the WebAPK if the download was successful.
   // |file_path| is the file path that the WebAPK was downloaded to.
diff --git a/chrome/browser/android/webapps/webapp_registry.cc b/chrome/browser/android/webapps/webapp_registry.cc
index 7ce9f96..3b3616b1 100644
--- a/chrome/browser/android/webapps/webapp_registry.cc
+++ b/chrome/browser/android/webapps/webapp_registry.cc
@@ -30,9 +30,8 @@
   // back OnWebappsUnregistered().
   UrlFilterBridge* filter_bridge = new UrlFilterBridge(url_filter);
 
-  Java_WebappRegistry_unregisterWebappsForUrls(
-      env, base::android::GetApplicationContext(), filter_bridge->j_bridge(),
-      callback_pointer);
+  Java_WebappRegistry_unregisterWebappsForUrls(env, filter_bridge->j_bridge(),
+                                               callback_pointer);
 }
 
 void WebappRegistry::ClearWebappHistoryForUrls(
@@ -46,9 +45,8 @@
   // back OnClearedWebappHistory().
   UrlFilterBridge* filter_bridge = new UrlFilterBridge(url_filter);
 
-  Java_WebappRegistry_clearWebappHistoryForUrls(
-      env, base::android::GetApplicationContext(), filter_bridge->j_bridge(),
-      callback_pointer);
+  Java_WebappRegistry_clearWebappHistoryForUrls(env, filter_bridge->j_bridge(),
+                                                callback_pointer);
 }
 
 // Callback used by Java when all web apps have been unregistered.
diff --git a/chrome/browser/content_settings/content_settings_browsertest.cc b/chrome/browser/content_settings/content_settings_browsertest.cc
index 84dcf66..1bebedb 100644
--- a/chrome/browser/content_settings/content_settings_browsertest.cc
+++ b/chrome/browser/content_settings/content_settings_browsertest.cc
@@ -52,6 +52,11 @@
 #include "base/mac/scoped_nsautorelease_pool.h"
 #endif
 
+#if defined(ENABLE_PEPPER_CDMS)
+#include "chrome/browser/media/pepper_cdm_test_constants.h"
+#include "chrome/browser/media/pepper_cdm_test_helper.h"
+#endif
+
 using content::BrowserThread;
 using net::URLRequestMockHTTPJob;
 
@@ -351,12 +356,14 @@
 #endif
   }
 
+#if defined(ENABLE_PEPPER_CDMS)
   void SetUpDefaultCommandLine(base::CommandLine* command_line) override {
     base::CommandLine default_command_line(base::CommandLine::NO_PROGRAM);
     InProcessBrowserTest::SetUpDefaultCommandLine(&default_command_line);
     test_launcher_utils::RemoveCommandLineSwitch(
         default_command_line, switches::kDisableComponentUpdate, command_line);
   }
+#endif  // defined(ENABLE_PEPPER_CDMS)
 
   void SetUpInProcessBrowserTestFixture() override {
     ContentSettingsTest::SetUpInProcessBrowserTestFixture();
@@ -488,7 +495,8 @@
   RunLoadPepperPluginTest(content::kFlashPluginSwfMimeType, false);
 }
 
-#if defined(WIDEVINE_CDM_AVAILABLE) && !defined(OS_CHROMEOS)
+#if defined(ENABLE_PEPPER_CDMS) && defined(WIDEVINE_CDM_AVAILABLE) && \
+    !defined(OS_CHROMEOS)
 IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesPluginsBlockedTest,
                        WidevineCdm) {
   // Check that Widevine CDM is available and registered.
@@ -498,7 +506,8 @@
   EXPECT_TRUE(IsPepperCdmRegistered(kWidevineCdmPluginMimeType));
   RunLoadPepperPluginTest(kWidevineCdmPluginMimeType, true);
 }
-#endif  // defined(WIDEVINE_CDM_AVAILABLE) && !defined(OS_CHROMEOS)
+#endif  // defined(ENABLE_PEPPER_CDMS) && defined(WIDEVINE_CDM_AVAILABLE) &&
+        // !defined(OS_CHROMEOS)
 
 #if !defined(DISABLE_NACL)
 IN_PROC_BROWSER_TEST_F(PepperContentSettingsSpecialCasesPluginsBlockedTest,
diff --git a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc b/chrome/browser/media_galleries/chromeos/mtp_device_delegate_impl_chromeos.cc
similarity index 98%
rename from chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc
rename to chrome/browser/media_galleries/chromeos/mtp_device_delegate_impl_chromeos.cc
index b92956ab..a6d1870 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.cc
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_delegate_impl_chromeos.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 "chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_delegate_impl_chromeos.h"
 
 #include <errno.h>
 #include <fcntl.h>
@@ -22,8 +22,8 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
-#include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h"
-#include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.h"
+#include "chrome/browser/media_galleries/chromeos/snapshot_file_details.h"
 #include "net/base/io_buffer.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
diff --git a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h b/chrome/browser/media_galleries/chromeos/mtp_device_delegate_impl_chromeos.h
similarity index 97%
rename from chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h
rename to chrome/browser/media_galleries/chromeos/mtp_device_delegate_impl_chromeos.h
index 7f06a81..50d325d 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_delegate_impl_linux.h
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_delegate_impl_chromeos.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_DELEGATE_IMPL_CHROMEOS_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_DELEGATE_IMPL_CHROMEOS_H_
 
 #include <stdint.h>
 
@@ -19,8 +19,8 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_task_helper.h"
 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h"
-#include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h"
 #include "content/public/browser/browser_thread.h"
 #include "storage/browser/fileapi/async_file_util.h"
 
@@ -528,4 +528,4 @@
   DISALLOW_COPY_AND_ASSIGN(MTPDeviceDelegateImplLinux);
 };
 
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_DELEGATE_IMPL_LINUX_H_
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_DELEGATE_IMPL_CHROMEOS_H_
diff --git a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.cc b/chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.cc
similarity index 95%
rename from chrome/browser/media_galleries/linux/mtp_device_object_enumerator.cc
rename to chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.cc
index af5b125..5884cc6 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.cc
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.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 "chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.h"
 
 #include "base/logging.h"
 
diff --git a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h b/chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.h
similarity index 87%
rename from chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h
rename to chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.h
index 785e90d..b2d24641 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_OBJECT_ENUMERATOR_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_OBJECT_ENUMERATOR_H_
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_OBJECT_ENUMERATOR_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_OBJECT_ENUMERATOR_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -53,4 +53,4 @@
   DISALLOW_COPY_AND_ASSIGN(MTPDeviceObjectEnumerator);
 };
 
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_OBJECT_ENUMERATOR_H_
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_OBJECT_ENUMERATOR_H_
diff --git a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator_unittest.cc b/chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator_unittest.cc
similarity index 96%
rename from chrome/browser/media_galleries/linux/mtp_device_object_enumerator_unittest.cc
rename to chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator_unittest.cc
index ae15310..b8069279 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_object_enumerator_unittest.cc
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator_unittest.cc
@@ -6,7 +6,7 @@
 #include <stdint.h>
 
 #include "base/macros.h"
-#include "chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper.cc b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc
similarity index 97%
rename from chrome/browser/media_galleries/linux/mtp_device_task_helper.cc
rename to chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc
index 859eb65..e4cae1c 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_task_helper.cc
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_task_helper.h"
 
 #include <algorithm>
 #include <limits>
 
 #include "base/logging.h"
-#include "chrome/browser/media_galleries/linux/mtp_device_object_enumerator.h"
-#include "chrome/browser/media_galleries/linux/mtp_read_file_worker.h"
-#include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_read_file_worker.h"
+#include "chrome/browser/media_galleries/chromeos/snapshot_file_details.h"
 #include "components/storage_monitor/storage_monitor.h"
 #include "content/public/browser/browser_thread.h"
 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper.h b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.h
similarity index 97%
rename from chrome/browser/media_galleries/linux/mtp_device_task_helper.h
rename to chrome/browser/media_galleries/chromeos/mtp_device_task_helper.h
index 9a55c17..f4e34ad 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_task_helper.h
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_TASK_HELPER_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_TASK_HELPER_H_
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_TASK_HELPER_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_TASK_HELPER_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -247,4 +247,4 @@
   DISALLOW_COPY_AND_ASSIGN(MTPDeviceTaskHelper);
 };
 
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_TASK_HELPER_H_
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_TASK_HELPER_H_
diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.cc b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.cc
similarity index 93%
rename from chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.cc
rename to chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.cc
index dd054d4..416948e 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.cc
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.h"
 
 #include "base/logging.h"
 #include "base/stl_util.h"
-#include "chrome/browser/media_galleries/linux/mtp_device_task_helper.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_device_task_helper.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace {
diff --git a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.h
similarity index 90%
rename from chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h
rename to chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.h
index 21543f1..c8dc5a5 100644
--- a/chrome/browser/media_galleries/linux/mtp_device_task_helper_map_service.h
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper_map_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_TASK_HELPER_MAP_SERVICE_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_TASK_HELPER_MAP_SERVICE_H_
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_TASK_HELPER_MAP_SERVICE_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_TASK_HELPER_MAP_SERVICE_H_
 
 #include <map>
 #include <string>
@@ -63,4 +63,4 @@
   DISALLOW_COPY_AND_ASSIGN(MTPDeviceTaskHelperMapService);
 };
 
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_DEVICE_TASK_HELPER_MAP_SERVICE_H_
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_DEVICE_TASK_HELPER_MAP_SERVICE_H_
diff --git a/chrome/browser/media_galleries/linux/mtp_read_file_worker.cc b/chrome/browser/media_galleries/chromeos/mtp_read_file_worker.cc
similarity index 96%
rename from chrome/browser/media_galleries/linux/mtp_read_file_worker.cc
rename to chrome/browser/media_galleries/chromeos/mtp_read_file_worker.cc
index c5a081d..1914881 100644
--- a/chrome/browser/media_galleries/linux/mtp_read_file_worker.cc
+++ b/chrome/browser/media_galleries/chromeos/mtp_read_file_worker.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 "chrome/browser/media_galleries/linux/mtp_read_file_worker.h"
+#include "chrome/browser/media_galleries/chromeos/mtp_read_file_worker.h"
 
 #include <utility>
 
@@ -11,7 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
-#include "chrome/browser/media_galleries/linux/snapshot_file_details.h"
+#include "chrome/browser/media_galleries/chromeos/snapshot_file_details.h"
 #include "components/storage_monitor/storage_monitor.h"
 #include "content/public/browser/browser_thread.h"
 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
diff --git a/chrome/browser/media_galleries/linux/mtp_read_file_worker.h b/chrome/browser/media_galleries/chromeos/mtp_read_file_worker.h
similarity index 93%
rename from chrome/browser/media_galleries/linux/mtp_read_file_worker.h
rename to chrome/browser/media_galleries/chromeos/mtp_read_file_worker.h
index 842a3801..4b9f2da 100644
--- a/chrome/browser/media_galleries/linux/mtp_read_file_worker.h
+++ b/chrome/browser/media_galleries/chromeos/mtp_read_file_worker.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_READ_FILE_WORKER_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_READ_FILE_WORKER_H_
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_READ_FILE_WORKER_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_READ_FILE_WORKER_H_
 
 #include <stdint.h>
 
@@ -89,4 +89,4 @@
   DISALLOW_COPY_AND_ASSIGN(MTPReadFileWorker);
 };
 
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_MTP_READ_FILE_WORKER_H_
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_MTP_READ_FILE_WORKER_H_
diff --git a/chrome/browser/media_galleries/linux/snapshot_file_details.cc b/chrome/browser/media_galleries/chromeos/snapshot_file_details.cc
similarity index 96%
rename from chrome/browser/media_galleries/linux/snapshot_file_details.cc
rename to chrome/browser/media_galleries/chromeos/snapshot_file_details.cc
index a596389a..347f332 100644
--- a/chrome/browser/media_galleries/linux/snapshot_file_details.cc
+++ b/chrome/browser/media_galleries/chromeos/snapshot_file_details.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 "chrome/browser/media_galleries/linux/snapshot_file_details.h"
+#include "chrome/browser/media_galleries/chromeos/snapshot_file_details.h"
 
 #include <limits>
 
diff --git a/chrome/browser/media_galleries/linux/snapshot_file_details.h b/chrome/browser/media_galleries/chromeos/snapshot_file_details.h
similarity index 93%
rename from chrome/browser/media_galleries/linux/snapshot_file_details.h
rename to chrome/browser/media_galleries/chromeos/snapshot_file_details.h
index e4a2c157..d20b9f8 100644
--- a/chrome/browser/media_galleries/linux/snapshot_file_details.h
+++ b/chrome/browser/media_galleries/chromeos/snapshot_file_details.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_MEDIA_GALLERIES_LINUX_SNAPSHOT_FILE_DETAILS_H_
-#define CHROME_BROWSER_MEDIA_GALLERIES_LINUX_SNAPSHOT_FILE_DETAILS_H_
+#ifndef CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_SNAPSHOT_FILE_DETAILS_H_
+#define CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_SNAPSHOT_FILE_DETAILS_H_
 
 #include <stdint.h>
 
@@ -108,4 +108,4 @@
   DISALLOW_COPY_AND_ASSIGN(SnapshotFileDetails);
 };
 
-#endif  // CHROME_BROWSER_MEDIA_GALLERIES_LINUX_SNAPSHOT_FILE_DETAILS_H_
+#endif  // CHROME_BROWSER_MEDIA_GALLERIES_CHROMEOS_SNAPSHOT_FILE_DETAILS_H_
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
index 54179ad..c5a0a780 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
@@ -21,7 +21,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_validator_factory.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
@@ -51,6 +50,10 @@
 #include "chrome/browser/media_galleries/fileapi/picasa_file_util.h"
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h"
+#endif
+
 using storage::FileSystemContext;
 using storage::FileSystemURL;
 
@@ -137,18 +140,20 @@
       media_task_runner_(media_task_runner),
       media_path_filter_(new MediaPathFilter),
       media_copy_or_move_file_validator_factory_(new MediaFileValidatorFactory),
-      native_media_file_util_(
-          new NativeMediaFileUtil(media_path_filter_.get())),
+      native_media_file_util_(new NativeMediaFileUtil(media_path_filter_.get()))
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+      ,
       device_media_async_file_util_(
           DeviceMediaAsyncFileUtil::Create(profile_path_,
                                            APPLY_MEDIA_FILE_VALIDATION))
+#endif
 #if defined(OS_WIN) || defined(OS_MACOSX)
       ,
       picasa_file_util_(new picasa::PicasaFileUtil(media_path_filter_.get())),
       itunes_file_util_(new itunes::ITunesFileUtil(media_path_filter_.get())),
       picasa_file_util_used_(false),
       itunes_file_util_used_(false)
-#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+#endif
 {
 }
 
@@ -261,8 +266,10 @@
   switch (type) {
     case storage::kFileSystemTypeNativeMedia:
       return native_media_file_util_.get();
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
     case storage::kFileSystemTypeDeviceMedia:
       return device_media_async_file_util_.get();
+#endif
 #if defined(OS_WIN) || defined(OS_MACOSX)
     case storage::kFileSystemTypeItunes:
       if (!itunes_file_util_used_) {
@@ -322,10 +329,10 @@
 
 bool MediaFileSystemBackend::SupportsStreaming(
     const storage::FileSystemURL& url) const {
-  if (url.type() == storage::kFileSystemTypeDeviceMedia) {
-    DCHECK(device_media_async_file_util_);
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+  if (url.type() == storage::kFileSystemTypeDeviceMedia)
     return device_media_async_file_util_->SupportsStreaming(url);
-  }
+#endif
 
   return false;
 }
@@ -346,14 +353,15 @@
     int64_t max_bytes_to_read,
     const base::Time& expected_modification_time,
     FileSystemContext* context) const {
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
   if (url.type() == storage::kFileSystemTypeDeviceMedia) {
-    DCHECK(device_media_async_file_util_);
     std::unique_ptr<storage::FileStreamReader> reader =
         device_media_async_file_util_->GetFileStreamReader(
             url, offset, expected_modification_time, context);
     DCHECK(reader);
     return reader;
   }
+#endif
 
   return std::unique_ptr<storage::FileStreamReader>(
       storage::FileStreamReader::CreateForLocalFile(
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
index 6db0a68..d5f830f 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
@@ -31,8 +31,8 @@
 class URLRequest;
 }
 
-class MediaPathFilter;
 class DeviceMediaAsyncFileUtil;
+class MediaPathFilter;
 
 class MediaFileSystemBackend : public storage::FileSystemBackend {
  public:
@@ -110,7 +110,11 @@
       media_copy_or_move_file_validator_factory_;
 
   std::unique_ptr<storage::AsyncFileUtil> native_media_file_util_;
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
   std::unique_ptr<DeviceMediaAsyncFileUtil> device_media_async_file_util_;
+#endif
+
 #if defined(OS_WIN) || defined(OS_MACOSX)
   std::unique_ptr<storage::AsyncFileUtil> picasa_file_util_;
   std::unique_ptr<storage::AsyncFileUtil> itunes_file_util_;
@@ -118,7 +122,7 @@
   // Used for usage UMA tracking.
   bool picasa_file_util_used_;
   bool itunes_file_util_used_;
-#endif  // defined(OS_WIN) || defined(OS_MACOSX)
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(MediaFileSystemBackend);
 };
diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc
index 0fc94d39..5d36112 100644
--- a/chrome/browser/media_galleries/media_file_system_registry.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry.cc
@@ -15,7 +15,6 @@
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
-#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
 #include "chrome/browser/media_galleries/gallery_watch_manager.h"
 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
 #include "chrome/browser/media_galleries/media_file_system_context.h"
@@ -43,6 +42,10 @@
 #include "storage/common/fileapi/file_system_mount_option.h"
 #include "storage/common/fileapi/file_system_types.h"
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
+#endif
+
 using content::BrowserThread;
 using content::NavigationController;
 using content::RenderProcessHost;
@@ -663,11 +666,9 @@
   bool RegisterFileSystem(const std::string& device_id,
                           const std::string& fs_name,
                           const base::FilePath& path) override {
-    if (StorageInfo::IsMassStorageDevice(device_id)) {
+    if (StorageInfo::IsMassStorageDevice(device_id))
       return RegisterFileSystemForMassStorage(device_id, fs_name, path);
-    } else {
-      return RegisterFileSystemForMTPDevice(device_id, fs_name, path);
-    }
+    return RegisterFileSystemForMTPDevice(device_id, fs_name, path);
   }
 
   void RevokeFileSystem(const std::string& fs_name) override {
@@ -678,10 +679,12 @@
 
     ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name);
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
         &MTPDeviceMapService::RevokeMTPFileSystem,
         base::Unretained(MTPDeviceMapService::GetInstance()),
         fs_name));
+#endif
   }
 
   base::FilePath GetRegisteredPath(const std::string& fs_name) const override {
@@ -732,6 +735,7 @@
   bool RegisterFileSystemForMTPDevice(const std::string& device_id,
                                       const std::string fs_name,
                                       const base::FilePath& path) {
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(!StorageInfo::IsMassStorageDevice(device_id));
 
@@ -749,6 +753,10 @@
                    base::Unretained(MTPDeviceMapService::GetInstance()),
                    path.value(), fs_name, true /* read only */));
     return result;
+#else
+    NOTREACHED();
+    return false;
+#endif
   }
 
   DISALLOW_COPY_AND_ASSIGN(MediaFileSystemContextImpl);
diff --git a/chrome/browser/resources/md_history/app.crisper.js b/chrome/browser/resources/md_history/app.crisper.js
index e6c08baa..7f6560e2 100644
--- a/chrome/browser/resources/md_history/app.crisper.js
+++ b/chrome/browser/resources/md_history/app.crisper.js
@@ -5401,8 +5401,9 @@
     setTimeout(function() {
       chrome.send('metricsHandler:recordTime', [ 'History.ResultsRenderedTime', window.performance.now() ]);
     });
-    if (!this.hasDrawer_) {
-      this.focusToolbarSearchField();
+    var searchField = this.$.toolbar.searchField;
+    if (!searchField.narrow) {
+      searchField.getSearchInput().focus();
     }
     md_history.ensureLazyLoaded();
   },
diff --git a/chrome/browser/resources/md_history/app.js b/chrome/browser/resources/md_history/app.js
index 33e2c62..40b41e21 100644
--- a/chrome/browser/resources/md_history/app.js
+++ b/chrome/browser/resources/md_history/app.js
@@ -114,8 +114,10 @@
 
     // Focus the search field on load. Done here to ensure the history page
     // is rendered before we try to take focus.
-    if (!this.hasDrawer_) {
-      this.focusToolbarSearchField();
+    var searchField =
+        /** @type {HistoryToolbarElement} */ (this.$.toolbar).searchField;
+    if (!searchField.narrow) {
+      searchField.getSearchInput().focus();
     }
 
     // Lazily load the remainder of the UI.
@@ -176,7 +178,7 @@
   },
 
   /**
-   * Focuses the search bar in the toolbar.
+   * Shows and focuses the search bar in the toolbar.
    */
   focusToolbarSearchField: function() { this.$.toolbar.showSearchField(); },
 
diff --git a/chrome/browser/resources/md_history/app.vulcanized.html b/chrome/browser/resources/md_history/app.vulcanized.html
index ee1b943..43040c9 100644
--- a/chrome/browser/resources/md_history/app.vulcanized.html
+++ b/chrome/browser/resources/md_history/app.vulcanized.html
@@ -2721,7 +2721,7 @@
       <cr-toolbar id="main-toolbar" page-name="$i18n{title}" clear-label="$i18n{clearSearch}" search-prompt="$i18n{searchPrompt}" hidden$="[[itemsSelected_]]" spinner-active="[[spinnerActive]]" show-menu="[[hasDrawer]]" show-menu-promo="[[showMenuPromo_]]" menu-label="$i18n{historyMenuButton}" menu-promo="$i18n{menuPromo}" close-menu-promo="$i18n{closeMenuPromo}" on-search-changed="onSearchChanged_" on-cr-menu-promo-shown="onMenuPromoShown_">
         <div class="more-actions">
           <template is="dom-if" if="[[showSyncNotice]]">
-            <button is="paper-icon-button-light" id="info-button" on-tap="onInfoButtonTap_" aria-label="$i18n{hasSyncedResultsDescription}">
+            <button is="paper-icon-button-light" id="info-button" on-click="onInfoButtonTap_" aria-label="$i18n{hasSyncedResultsDescription}">
               <iron-icon icon="history:info-outline" id="info-button-icon">
               </iron-icon>
             </button>
@@ -3244,12 +3244,12 @@
           </div>
           <div id="star-container">
             <template is="dom-if" if="[[item.starred]]">
-              <button is="paper-icon-button-light" id="bookmark-star" title="$i18n{removeBookmark}" on-tap="onRemoveBookmarkTap_">
+              <button is="paper-icon-button-light" id="bookmark-star" title="$i18n{removeBookmark}" on-click="onRemoveBookmarkTap_">
                 <iron-icon icon="cr:star"></iron-icon>
               </button>
             </template>
           </div>
-          <button is="paper-icon-button-light" id="menu-button" class="more-vert-button" title="$i18n{moreActionsButton}" on-tap="onMenuButtonTap_">
+          <button is="paper-icon-button-light" id="menu-button" class="more-vert-button" title="$i18n{moreActionsButton}" on-click="onMenuButtonTap_">
             <div></div>
             <div></div>
             <div></div>
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/md_history/history_item.html
index d74b22f2..963a9a4 100644
--- a/chrome/browser/resources/md_history/history_item.html
+++ b/chrome/browser/resources/md_history/history_item.html
@@ -239,14 +239,14 @@
           <div id="star-container">
             <template is="dom-if" if="[[item.starred]]">
               <button is="paper-icon-button-light" id="bookmark-star"
-                  title="$i18n{removeBookmark}" on-tap="onRemoveBookmarkTap_">
+                  title="$i18n{removeBookmark}" on-click="onRemoveBookmarkTap_">
                 <iron-icon icon="cr:star"></iron-icon>
               </button>
             </template>
           </div>
           <button is="paper-icon-button-light" id="menu-button"
               class="more-vert-button" title="$i18n{moreActionsButton}"
-              on-tap="onMenuButtonTap_">
+              on-click="onMenuButtonTap_">
             <div></div>
             <div></div>
             <div></div>
diff --git a/chrome/browser/resources/md_history/history_toolbar.html b/chrome/browser/resources/md_history/history_toolbar.html
index ee80542..b651420 100644
--- a/chrome/browser/resources/md_history/history_toolbar.html
+++ b/chrome/browser/resources/md_history/history_toolbar.html
@@ -190,7 +190,7 @@
         <div class="more-actions">
           <template is="dom-if" if="[[showSyncNotice]]">
             <button is="paper-icon-button-light" id="info-button"
-                on-tap="onInfoButtonTap_"
+                on-click="onInfoButtonTap_"
                 aria-label="$i18n{hasSyncedResultsDescription}">
               <iron-icon icon="history:info-outline" id="info-button-icon">
               </iron-icon>
diff --git a/chrome/browser/resources/md_history/lazy_load.vulcanized.html b/chrome/browser/resources/md_history/lazy_load.vulcanized.html
index a1dfb0f..b36ec21 100644
--- a/chrome/browser/resources/md_history/lazy_load.vulcanized.html
+++ b/chrome/browser/resources/md_history/lazy_load.vulcanized.html
@@ -732,7 +732,7 @@
           <span id="last-update-time">[[lastUpdateTime]]</span>
         </div>
         <div id="right-buttons">
-          <button is="paper-icon-button-light" id="menu-button" class="more-vert-button" on-tap="onMenuButtonTap_" title="$i18n{moreActionsButton}">
+          <button is="paper-icon-button-light" id="menu-button" class="more-vert-button" on-click="onMenuButtonTap_" title="$i18n{moreActionsButton}">
             <div></div>
             <div></div>
             <div></div>
diff --git a/chrome/browser/resources/md_history/synced_device_card.html b/chrome/browser/resources/md_history/synced_device_card.html
index ff6329f..7f71f8bb 100644
--- a/chrome/browser/resources/md_history/synced_device_card.html
+++ b/chrome/browser/resources/md_history/synced_device_card.html
@@ -87,7 +87,7 @@
         </div>
         <div id="right-buttons">
           <button is="paper-icon-button-light" id="menu-button"
-              class="more-vert-button" on-tap="onMenuButtonTap_"
+              class="more-vert-button" on-click="onMenuButtonTap_"
               title="$i18n{moreActionsButton}">
             <div></div>
             <div></div>
diff --git a/chrome/browser/resources/pdf/manifest.json b/chrome/browser/resources/pdf/manifest.json
index 4e6189d..33a1e96f 100644
--- a/chrome/browser/resources/pdf/manifest.json
+++ b/chrome/browser/resources/pdf/manifest.json
@@ -14,7 +14,7 @@
   "mime_types": [
     "application/pdf"
   ],
-  "content_security_policy": "script-src 'self' blob: filesystem: chrome://resources; object-src * blob: file: filesystem: data:; plugin-types application/x-google-chrome-pdf",
+  "content_security_policy": "script-src 'self' blob: filesystem: chrome://resources; object-src * blob: externalfile: file: filesystem: data:; plugin-types application/x-google-chrome-pdf",
   "mime_types_handler": "index.html",
   "web_accessible_resources": [
     "*.js",
diff --git a/chrome/browser/safe_browsing/mock_permission_report_sender.cc b/chrome/browser/safe_browsing/mock_permission_report_sender.cc
index dc48a0a1..b6a8c0c 100644
--- a/chrome/browser/safe_browsing/mock_permission_report_sender.cc
+++ b/chrome/browser/safe_browsing/mock_permission_report_sender.cc
@@ -18,9 +18,11 @@
 }
 
 void MockPermissionReportSender::Send(const GURL& report_uri,
-                                      const std::string& report) {
+                                      base::StringPiece content_type,
+                                      base::StringPiece report) {
   latest_report_uri_ = report_uri;
-  latest_report_ = report;
+  report.CopyToString(&latest_report_);
+  content_type.CopyToString(&latest_content_type_);
   number_of_reports_++;
 
   // BrowserThreads aren't initialized in the unittest, so don't post tasks
@@ -56,6 +58,10 @@
   return latest_report_;
 }
 
+const std::string& MockPermissionReportSender::latest_content_type() {
+  return latest_content_type_;
+}
+
 int MockPermissionReportSender::GetAndResetNumberOfReportsSent() {
   int new_reports = number_of_reports_;
   number_of_reports_ = 0;
diff --git a/chrome/browser/safe_browsing/mock_permission_report_sender.h b/chrome/browser/safe_browsing/mock_permission_report_sender.h
index fc1c92ee..e8d6b76c 100644
--- a/chrome/browser/safe_browsing/mock_permission_report_sender.h
+++ b/chrome/browser/safe_browsing/mock_permission_report_sender.h
@@ -17,12 +17,16 @@
 
   ~MockPermissionReportSender() override;
 
-  void Send(const GURL& report_uri, const std::string& report) override;
+  void Send(const GURL& report_uri,
+            base::StringPiece content_type,
+            base::StringPiece report) override;
 
   const GURL& latest_report_uri();
 
   const std::string& latest_report();
 
+  const std::string& latest_content_type();
+
   int GetAndResetNumberOfReportsSent();
 
   void WaitForReportSent();
@@ -30,6 +34,7 @@
  private:
   GURL latest_report_uri_;
   std::string latest_report_;
+  std::string latest_content_type_;
   int number_of_reports_;
   base::Closure quit_closure_;
 
diff --git a/chrome/browser/safe_browsing/permission_reporter.cc b/chrome/browser/safe_browsing/permission_reporter.cc
index b03f2123..fee2d35 100644
--- a/chrome/browser/safe_browsing/permission_reporter.cc
+++ b/chrome/browser/safe_browsing/permission_reporter.cc
@@ -170,6 +170,7 @@
   std::string serialized_report;
   BuildReport(report_info, &serialized_report);
   permission_report_sender_->Send(GURL(kPermissionActionReportingUploadUrl),
+                                  "application/octet-stream",
                                   serialized_report);
 }
 
diff --git a/chrome/browser/safe_browsing/permission_reporter_unittest.cc b/chrome/browser/safe_browsing/permission_reporter_unittest.cc
index 6f83885..7a825cb4 100644
--- a/chrome/browser/safe_browsing/permission_reporter_unittest.cc
+++ b/chrome/browser/safe_browsing/permission_reporter_unittest.cc
@@ -118,6 +118,8 @@
 
   EXPECT_EQ(GURL(kPermissionActionReportingUploadUrl),
             mock_report_sender_->latest_report_uri());
+  EXPECT_EQ("application/octet-stream",
+            mock_report_sender_->latest_content_type());
 }
 
 // Test that PermissionReporter::SendReport sends a serialized report string
@@ -153,6 +155,9 @@
 
   permission_reporter_->SendReport(BuildDummyReportInfo());
 
+  EXPECT_EQ("application/octet-stream",
+            mock_report_sender_->latest_content_type());
+
   PermissionReport permission_report;
   ASSERT_TRUE(
       permission_report.ParseFromString(mock_report_sender_->latest_report()));
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter.cc b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
index 297ecdc..8a50a200 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter.cc
@@ -176,5 +176,6 @@
 
   UMA_HISTOGRAM_BOOLEAN("SSL.ExpectCTReportSendingAttempt", true);
 
-  report_sender_->Send(report_uri, serialized_report);
+  report_sender_->Send(report_uri, "application/json; charset=utf-8",
+                       serialized_report);
 }
diff --git a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
index a5bdeb3..7efa5a13 100644
--- a/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
+++ b/chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc
@@ -39,19 +39,24 @@
   ~TestCertificateReportSender() override {}
 
   void Send(const GURL& report_uri,
-            const std::string& serialized_report) override {
+            base::StringPiece content_type,
+            base::StringPiece serialized_report) override {
     latest_report_uri_ = report_uri;
-    latest_serialized_report_ = serialized_report;
+    serialized_report.CopyToString(&latest_serialized_report_);
+    content_type.CopyToString(&latest_content_type_);
   }
 
   const GURL& latest_report_uri() { return latest_report_uri_; }
 
+  const std::string& latest_content_type() { return latest_content_type_; }
+
   const std::string& latest_serialized_report() {
     return latest_serialized_report_;
   }
 
  private:
   GURL latest_report_uri_;
+  std::string latest_content_type_;
   std::string latest_serialized_report_;
 };
 
@@ -478,6 +483,7 @@
   reporter.OnExpectCTFailed(host_port, report_uri, ssl_info);
   EXPECT_EQ(report_uri, sender->latest_report_uri());
   EXPECT_FALSE(sender->latest_serialized_report().empty());
+  EXPECT_EQ("application/json; charset=utf-8", sender->latest_content_type());
   ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport(
       sender->latest_serialized_report(), host_port, ssl_info));
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 7c0a94c..2dd0e902 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3502,7 +3502,6 @@
       "../browser/media/webrtc/tab_desktop_media_list_unittest.cc",
       "../browser/media_galleries/fileapi/native_media_file_util_unittest.cc",
       "../browser/media_galleries/gallery_watch_manager_unittest.cc",
-      "../browser/media_galleries/linux/mtp_device_object_enumerator_unittest.cc",
       "../browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm",
       "../browser/media_galleries/media_file_system_registry_unittest.cc",
       "../browser/media_galleries/media_galleries_dialog_controller_mock.cc",
@@ -3857,6 +3856,7 @@
       "../browser/extensions/zipfile_installer_unittest.cc",
       "../browser/media/cast_remoting_sender_unittest.cc",
       "../browser/media/cast_transport_host_filter_unittest.cc",
+      "../browser/media_galleries/chromeos/mtp_device_object_enumerator_unittest.cc",
       "../browser/metrics/extensions_metrics_provider_unittest.cc",
       "../browser/notifications/extension_welcome_notification_unittest.cc",
       "../browser/notifications/notification_conversion_helper_unittest.cc",
diff --git a/chrome/test/data/webui/md_history/history_toolbar_test.js b/chrome/test/data/webui/md_history/history_toolbar_test.js
index b16793c..bbac0e3 100644
--- a/chrome/test/data/webui/md_history/history_toolbar_test.js
+++ b/chrome/test/data/webui/md_history/history_toolbar_test.js
@@ -116,6 +116,7 @@
       ;
 
       setup(function() {
+        window.resultsRendered = false;
         app = replaceApp();
 
         element = app.$['history'].$['infinite-list'];
@@ -123,8 +124,7 @@
       });
 
       test('search bar is focused on load in wide mode', function() {
-        window.resultsRendered = false;
-        app.hasDrawer_ = false;
+        toolbar.$['main-toolbar'].narrow_ = false;
 
         historyResult(createHistoryInfo(), []);
         return flush().then(() => {
@@ -137,15 +137,17 @@
       });
 
       test('search bar is not focused on load in narrow mode', function() {
-        app.hasDrawer_ = true;
+        toolbar.$['main-toolbar'].narrow_ = true;
 
         historyResult(createHistoryInfo(), []);
-        // Ensure the search bar is focused on load.
-        assertFalse(
-            $('history-app')
-                .$.toolbar.$['main-toolbar']
-                .getSearchField()
-                .isSearchFocused());
+        return flush().then(() => {
+          // Ensure the search bar is focused on load.
+          assertFalse(
+              $('history-app')
+                  .$.toolbar.$['main-toolbar']
+                  .getSearchField()
+                  .isSearchFocused());
+        });
       });
     });
   };
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn
index 8b1ec987..15a8c8bf 100644
--- a/chromecast/browser/BUILD.gn
+++ b/chromecast/browser/BUILD.gn
@@ -87,6 +87,7 @@
     "//chromecast/base:cast_version",
     "//chromecast/common",
     "//chromecast/common/media",
+    "//chromecast/graphics",
     "//chromecast/media",
     "//chromecast/net",
     "//chromecast/service",
@@ -127,7 +128,6 @@
 
     deps += [
       "//build/linux:fontconfig",
-      "//chromecast/graphics",
       "//components/metrics:serialization",
       "//ui/aura",
     ]
diff --git a/chromecast/browser/cast_content_window.cc b/chromecast/browser/cast_content_window.cc
index cd7e7e2..5eb8cfd 100644
--- a/chromecast/browser/cast_content_window.cc
+++ b/chromecast/browser/cast_content_window.cc
@@ -9,6 +9,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "chromecast/base/metrics/cast_metrics_helper.h"
 #include "chromecast/browser/cast_browser_process.h"
+#include "chromecast/graphics/cast_vsync_settings.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
@@ -64,6 +65,7 @@
 
 CastContentWindow::~CastContentWindow() {
 #if defined(USE_AURA)
+  CastVSyncSettings::GetInstance()->RemoveObserver(this);
   window_tree_host_.reset();
   // We don't delete the screen here to avoid a CHECK failure when
   // the screen size is queried periodically for metric gathering. b/18101124
@@ -89,6 +91,11 @@
   } else {
     window_tree_host_->compositor()->SetBackgroundColor(SK_ColorBLACK);
   }
+
+  CastVSyncSettings::GetInstance()->AddObserver(this);
+  window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(
+      CastVSyncSettings::GetInstance()->GetVSyncInterval());
+
   window_tree_host_->Show();
 
   // Add and show content's view/window
@@ -137,5 +144,12 @@
                                           : SK_ColorBLACK);
 }
 
+void CastContentWindow::OnVSyncIntervalChanged(base::TimeDelta interval) {
+#if defined(USE_AURA)
+  window_tree_host_->compositor()->SetAuthoritativeVSyncInterval(
+      interval);
+#endif
+}
+
 }  // namespace shell
 }  // namespace chromecast
diff --git a/chromecast/browser/cast_content_window.h b/chromecast/browser/cast_content_window.h
index dfce908..1d393da 100644
--- a/chromecast/browser/cast_content_window.h
+++ b/chromecast/browser/cast_content_window.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "chromecast/graphics/cast_vsync_settings.h"
 #include "content/public/browser/web_contents_observer.h"
 
 namespace aura {
@@ -26,7 +27,8 @@
 namespace chromecast {
 namespace shell {
 
-class CastContentWindow : public content::WebContentsObserver {
+class CastContentWindow : public content::WebContentsObserver,
+                          public CastVSyncSettings::Observer {
  public:
   CastContentWindow();
 
@@ -49,6 +51,9 @@
   void MediaStartedPlaying(const MediaPlayerId& id) override;
   void RenderViewCreated(content::RenderViewHost* render_view_host) override;
 
+  // CastVSyncSettings::Observer implementation:
+  void OnVSyncIntervalChanged(base::TimeDelta interval) override;
+
  private:
 #if defined(USE_AURA)
   std::unique_ptr<aura::WindowTreeHost> window_tree_host_;
diff --git a/chromecast/graphics/BUILD.gn b/chromecast/graphics/BUILD.gn
index 7c1c607..435b1a02 100644
--- a/chromecast/graphics/BUILD.gn
+++ b/chromecast/graphics/BUILD.gn
@@ -5,14 +5,23 @@
 import("//chromecast/chromecast.gni")
 import("//build/config/ui.gni")
 
-if (use_aura) {
-  source_set("graphics") {
-    sources = [
+source_set("graphics") {
+  sources = [
+    "cast_vsync_settings.cc",
+    "cast_vsync_settings.h",
+  ]
+
+  deps = [
+    "//base",
+  ]
+
+  if (use_aura) {
+    sources += [
       "cast_screen.cc",
       "cast_screen.h",
     ]
 
-    deps = [
+    deps += [
       ":libcast_graphics_1.0",
       "//chromecast/public",
       "//ui/aura",
diff --git a/chromecast/graphics/cast_vsync_settings.cc b/chromecast/graphics/cast_vsync_settings.cc
new file mode 100644
index 0000000..5c2a951
--- /dev/null
+++ b/chromecast/graphics/cast_vsync_settings.cc
@@ -0,0 +1,43 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/graphics/cast_vsync_settings.h"
+
+namespace chromecast {
+namespace {
+base::LazyInstance<CastVSyncSettings> g_instance = LAZY_INSTANCE_INITIALIZER;
+}  // namespace
+
+// static
+CastVSyncSettings* CastVSyncSettings::GetInstance() {
+  return g_instance.Pointer();
+}
+
+base::TimeDelta CastVSyncSettings::GetVSyncInterval() const {
+  return interval_;
+}
+
+void CastVSyncSettings::SetVSyncInterval(base::TimeDelta interval) {
+  if (interval_ == interval)
+    return;
+  interval_ = interval;
+  FOR_EACH_OBSERVER(Observer, observers_,
+                    OnVSyncIntervalChanged(interval));
+}
+
+void CastVSyncSettings::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void CastVSyncSettings::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+// Default to 60fps until set otherwise
+CastVSyncSettings::CastVSyncSettings()
+    : interval_(base::TimeDelta::FromMicroseconds(16666)) {}
+
+CastVSyncSettings::~CastVSyncSettings() = default;
+
+}  // namespace chromecast
diff --git a/chromecast/graphics/cast_vsync_settings.h b/chromecast/graphics/cast_vsync_settings.h
new file mode 100644
index 0000000..791fd0f
--- /dev/null
+++ b/chromecast/graphics/cast_vsync_settings.h
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_GRAPHICS_CAST_VSYNC_SETTINGS_H_
+#define CHROMECAST_GRAPHICS_CAST_VSYNC_SETTINGS_H_
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "base/observer_list.h"
+#include "base/time/time.h"
+
+namespace chromecast {
+
+// Provides a central place to manage VSync interval, supports observers
+// to be notified of changes.
+// TODO(halliwell): plumb this via Ozone or ui::Display instead.
+class CastVSyncSettings {
+ public:
+  class Observer {
+   public:
+    virtual ~Observer() {}
+    virtual void OnVSyncIntervalChanged(base::TimeDelta interval) = 0;
+  };
+
+  static CastVSyncSettings* GetInstance();
+
+  base::TimeDelta GetVSyncInterval() const;
+  void SetVSyncInterval(base::TimeDelta interval);
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+ private:
+  friend struct base::DefaultLazyInstanceTraits<CastVSyncSettings>;
+
+  CastVSyncSettings();
+  ~CastVSyncSettings();
+
+  base::TimeDelta interval_;
+  base::ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(CastVSyncSettings);
+};
+
+}  // namespace chromecast
+
+#endif  // CHROMECAST_GRAPHICS_CAST_VSYNC_SETTINGS_H_
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index f81bf3cc..f7a6eee 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-8839.0.0
\ No newline at end of file
+8843.0.0
\ No newline at end of file
diff --git a/components/certificate_reporting/error_reporter.cc b/components/certificate_reporting/error_reporter.cc
index 124d2f260..3e639ea 100644
--- a/components/certificate_reporting/error_reporter.cc
+++ b/components/certificate_reporting/error_reporter.cc
@@ -139,7 +139,8 @@
 void ErrorReporter::SendExtendedReportingReport(
     const std::string& serialized_report) {
   if (upload_url_.SchemeIsCryptographic()) {
-    certificate_report_sender_->Send(upload_url_, serialized_report);
+    certificate_report_sender_->Send(upload_url_, "application/octet-stream",
+                                     serialized_report);
   } else {
     EncryptedCertLoggerRequest encrypted_report;
     if (!EncryptSerializedReport(server_public_key_, server_public_key_version_,
@@ -149,7 +150,8 @@
     }
     std::string serialized_encrypted_report;
     encrypted_report.SerializeToString(&serialized_encrypted_report);
-    certificate_report_sender_->Send(upload_url_, serialized_encrypted_report);
+    certificate_report_sender_->Send(upload_url_, "application/octet-stream",
+                                     serialized_encrypted_report);
   }
 }
 
diff --git a/components/certificate_reporting/error_reporter_unittest.cc b/components/certificate_reporting/error_reporter_unittest.cc
index 6398c5fc..6e83ca1 100644
--- a/components/certificate_reporting/error_reporter_unittest.cc
+++ b/components/certificate_reporting/error_reporter_unittest.cc
@@ -42,18 +42,24 @@
       : net::ReportSender(nullptr, DO_NOT_SEND_COOKIES) {}
   ~MockCertificateReportSender() override {}
 
-  void Send(const GURL& report_uri, const std::string& report) override {
+  void Send(const GURL& report_uri,
+            base::StringPiece content_type,
+            base::StringPiece report) override {
     latest_report_uri_ = report_uri;
-    latest_report_ = report;
+    report.CopyToString(&latest_report_);
+    content_type.CopyToString(&latest_content_type_);
   }
 
   const GURL& latest_report_uri() { return latest_report_uri_; }
 
   const std::string& latest_report() { return latest_report_; }
 
+  const std::string& latest_content_type() { return latest_content_type_; }
+
  private:
   GURL latest_report_uri_;
   std::string latest_report_;
+  std::string latest_content_type_;
 
   DISALLOW_COPY_AND_ASSIGN(MockCertificateReportSender);
 };
@@ -121,6 +127,8 @@
   http_reporter.SendExtendedReportingReport(kDummyReport);
 
   EXPECT_EQ(http_mock_report_sender->latest_report_uri(), http_url);
+  EXPECT_EQ("application/octet-stream",
+            http_mock_report_sender->latest_content_type());
 
   std::string uploaded_report;
   EncryptedCertLoggerRequest encrypted_request;
diff --git a/components/storage_monitor/BUILD.gn b/components/storage_monitor/BUILD.gn
index a0c4d0e..87b7911 100644
--- a/components/storage_monitor/BUILD.gn
+++ b/components/storage_monitor/BUILD.gn
@@ -12,8 +12,6 @@
     "image_capture_device_manager.mm",
     "media_storage_util.cc",
     "media_storage_util.h",
-    "media_transfer_protocol_device_observer_linux.cc",
-    "media_transfer_protocol_device_observer_linux.h",
     "mtab_watcher_linux.cc",
     "mtab_watcher_linux.h",
     "portable_device_watcher_win.cc",
@@ -55,12 +53,16 @@
     ]
   }
 
-  if (is_linux && use_dbus) {
+  if (is_chromeos && use_dbus) {
     deps += [
       "//device/media_transfer_protocol",
       "//device/media_transfer_protocol:mtp_file_entry_proto",
       "//device/media_transfer_protocol:mtp_storage_info_proto",
     ]
+    sources += [
+      "media_transfer_protocol_device_observer_chromeos.cc",
+      "media_transfer_protocol_device_observer_chromeos.h",
+    ]
   }
 
   if (use_udev) {
@@ -91,8 +93,8 @@
   sources = [
     "mock_removable_storage_observer.cc",
     "mock_removable_storage_observer.h",
-    "test_media_transfer_protocol_manager_linux.cc",
-    "test_media_transfer_protocol_manager_linux.h",
+    "test_media_transfer_protocol_manager_chromeos.cc",
+    "test_media_transfer_protocol_manager_chromeos.h",
     "test_portable_device_watcher_win.cc",
     "test_portable_device_watcher_win.h",
     "test_storage_monitor.cc",
@@ -109,7 +111,7 @@
     "//content/public/browser",
   ]
 
-  if (is_linux && use_dbus) {
+  if (is_chromeos && use_dbus) {
     deps = [
       "//device/media_transfer_protocol",
       "//device/media_transfer_protocol:mtp_file_entry_proto",
@@ -129,7 +131,7 @@
   sources = [
     "image_capture_device_manager_unittest.mm",
     "media_storage_util_unittest.cc",
-    "media_transfer_protocol_device_observer_linux_unittest.cc",
+    "media_transfer_protocol_device_observer_chromeos_unittest.cc",
     "storage_info_unittest.cc",
     "storage_monitor_mac_unittest.mm",
     "storage_monitor_unittest.cc",
@@ -144,17 +146,20 @@
     "//testing/gtest",
   ]
 
-  if (is_linux && use_dbus) {
-    deps += [ "//device/media_transfer_protocol" ]
-    if (!is_chromeos) {
+  if (use_dbus) {
+    if (is_chromeos) {
+      deps += [
+        "//device/media_transfer_protocol",
+        "//device/media_transfer_protocol:mtp_file_entry_proto",
+        "//device/media_transfer_protocol:mtp_storage_info_proto",
+        "//testing/gmock",
+      ]
+      sources += [ "storage_monitor_chromeos_unittest.cc" ]
+    } else if (is_linux) {
       sources += [ "storage_monitor_linux_unittest.cc" ]
     }
   }
   if (is_chromeos) {
-    sources += [ "storage_monitor_chromeos_unittest.cc" ]
-    deps += [
-      "//chromeos:test_support",
-      "//testing/gmock",
-    ]
+    deps += [ "//chromeos:test_support" ]
   }
 }
diff --git a/components/storage_monitor/media_transfer_protocol_device_observer_linux.cc b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
similarity index 85%
rename from components/storage_monitor/media_transfer_protocol_device_observer_linux.cc
rename to components/storage_monitor/media_transfer_protocol_device_observer_chromeos.cc
index e983bc1..0616199 100644
--- a/components/storage_monitor/media_transfer_protocol_device_observer_linux.cc
+++ b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.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 "components/storage_monitor/media_transfer_protocol_device_observer_linux.h"
+#include "components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h"
 
 #include <vector>
 
@@ -119,10 +119,10 @@
 
 }  // namespace
 
-MediaTransferProtocolDeviceObserverLinux::
-MediaTransferProtocolDeviceObserverLinux(
-    StorageMonitor::Receiver* receiver,
-    device::MediaTransferProtocolManager* mtp_manager)
+MediaTransferProtocolDeviceObserverChromeOS::
+    MediaTransferProtocolDeviceObserverChromeOS(
+        StorageMonitor::Receiver* receiver,
+        device::MediaTransferProtocolManager* mtp_manager)
     : mtp_manager_(mtp_manager),
       get_storage_info_func_(&GetStorageInfo),
       notifications_(receiver) {
@@ -131,22 +131,21 @@
 }
 
 // This constructor is only used by unit tests.
-MediaTransferProtocolDeviceObserverLinux::
-MediaTransferProtocolDeviceObserverLinux(
-    StorageMonitor::Receiver* receiver,
-    device::MediaTransferProtocolManager* mtp_manager,
-    GetStorageInfoFunc get_storage_info_func)
+MediaTransferProtocolDeviceObserverChromeOS::
+    MediaTransferProtocolDeviceObserverChromeOS(
+        StorageMonitor::Receiver* receiver,
+        device::MediaTransferProtocolManager* mtp_manager,
+        GetStorageInfoFunc get_storage_info_func)
     : mtp_manager_(mtp_manager),
       get_storage_info_func_(get_storage_info_func),
-      notifications_(receiver) {
-}
+      notifications_(receiver) {}
 
-MediaTransferProtocolDeviceObserverLinux::
-~MediaTransferProtocolDeviceObserverLinux() {
+MediaTransferProtocolDeviceObserverChromeOS::
+    ~MediaTransferProtocolDeviceObserverChromeOS() {
   mtp_manager_->RemoveObserver(this);
 }
 
-bool MediaTransferProtocolDeviceObserverLinux::GetStorageInfoForPath(
+bool MediaTransferProtocolDeviceObserverChromeOS::GetStorageInfoForPath(
     const base::FilePath& path,
     StorageInfo* storage_info) const {
   DCHECK(storage_info);
@@ -171,7 +170,7 @@
   return true;
 }
 
-void MediaTransferProtocolDeviceObserverLinux::EjectDevice(
+void MediaTransferProtocolDeviceObserverChromeOS::EjectDevice(
     const std::string& device_id,
     base::Callback<void(StorageMonitor::EjectStatus)> callback) {
   std::string location;
@@ -187,7 +186,7 @@
 }
 
 // device::MediaTransferProtocolManager::Observer override.
-void MediaTransferProtocolDeviceObserverLinux::StorageChanged(
+void MediaTransferProtocolDeviceObserverChromeOS::StorageChanged(
     bool is_attached,
     const std::string& storage_name) {
   DCHECK(!storage_name.empty());
@@ -199,9 +198,9 @@
     std::string location;
     base::string16 vendor_name;
     base::string16 product_name;
-    get_storage_info_func_(storage_name, mtp_manager_,
-                           &device_id, &storage_label, &location,
-                           &vendor_name, &product_name);
+    get_storage_info_func_(storage_name, mtp_manager_, &device_id,
+                           &storage_label, &location, &vendor_name,
+                           &product_name);
 
     // Keep track of device id and device name to see how often we receive
     // empty values.
@@ -212,8 +211,8 @@
 
     DCHECK(!base::ContainsKey(storage_map_, location));
 
-    StorageInfo storage_info(device_id, location, storage_label,
-                             vendor_name, product_name, 0);
+    StorageInfo storage_info(device_id, location, storage_label, vendor_name,
+                             product_name, 0);
     storage_map_[location] = storage_info;
     notifications_->ProcessAttach(storage_info);
   } else {
@@ -227,7 +226,7 @@
   }
 }
 
-void MediaTransferProtocolDeviceObserverLinux::EnumerateStorages() {
+void MediaTransferProtocolDeviceObserverChromeOS::EnumerateStorages() {
   typedef std::vector<std::string> StorageList;
   StorageList storages = mtp_manager_->GetStorages();
   for (StorageList::const_iterator storage_iter = storages.begin();
@@ -236,8 +235,9 @@
   }
 }
 
-bool MediaTransferProtocolDeviceObserverLinux::GetLocationForDeviceId(
-    const std::string& device_id, std::string* location) const {
+bool MediaTransferProtocolDeviceObserverChromeOS::GetLocationForDeviceId(
+    const std::string& device_id,
+    std::string* location) const {
   for (StorageLocationToInfoMap::const_iterator it = storage_map_.begin();
        it != storage_map_.end(); ++it) {
     if (it->second.device_id() == device_id) {
diff --git a/components/storage_monitor/media_transfer_protocol_device_observer_linux.h b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h
similarity index 89%
rename from components/storage_monitor/media_transfer_protocol_device_observer_linux.h
rename to components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h
index 611d0da2..a004426f 100644
--- a/components/storage_monitor/media_transfer_protocol_device_observer_linux.h
+++ b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos.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 COMPONENTS_STORAGE_MONITOR_MEDIA_TRANSFER_PROTOCOL_DEVICE_OBSERVER_LINUX_H_
-#define COMPONENTS_STORAGE_MONITOR_MEDIA_TRANSFER_PROTOCOL_DEVICE_OBSERVER_LINUX_H_
+#ifndef COMPONENTS_STORAGE_MONITOR_MEDIA_TRANSFER_PROTOCOL_DEVICE_OBSERVER_CHROMEOS_H_
+#define COMPONENTS_STORAGE_MONITOR_MEDIA_TRANSFER_PROTOCOL_DEVICE_OBSERVER_CHROMEOS_H_
 
 #include <map>
 #include <string>
@@ -32,13 +32,13 @@
 
 // Helper class to send MTP storage attachment and detachment events to
 // StorageMonitor.
-class MediaTransferProtocolDeviceObserverLinux
+class MediaTransferProtocolDeviceObserverChromeOS
     : public device::MediaTransferProtocolManager::Observer {
  public:
-  MediaTransferProtocolDeviceObserverLinux(
+  MediaTransferProtocolDeviceObserverChromeOS(
       StorageMonitor::Receiver* receiver,
       device::MediaTransferProtocolManager* mtp_manager);
-  ~MediaTransferProtocolDeviceObserverLinux() override;
+  ~MediaTransferProtocolDeviceObserverChromeOS() override;
 
   // Finds the storage that contains |path| and populates |storage_info|.
   // Returns false if unable to find the storage.
@@ -50,7 +50,7 @@
 
  protected:
   // Only used in unit tests.
-  MediaTransferProtocolDeviceObserverLinux(
+  MediaTransferProtocolDeviceObserverChromeOS(
       StorageMonitor::Receiver* receiver,
       device::MediaTransferProtocolManager* mtp_manager,
       GetStorageInfoFunc get_storage_info_func);
@@ -87,9 +87,9 @@
   // Guaranteed to outlive this class.
   StorageMonitor::Receiver* const notifications_;
 
-  DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDeviceObserverLinux);
+  DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDeviceObserverChromeOS);
 };
 
 }  // namespace storage_monitor
 
-#endif  // COMPONENTS_STORAGE_MONITOR_MEDIA_TRANSFER_PROTOCOL_DEVICE_OBSERVER_LINUX_H_
+#endif  // COMPONENTS_STORAGE_MONITOR_MEDIA_TRANSFER_PROTOCOL_DEVICE_OBSERVER_CHROMEOS_H_
diff --git a/components/storage_monitor/media_transfer_protocol_device_observer_linux_unittest.cc b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc
similarity index 78%
rename from components/storage_monitor/media_transfer_protocol_device_observer_linux_unittest.cc
rename to components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc
index 0bb6ba81..0ddc612 100644
--- a/components/storage_monitor/media_transfer_protocol_device_observer_linux_unittest.cc
+++ b/components/storage_monitor/media_transfer_protocol_device_observer_chromeos_unittest.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// MediaTransferProtocolDeviceObserverLinux unit tests.
+// MediaTransferProtocolDeviceObserverChromeOS unit tests.
 
-#include "components/storage_monitor/media_transfer_protocol_device_observer_linux.h"
+#include "components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h"
 
 #include <memory>
 #include <string>
@@ -60,24 +60,26 @@
   *product_name = base::ASCIIToUTF16(kStorageProductName);
 }
 
-class TestMediaTransferProtocolDeviceObserverLinux
-    : public MediaTransferProtocolDeviceObserverLinux {
+class TestMediaTransferProtocolDeviceObserverChromeOS
+    : public MediaTransferProtocolDeviceObserverChromeOS {
  public:
-  TestMediaTransferProtocolDeviceObserverLinux(
+  TestMediaTransferProtocolDeviceObserverChromeOS(
       StorageMonitor::Receiver* receiver,
       device::MediaTransferProtocolManager* mtp_manager)
-      : MediaTransferProtocolDeviceObserverLinux(receiver, mtp_manager,
-                                                 &GetStorageInfo) {
-  }
+      : MediaTransferProtocolDeviceObserverChromeOS(receiver,
+                                                    mtp_manager,
+                                                    &GetStorageInfo) {}
 
-  // Notifies MediaTransferProtocolDeviceObserverLinux about the attachment of
+  // Notifies MediaTransferProtocolDeviceObserverChromeOS about the attachment
+  // of
   // mtp storage device given the |storage_name|.
   void MtpStorageAttached(const std::string& storage_name) {
     StorageChanged(true, storage_name);
     base::RunLoop().RunUntilIdle();
   }
 
-  // Notifies MediaTransferProtocolDeviceObserverLinux about the detachment of
+  // Notifies MediaTransferProtocolDeviceObserverChromeOS about the detachment
+  // of
   // mtp storage device given the |storage_name|.
   void MtpStorageDetached(const std::string& storage_name) {
     StorageChanged(false, storage_name);
@@ -85,26 +87,26 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(TestMediaTransferProtocolDeviceObserverLinux);
+  DISALLOW_COPY_AND_ASSIGN(TestMediaTransferProtocolDeviceObserverChromeOS);
 };
 
 }  // namespace
 
-// A class to test the functionality of MediaTransferProtocolDeviceObserverLinux
-// member functions.
-class MediaTransferProtocolDeviceObserverLinuxTest : public testing::Test {
+// A class to test the functionality of
+// MediaTransferProtocolDeviceObserverChromeOS member functions.
+class MediaTransferProtocolDeviceObserverChromeOSTest : public testing::Test {
  public:
-  MediaTransferProtocolDeviceObserverLinuxTest()
+  MediaTransferProtocolDeviceObserverChromeOSTest()
       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
 
-  ~MediaTransferProtocolDeviceObserverLinuxTest() override {}
+  ~MediaTransferProtocolDeviceObserverChromeOSTest() override {}
 
  protected:
   void SetUp() override {
     mock_storage_observer_.reset(new MockRemovableStorageObserver);
     TestStorageMonitor* monitor = TestStorageMonitor::CreateAndInstall();
     mtp_device_observer_.reset(
-        new TestMediaTransferProtocolDeviceObserverLinux(
+        new TestMediaTransferProtocolDeviceObserverChromeOS(
             monitor->receiver(), monitor->media_transfer_protocol_manager()));
     monitor->AddObserver(mock_storage_observer_.get());
   }
@@ -117,26 +119,24 @@
   }
 
   // Returns the device changed observer object.
-  MockRemovableStorageObserver& observer() {
-    return *mock_storage_observer_;
-  }
+  MockRemovableStorageObserver& observer() { return *mock_storage_observer_; }
 
-  TestMediaTransferProtocolDeviceObserverLinux* mtp_device_observer() {
+  TestMediaTransferProtocolDeviceObserverChromeOS* mtp_device_observer() {
     return mtp_device_observer_.get();
   }
 
  private:
   content::TestBrowserThreadBundle thread_bundle_;
 
-  std::unique_ptr<TestMediaTransferProtocolDeviceObserverLinux>
+  std::unique_ptr<TestMediaTransferProtocolDeviceObserverChromeOS>
       mtp_device_observer_;
   std::unique_ptr<MockRemovableStorageObserver> mock_storage_observer_;
 
-  DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDeviceObserverLinuxTest);
+  DISALLOW_COPY_AND_ASSIGN(MediaTransferProtocolDeviceObserverChromeOSTest);
 };
 
 // Test to verify basic mtp storage attach and detach notifications.
-TEST_F(MediaTransferProtocolDeviceObserverLinuxTest, BasicAttachDetach) {
+TEST_F(MediaTransferProtocolDeviceObserverChromeOSTest, BasicAttachDetach) {
   std::string device_id = GetMtpDeviceId(kStorageUniqueId);
 
   // Attach a mtp storage.
@@ -162,7 +162,8 @@
 // When a mtp storage device with invalid storage label and id is
 // attached/detached, there should not be any device attach/detach
 // notifications.
-TEST_F(MediaTransferProtocolDeviceObserverLinuxTest, StorageWithInvalidInfo) {
+TEST_F(MediaTransferProtocolDeviceObserverChromeOSTest,
+       StorageWithInvalidInfo) {
   // Attach the mtp storage with invalid storage info.
   mtp_device_observer()->MtpStorageAttached(kStorageWithInvalidInfo);
 
diff --git a/components/storage_monitor/storage_monitor.h b/components/storage_monitor/storage_monitor.h
index 5e8654ab..5c58581 100644
--- a/components/storage_monitor/storage_monitor.h
+++ b/components/storage_monitor/storage_monitor.h
@@ -120,7 +120,7 @@
       base::string16* storage_object_id) const = 0;
 #endif
 
-#if defined(OS_LINUX)
+#if defined(OS_CHROMEOS)
   virtual device::MediaTransferProtocolManager*
       media_transfer_protocol_manager() = 0;
 #endif
diff --git a/components/storage_monitor/storage_monitor_chromeos.cc b/components/storage_monitor/storage_monitor_chromeos.cc
index e8b55374..228cc440 100644
--- a/components/storage_monitor/storage_monitor_chromeos.cc
+++ b/components/storage_monitor/storage_monitor_chromeos.cc
@@ -13,7 +13,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/storage_monitor/media_storage_util.h"
-#include "components/storage_monitor/media_transfer_protocol_device_observer_linux.h"
+#include "components/storage_monitor/media_transfer_protocol_device_observer_chromeos.h"
 #include "components/storage_monitor/removable_device_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"
@@ -111,7 +111,7 @@
   }
 
   media_transfer_protocol_device_observer_.reset(
-      new MediaTransferProtocolDeviceObserverLinux(
+      new MediaTransferProtocolDeviceObserverChromeOS(
           receiver(), media_transfer_protocol_manager_.get()));
 }
 
diff --git a/components/storage_monitor/storage_monitor_chromeos.h b/components/storage_monitor/storage_monitor_chromeos.h
index 7b3386b..b427c220 100644
--- a/components/storage_monitor/storage_monitor_chromeos.h
+++ b/components/storage_monitor/storage_monitor_chromeos.h
@@ -26,7 +26,7 @@
 
 namespace storage_monitor {
 
-class MediaTransferProtocolDeviceObserverLinux;
+class MediaTransferProtocolDeviceObserverChromeOS;
 
 class StorageMonitorCros : public StorageMonitor,
                            public chromeos::disks::DiskMountManager::Observer {
@@ -86,7 +86,7 @@
 
   std::unique_ptr<device::MediaTransferProtocolManager>
       media_transfer_protocol_manager_;
-  std::unique_ptr<MediaTransferProtocolDeviceObserverLinux>
+  std::unique_ptr<MediaTransferProtocolDeviceObserverChromeOS>
       media_transfer_protocol_device_observer_;
 
   base::WeakPtrFactory<StorageMonitorCros> weak_ptr_factory_;
diff --git a/components/storage_monitor/storage_monitor_chromeos_unittest.cc b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
index b12b8f3..5ffb3f8 100644
--- a/components/storage_monitor/storage_monitor_chromeos_unittest.cc
+++ b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
@@ -19,7 +19,7 @@
 #include "components/storage_monitor/mock_removable_storage_observer.h"
 #include "components/storage_monitor/removable_device_constants.h"
 #include "components/storage_monitor/storage_info.h"
-#include "components/storage_monitor/test_media_transfer_protocol_manager_linux.h"
+#include "components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h"
 #include "components/storage_monitor/test_storage_monitor.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -68,7 +68,7 @@
 
   void Init() override {
     SetMediaTransferProtocolManagerForTest(
-        new TestMediaTransferProtocolManagerLinux());
+        new TestMediaTransferProtocolManagerChromeOS());
     StorageMonitorCros::Init();
   }
 
diff --git a/components/storage_monitor/storage_monitor_linux.cc b/components/storage_monitor/storage_monitor_linux.cc
index aba36bbd..4b3a01f 100644
--- a/components/storage_monitor/storage_monitor_linux.cc
+++ b/components/storage_monitor/storage_monitor_linux.cc
@@ -24,7 +24,6 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/storage_monitor/media_storage_util.h"
-#include "components/storage_monitor/media_transfer_protocol_device_observer_linux.h"
 #include "components/storage_monitor/removable_device_constants.h"
 #include "components/storage_monitor/storage_info.h"
 #include "components/storage_monitor/udev_util_linux.h"
@@ -264,16 +263,6 @@
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&StorageMonitorLinux::OnMtabWatcherCreated,
                  weak_ptr_factory_.GetWeakPtr()));
-
-  if (!media_transfer_protocol_manager_) {
-    media_transfer_protocol_manager_.reset(
-        device::MediaTransferProtocolManager::Initialize(
-            BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)));
-  }
-
-  media_transfer_protocol_device_observer_.reset(
-      new MediaTransferProtocolDeviceObserverLinux(
-          receiver(), media_transfer_protocol_manager_.get()));
 }
 
 bool StorageMonitorLinux::GetStorageInfoForPath(
@@ -282,14 +271,6 @@
   DCHECK(device_info);
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  // TODO(thestig) |media_transfer_protocol_device_observer_| should always be
-  // valid.
-  if (media_transfer_protocol_device_observer_ &&
-      media_transfer_protocol_device_observer_->GetStorageInfoForPath(
-          path, device_info)) {
-    return true;
-  }
-
   if (!path.IsAbsolute())
     return false;
 
@@ -305,22 +286,11 @@
   return true;
 }
 
-device::MediaTransferProtocolManager*
-StorageMonitorLinux::media_transfer_protocol_manager() {
-  return media_transfer_protocol_manager_.get();
-}
-
 void StorageMonitorLinux::SetGetDeviceInfoCallbackForTest(
     const GetDeviceInfoCallback& get_device_info_callback) {
   get_device_info_callback_ = get_device_info_callback;
 }
 
-void StorageMonitorLinux::SetMediaTransferProtocolManagerForTest(
-    device::MediaTransferProtocolManager* test_manager) {
-  DCHECK(!media_transfer_protocol_manager_);
-  media_transfer_protocol_manager_.reset(test_manager);
-}
-
 void StorageMonitorLinux::EjectDevice(
     const std::string& device_id,
     base::Callback<void(EjectStatus)> callback) {
@@ -330,10 +300,7 @@
     return;
   }
 
-  if (type == StorageInfo::MTP_OR_PTP) {
-    media_transfer_protocol_device_observer_->EjectDevice(device_id, callback);
-    return;
-  }
+  DCHECK_NE(type, StorageInfo::MTP_OR_PTP);
 
   // Find the mount point for the given device ID.
   base::FilePath path;
diff --git a/components/storage_monitor/storage_monitor_linux.h b/components/storage_monitor/storage_monitor_linux.h
index 05a59f7..a007bf9c 100644
--- a/components/storage_monitor/storage_monitor_linux.h
+++ b/components/storage_monitor/storage_monitor_linux.h
@@ -31,8 +31,6 @@
 
 namespace storage_monitor {
 
-class MediaTransferProtocolDeviceObserverLinux;
-
 class StorageMonitorLinux : public StorageMonitor,
                             public MtabWatcherLinux::Delegate {
  public:
@@ -54,9 +52,6 @@
   void SetGetDeviceInfoCallbackForTest(
       const GetDeviceInfoCallback& get_device_info_callback);
 
-  void SetMediaTransferProtocolManagerForTest(
-      device::MediaTransferProtocolManager* test_manager);
-
   // MtabWatcherLinux::Delegate implementation.
   void UpdateMtab(
       const MtabWatcherLinux::MountPointDeviceMap& new_mtab) override;
@@ -95,8 +90,6 @@
                              StorageInfo* device_info) const override;
   void EjectDevice(const std::string& device_id,
                    base::Callback<void(EjectStatus)> callback) override;
-  device::MediaTransferProtocolManager* media_transfer_protocol_manager()
-      override;
 
   // Called when the MtabWatcher has been created.
   void OnMtabWatcherCreated(MtabWatcherLinux* watcher);
@@ -130,11 +123,6 @@
   // points.
   MountPriorityMap mount_priority_map_;
 
-  std::unique_ptr<device::MediaTransferProtocolManager>
-      media_transfer_protocol_manager_;
-  std::unique_ptr<MediaTransferProtocolDeviceObserverLinux>
-      media_transfer_protocol_device_observer_;
-
   std::unique_ptr<MtabWatcherLinux, MtabWatcherLinuxDeleter> mtab_watcher_;
 
   base::WeakPtrFactory<StorageMonitorLinux> weak_ptr_factory_;
diff --git a/components/storage_monitor/storage_monitor_linux_unittest.cc b/components/storage_monitor/storage_monitor_linux_unittest.cc
index 8a609b6..92311f2c 100644
--- a/components/storage_monitor/storage_monitor_linux_unittest.cc
+++ b/components/storage_monitor/storage_monitor_linux_unittest.cc
@@ -25,7 +25,6 @@
 #include "components/storage_monitor/removable_device_constants.h"
 #include "components/storage_monitor/storage_info.h"
 #include "components/storage_monitor/storage_monitor.h"
-#include "components/storage_monitor/test_media_transfer_protocol_manager_linux.h"
 #include "components/storage_monitor/test_storage_monitor.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -126,8 +125,6 @@
  public:
   explicit TestStorageMonitorLinux(const base::FilePath& path)
       : StorageMonitorLinux(path) {
-    SetMediaTransferProtocolManagerForTest(
-        new TestMediaTransferProtocolManagerLinux());
     SetGetDeviceInfoCallbackForTest(base::Bind(&GetDeviceInfo));
   }
   ~TestStorageMonitorLinux() override {}
diff --git a/components/storage_monitor/test_media_transfer_protocol_manager_linux.cc b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
similarity index 64%
rename from components/storage_monitor/test_media_transfer_protocol_manager_linux.cc
rename to components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
index addfd872..dcef664 100644
--- a/components/storage_monitor/test_media_transfer_protocol_manager_linux.cc
+++ b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.cc
@@ -2,54 +2,55 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/storage_monitor/test_media_transfer_protocol_manager_linux.h"
+#include "components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h"
 
 #include "device/media_transfer_protocol/mtp_file_entry.pb.h"
 #include "device/media_transfer_protocol/mtp_storage_info.pb.h"
 
 namespace storage_monitor {
 
-TestMediaTransferProtocolManagerLinux::
-TestMediaTransferProtocolManagerLinux() {}
+TestMediaTransferProtocolManagerChromeOS::
+    TestMediaTransferProtocolManagerChromeOS() {}
 
-TestMediaTransferProtocolManagerLinux::
-~TestMediaTransferProtocolManagerLinux() {}
+TestMediaTransferProtocolManagerChromeOS::
+    ~TestMediaTransferProtocolManagerChromeOS() {}
 
-void TestMediaTransferProtocolManagerLinux::AddObserver(Observer* observer) {}
+void TestMediaTransferProtocolManagerChromeOS::AddObserver(Observer* observer) {
+}
 
-void TestMediaTransferProtocolManagerLinux::RemoveObserver(
+void TestMediaTransferProtocolManagerChromeOS::RemoveObserver(
     Observer* observer) {}
 
 const std::vector<std::string>
-TestMediaTransferProtocolManagerLinux::GetStorages() const {
-    return std::vector<std::string>();
+TestMediaTransferProtocolManagerChromeOS::GetStorages() const {
+  return std::vector<std::string>();
 }
-const MtpStorageInfo* TestMediaTransferProtocolManagerLinux::GetStorageInfo(
+const MtpStorageInfo* TestMediaTransferProtocolManagerChromeOS::GetStorageInfo(
     const std::string& storage_name) const {
   return NULL;
 }
 
-void TestMediaTransferProtocolManagerLinux::GetStorageInfoFromDevice(
+void TestMediaTransferProtocolManagerChromeOS::GetStorageInfoFromDevice(
     const std::string& storage_name,
     const GetStorageInfoFromDeviceCallback& callback) {
   MtpStorageInfo mtp_storage_info;
   callback.Run(mtp_storage_info, true /* error */);
 }
 
-void TestMediaTransferProtocolManagerLinux::OpenStorage(
+void TestMediaTransferProtocolManagerChromeOS::OpenStorage(
     const std::string& storage_name,
     const std::string& mode,
     const OpenStorageCallback& callback) {
   callback.Run("", true);
 }
 
-void TestMediaTransferProtocolManagerLinux::CloseStorage(
+void TestMediaTransferProtocolManagerChromeOS::CloseStorage(
     const std::string& storage_handle,
     const CloseStorageCallback& callback) {
   callback.Run(true);
 }
 
-void TestMediaTransferProtocolManagerLinux::CreateDirectory(
+void TestMediaTransferProtocolManagerChromeOS::CreateDirectory(
     const std::string& storage_handle,
     const uint32_t parent_id,
     const std::string& directory_name,
@@ -57,17 +58,16 @@
   callback.Run(true /* error */);
 }
 
-void TestMediaTransferProtocolManagerLinux::ReadDirectory(
+void TestMediaTransferProtocolManagerChromeOS::ReadDirectory(
     const std::string& storage_handle,
     const uint32_t file_id,
     const size_t max_size,
     const ReadDirectoryCallback& callback) {
-  callback.Run(std::vector<MtpFileEntry>(),
-               false /* no more entries*/,
+  callback.Run(std::vector<MtpFileEntry>(), false /* no more entries*/,
                true /* error */);
 }
 
-void TestMediaTransferProtocolManagerLinux::ReadFileChunk(
+void TestMediaTransferProtocolManagerChromeOS::ReadFileChunk(
     const std::string& storage_handle,
     uint32_t file_id,
     uint32_t offset,
@@ -76,14 +76,14 @@
   callback.Run(std::string(), true);
 }
 
-void TestMediaTransferProtocolManagerLinux::GetFileInfo(
+void TestMediaTransferProtocolManagerChromeOS::GetFileInfo(
     const std::string& storage_handle,
     uint32_t file_id,
     const GetFileInfoCallback& callback) {
   callback.Run(MtpFileEntry(), true);
 }
 
-void TestMediaTransferProtocolManagerLinux::RenameObject(
+void TestMediaTransferProtocolManagerChromeOS::RenameObject(
     const std::string& storage_handle,
     const uint32_t object_id,
     const std::string& new_name,
@@ -91,7 +91,7 @@
   callback.Run(true /* error */);
 }
 
-void TestMediaTransferProtocolManagerLinux::CopyFileFromLocal(
+void TestMediaTransferProtocolManagerChromeOS::CopyFileFromLocal(
     const std::string& storage_handle,
     const int source_file_descriptor,
     const uint32_t parent_id,
@@ -100,7 +100,7 @@
   callback.Run(true /* error */);
 }
 
-void TestMediaTransferProtocolManagerLinux::DeleteObject(
+void TestMediaTransferProtocolManagerChromeOS::DeleteObject(
     const std::string& storage_handle,
     const uint32_t object_id,
     const DeleteObjectCallback& callback) {
diff --git a/components/storage_monitor/test_media_transfer_protocol_manager_linux.h b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
similarity index 90%
rename from components/storage_monitor/test_media_transfer_protocol_manager_linux.h
rename to components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h
index c53b39c9..403e350f 100644
--- a/components/storage_monitor/test_media_transfer_protocol_manager_linux.h
+++ b/components/storage_monitor/test_media_transfer_protocol_manager_chromeos.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 COMPONENTS_STORAGE_MONITOR_TEST_MEDIA_TRANSFER_PROTOCOL_MANAGER_LINUX_H_
-#define COMPONENTS_STORAGE_MONITOR_TEST_MEDIA_TRANSFER_PROTOCOL_MANAGER_LINUX_H_
+#ifndef COMPONENTS_STORAGE_MONITOR_TEST_MEDIA_TRANSFER_PROTOCOL_MANAGER_CHROMEOS_H_
+#define COMPONENTS_STORAGE_MONITOR_TEST_MEDIA_TRANSFER_PROTOCOL_MANAGER_CHROMEOS_H_
 
 #include <stddef.h>
 #include <stdint.h>
@@ -14,11 +14,11 @@
 namespace storage_monitor {
 
 // A dummy MediaTransferProtocolManager implementation.
-class TestMediaTransferProtocolManagerLinux
+class TestMediaTransferProtocolManagerChromeOS
     : public device::MediaTransferProtocolManager {
  public:
-  TestMediaTransferProtocolManagerLinux();
-  ~TestMediaTransferProtocolManagerLinux() override;
+  TestMediaTransferProtocolManagerChromeOS();
+  ~TestMediaTransferProtocolManagerChromeOS() override;
 
  private:
   // device::MediaTransferProtocolManager implementation.
@@ -64,9 +64,9 @@
                     const uint32_t object_id,
                     const DeleteObjectCallback& callback) override;
 
-  DISALLOW_COPY_AND_ASSIGN(TestMediaTransferProtocolManagerLinux);
+  DISALLOW_COPY_AND_ASSIGN(TestMediaTransferProtocolManagerChromeOS);
 };
 
 }  // namespace storage_monitor
 
-#endif  // COMPONENTS_STORAGE_MONITOR_TEST_MEDIA_TRANSFER_PROTOCOL_MANAGER_LINUX_H_
+#endif  // COMPONENTS_STORAGE_MONITOR_TEST_MEDIA_TRANSFER_PROTOCOL_MANAGER_CHROMEOS_H_
diff --git a/components/storage_monitor/test_storage_monitor.cc b/components/storage_monitor/test_storage_monitor.cc
index 3277f6f..3ab33bb0 100644
--- a/components/storage_monitor/test_storage_monitor.cc
+++ b/components/storage_monitor/test_storage_monitor.cc
@@ -11,8 +11,8 @@
 #include "build/build_config.h"
 #include "components/storage_monitor/storage_info.h"
 
-#if defined(OS_LINUX)
-#include "components/storage_monitor/test_media_transfer_protocol_manager_linux.h"
+#if defined(OS_CHROMEOS)
+#include "components/storage_monitor/test_media_transfer_protocol_manager_chromeos.h"
 #include "device/media_transfer_protocol/media_transfer_protocol_manager.h"  // nogncheck
 #endif
 
@@ -21,9 +21,9 @@
 TestStorageMonitor::TestStorageMonitor()
     : StorageMonitor(),
       init_called_(false) {
-#if defined(OS_LINUX)
+#if defined(OS_CHROMEOS)
   media_transfer_protocol_manager_.reset(
-      new TestMediaTransferProtocolManagerLinux());
+      new TestMediaTransferProtocolManagerChromeOS());
 #endif
 }
 
@@ -115,7 +115,7 @@
 }
 #endif
 
-#if defined(OS_LINUX)
+#if defined(OS_CHROMEOS)
 device::MediaTransferProtocolManager*
 TestStorageMonitor::media_transfer_protocol_manager() {
   return media_transfer_protocol_manager_.get();
diff --git a/components/storage_monitor/test_storage_monitor.h b/components/storage_monitor/test_storage_monitor.h
index ec29b8c..df3c57a4 100644
--- a/components/storage_monitor/test_storage_monitor.h
+++ b/components/storage_monitor/test_storage_monitor.h
@@ -46,7 +46,7 @@
       base::string16* storage_object_id) const override;
 #endif
 
-#if defined(OS_LINUX)
+#if defined(OS_CHROMEOS)
   device::MediaTransferProtocolManager* media_transfer_protocol_manager()
       override;
 #endif
@@ -73,7 +73,7 @@
   // Paths considered for testing purposes to be on removable storage.
   std::vector<base::FilePath> removable_paths_;
 
-#if defined(OS_LINUX)
+#if defined(OS_CHROMEOS)
   std::unique_ptr<device::MediaTransferProtocolManager>
       media_transfer_protocol_manager_;
 #endif
diff --git a/components/translate/core/language_detection/language_detection_util.cc b/components/translate/core/language_detection/language_detection_util.cc
index d4d1bfd3..7028461 100644
--- a/components/translate/core/language_detection/language_detection_util.cc
+++ b/components/translate/core/language_detection/language_detection_util.cc
@@ -197,7 +197,14 @@
     *is_cld_reliable = prediction_reliable;
   }
 
+  // Ignore unreliable, "unknown", and xx-Latn predictions that are currently
+  // not supported.
   if (prediction_reliable &&
+      predicted_language != "bg-Latn" &&
+      predicted_language != "el-Latn" &&
+      predicted_language != "ja-Latn" &&
+      predicted_language != "ru-Latn" &&
+      predicted_language != "zh-Latn" &&
       predicted_language !=
           chrome_lang_id::NNetLanguageIdentifier::kUnknown) {
     // CLD3 returns 'zh' for Chinese but Translate doesn't accept it. Thus,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index cbc1706..eefa129 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -435,6 +435,8 @@
     "devtools/protocol/storage_handler.h",
     "devtools/protocol/system_info_handler.cc",
     "devtools/protocol/system_info_handler.h",
+    "devtools/protocol/target_handler.cc",
+    "devtools/protocol/target_handler.h",
     "devtools/protocol/tethering_handler.cc",
     "devtools/protocol/tethering_handler.h",
     "devtools/protocol/tracing_handler.cc",
diff --git a/content/browser/devtools/protocol/schema_handler.cc b/content/browser/devtools/protocol/schema_handler.cc
index 608e028..93d3e1f 100644
--- a/content/browser/devtools/protocol/schema_handler.cc
+++ b/content/browser/devtools/protocol/schema_handler.cc
@@ -18,6 +18,7 @@
 
 Response SchemaHandler::GetDomains(
     std::vector<scoped_refptr<Domain>>* domains) {
+  // TODO(kozyatisnkiy): get this from the target instead of hardcoding a list.
   static const char kVersion[] = "1.2";
   static const char* kDomains[] = {
     "Inspector", "Memory", "Page", "Rendering", "Emulation", "Security",
@@ -25,7 +26,7 @@
     "ApplicationCache", "DOM", "IO", "DOMDebugger", "Worker", "ServiceWorker",
     "Input", "LayerTree", "DeviceOrientation", "Tracing", "Animation",
     "Accessibility", "Storage", "Log", "Browser", "Runtime", "Debugger",
-    "Profiler", "HeapProfiler", "Schema"
+    "Profiler", "HeapProfiler", "Schema", "Target"
   };
   for (size_t i = 0; i < arraysize(kDomains); ++i) {
     domains->push_back(Domain::Create()
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc
index a5de8d57..c34d15a1 100644
--- a/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -32,11 +32,6 @@
 #include "content/public/common/push_messaging_status.h"
 #include "url/gurl.h"
 
-// Windows headers will redefine SendMessage.
-#ifdef SendMessage
-#undef SendMessage
-#endif
-
 namespace content {
 namespace devtools {
 namespace service_worker {
@@ -45,9 +40,6 @@
 
 namespace {
 
-using ScopeAgentsMap =
-    std::map<GURL, std::unique_ptr<ServiceWorkerDevToolsAgentHost::List>>;
-
 void ResultNoOp(bool success) {
 }
 
@@ -136,6 +128,13 @@
           ->set_script_response_time(
                 version_info.script_response_time.ToDoubleT())
           ->set_controlled_clients(clients));
+  scoped_refptr<DevToolsAgentHostImpl> host(
+      ServiceWorkerDevToolsManager::GetInstance()
+          ->GetDevToolsAgentHostForWorker(
+              version_info.process_id,
+              version_info.devtools_agent_route_id));
+  if (host)
+    version->set_target_id(host->GetId());
   return version;
 }
 
@@ -151,69 +150,6 @@
   return registration;
 }
 
-void GetMatchingHostsByScopeMap(
-    const ServiceWorkerDevToolsAgentHost::List& agent_hosts,
-    const std::set<GURL>& urls,
-    ScopeAgentsMap* scope_agents_map) {
-  std::set<base::StringPiece> host_name_set;
-  for (const GURL& url : urls)
-    host_name_set.insert(url.host_piece());
-  for (const auto& host : agent_hosts) {
-    if (host_name_set.find(host->scope().host_piece()) == host_name_set.end())
-      continue;
-    const auto& it = scope_agents_map->find(host->scope());
-    if (it == scope_agents_map->end()) {
-      std::unique_ptr<ServiceWorkerDevToolsAgentHost::List> new_list(
-          new ServiceWorkerDevToolsAgentHost::List());
-      new_list->push_back(host);
-      (*scope_agents_map)[host->scope()] = std::move(new_list);
-    } else {
-      it->second->push_back(host);
-    }
-  }
-}
-
-void AddEligibleHosts(const ServiceWorkerDevToolsAgentHost::List& list,
-                      ServiceWorkerDevToolsAgentHost::Map* result) {
-  base::Time last_installed_time;
-  base::Time last_doomed_time;
-  for (const auto& host : list) {
-    if (host->version_installed_time() > last_installed_time)
-      last_installed_time = host->version_installed_time();
-    if (host->version_doomed_time() > last_doomed_time)
-      last_doomed_time = host->version_doomed_time();
-  }
-  for (const auto& host : list) {
-    // We don't attech old redundant Service Workers when there is newer
-    // installed Service Worker.
-    if (host->version_doomed_time().is_null() ||
-        (last_installed_time < last_doomed_time &&
-         last_doomed_time == host->version_doomed_time())) {
-      (*result)[host->GetId()] = host;
-    }
-  }
-}
-
-ServiceWorkerDevToolsAgentHost::Map GetMatchingServiceWorkers(
-    BrowserContext* browser_context,
-    const std::set<GURL>& urls) {
-  ServiceWorkerDevToolsAgentHost::Map result;
-  if (!browser_context)
-    return result;
-
-  ServiceWorkerDevToolsAgentHost::List agent_hosts;
-  ServiceWorkerDevToolsManager::GetInstance()
-      ->AddAllAgentHostsForBrowserContext(browser_context, &agent_hosts);
-
-  ScopeAgentsMap scope_agents_map;
-  GetMatchingHostsByScopeMap(agent_hosts, urls, &scope_agents_map);
-
-  for (const auto& it : scope_agents_map)
-    AddEligibleHosts(*it.second.get(), &result);
-
-  return result;
-}
-
 void StopServiceWorkerOnIO(scoped_refptr<ServiceWorkerContextWrapper> context,
                            int64_t version_id) {
   if (content::ServiceWorkerVersion* version =
@@ -305,35 +241,6 @@
   client_.swap(client);
 }
 
-void ServiceWorkerHandler::UpdateHosts() {
-  if (!enabled_)
-    return;
-
-  urls_.clear();
-  BrowserContext* browser_context = nullptr;
-  if (render_frame_host_) {
-    for (FrameTreeNode* node :
-         render_frame_host_->frame_tree_node()->frame_tree()->Nodes())
-      urls_.insert(node->current_url());
-
-    browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
-  }
-
-  ServiceWorkerDevToolsAgentHost::Map old_hosts = attached_hosts_;
-  ServiceWorkerDevToolsAgentHost::Map new_hosts =
-      GetMatchingServiceWorkers(browser_context, urls_);
-
-  for (const auto& pair : old_hosts) {
-    if (new_hosts.find(pair.first) == new_hosts.end())
-      ReportWorkerTerminated(pair.second.get());
-  }
-
-  for (const auto& pair : new_hosts) {
-    if (old_hosts.find(pair.first) == old_hosts.end())
-      ReportWorkerCreated(pair.second.get());
-  }
-}
-
 void ServiceWorkerHandler::Detached() {
   Disable();
 }
@@ -345,8 +252,6 @@
     return Response::InternalError("Could not connect to the context");
   enabled_ = true;
 
-  ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this);
-
   context_watcher_ = new ServiceWorkerContextWatcher(
       context_, base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated,
                            weak_factory_.GetWeakPtr()),
@@ -356,7 +261,6 @@
                  weak_factory_.GetWeakPtr()));
   context_watcher_->Start();
 
-  UpdateHosts();
   return Response::OK();
 }
 
@@ -365,36 +269,13 @@
     return Response::OK();
   enabled_ = false;
 
-  ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this);
   ClearForceUpdate();
-  for (const auto& pair : attached_hosts_)
-    pair.second->DetachClient(this);
-  attached_hosts_.clear();
   DCHECK(context_watcher_);
   context_watcher_->Stop();
   context_watcher_ = nullptr;
   return Response::OK();
 }
 
-Response ServiceWorkerHandler::SendMessage(
-    const std::string& worker_id,
-    const std::string& message) {
-  auto it = attached_hosts_.find(worker_id);
-  if (it == attached_hosts_.end())
-    return Response::InternalError("Not connected to the worker");
-  it->second->DispatchProtocolMessage(message);
-  return Response::OK();
-}
-
-Response ServiceWorkerHandler::Stop(
-    const std::string& worker_id) {
-  auto it = attached_hosts_.find(worker_id);
-  if (it == attached_hosts_.end())
-    return Response::InternalError("Not connected to the worker");
-  it->second->UnregisterWorker();
-  return Response::OK();
-}
-
 Response ServiceWorkerHandler::Unregister(const std::string& scope_url) {
   if (!enabled_)
     return Response::OK();
@@ -516,31 +397,6 @@
   return Response::OK();
 }
 
-Response ServiceWorkerHandler::GetTargetInfo(
-    const std::string& target_id,
-    scoped_refptr<TargetInfo>* target_info) {
-  scoped_refptr<DevToolsAgentHost> agent_host(
-      DevToolsAgentHost::GetForId(target_id));
-  if (!agent_host)
-    return Response::InvalidParams("targetId");
-  *target_info =
-      TargetInfo::Create()
-          ->set_id(agent_host->GetId())
-          ->set_type(agent_host->GetType())
-          ->set_title(agent_host->GetTitle())
-          ->set_url(agent_host->GetURL().spec());
-  return Response::OK();
-}
-
-Response ServiceWorkerHandler::ActivateTarget(const std::string& target_id) {
-  scoped_refptr<DevToolsAgentHost> agent_host(
-      DevToolsAgentHost::GetForId(target_id));
-  if (!agent_host)
-    return Response::InvalidParams("targetId");
-  agent_host->Activate();
-  return Response::OK();
-}
-
 void ServiceWorkerHandler::OpenNewDevToolsWindow(int process_id,
                                                  int devtools_agent_route_id) {
   scoped_refptr<DevToolsAgentHostImpl> agent_host(
@@ -588,89 +444,6 @@
               ->set_column_number(info.column_number)));
 }
 
-void ServiceWorkerHandler::DispatchProtocolMessage(
-    DevToolsAgentHost* host,
-    const std::string& message) {
-
-  auto it = attached_hosts_.find(host->GetId());
-  if (it == attached_hosts_.end())
-    return;  // Already disconnected.
-
-  client_->DispatchMessage(
-      DispatchMessageParams::Create()->
-          set_worker_id(host->GetId())->
-          set_message(message));
-}
-
-void ServiceWorkerHandler::AgentHostClosed(
-    DevToolsAgentHost* host,
-    bool replaced_with_another_client) {
-  client_->WorkerTerminated(WorkerTerminatedParams::Create()->
-      set_worker_id(host->GetId()));
-  attached_hosts_.erase(host->GetId());
-}
-
-void ServiceWorkerHandler::WorkerCreated(
-    ServiceWorkerDevToolsAgentHost* host) {
-  BrowserContext* browser_context = nullptr;
-  if (render_frame_host_)
-    browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
-
-  auto hosts = GetMatchingServiceWorkers(browser_context, urls_);
-  if (hosts.find(host->GetId()) != hosts.end() && !host->IsAttached() &&
-      !host->IsPausedForDebugOnStart())
-    host->PauseForDebugOnStart();
-}
-
-void ServiceWorkerHandler::WorkerReadyForInspection(
-    ServiceWorkerDevToolsAgentHost* host) {
-  if (ServiceWorkerDevToolsManager::GetInstance()
-          ->debug_service_worker_on_start()) {
-    // When debug_service_worker_on_start is true, a new DevTools window will
-    // be opend in ServiceWorkerDevToolsManager::WorkerReadyForInspection.
-    return;
-  }
-  UpdateHosts();
-}
-
-void ServiceWorkerHandler::WorkerVersionInstalled(
-    ServiceWorkerDevToolsAgentHost* host) {
-  UpdateHosts();
-}
-void ServiceWorkerHandler::WorkerVersionDoomed(
-    ServiceWorkerDevToolsAgentHost* host) {
-  UpdateHosts();
-}
-
-void ServiceWorkerHandler::WorkerDestroyed(
-    ServiceWorkerDevToolsAgentHost* host) {
-  UpdateHosts();
-}
-
-void ServiceWorkerHandler::ReportWorkerCreated(
-    ServiceWorkerDevToolsAgentHost* host) {
-  if (host->IsAttached())
-    return;
-  attached_hosts_[host->GetId()] = host;
-  host->AttachClient(this);
-  client_->WorkerCreated(WorkerCreatedParams::Create()
-                             ->set_worker_id(host->GetId())
-                             ->set_url(host->GetURL().spec())
-                             ->set_version_id(base::Int64ToString(
-                                 host->service_worker_version_id())));
-}
-
-void ServiceWorkerHandler::ReportWorkerTerminated(
-    ServiceWorkerDevToolsAgentHost* host) {
-  auto it = attached_hosts_.find(host->GetId());
-  if (it == attached_hosts_.end())
-    return;
-  host->DetachClient(this);
-  client_->WorkerTerminated(WorkerTerminatedParams::Create()->
-      set_worker_id(host->GetId()));
-  attached_hosts_.erase(it);
-}
-
 void ServiceWorkerHandler::ClearForceUpdate() {
   if (context_)
     context_->SetForceUpdateOnPageLoad(false);
diff --git a/content/browser/devtools/protocol/service_worker_handler.h b/content/browser/devtools/protocol/service_worker_handler.h
index ac7d460c..892a8c7 100644
--- a/content/browser/devtools/protocol/service_worker_handler.h
+++ b/content/browser/devtools/protocol/service_worker_handler.h
@@ -33,25 +33,20 @@
 namespace devtools {
 namespace service_worker {
 
-class ServiceWorkerHandler : public DevToolsAgentHostClient,
-                             public ServiceWorkerDevToolsManager::Observer {
+class ServiceWorkerHandler {
  public:
   typedef DevToolsProtocolClient::Response Response;
 
   ServiceWorkerHandler();
-  ~ServiceWorkerHandler() override;
+  ~ServiceWorkerHandler();
 
   void SetRenderFrameHost(RenderFrameHostImpl* render_frame_host);
   void SetClient(std::unique_ptr<Client> client);
-  void UpdateHosts();
   void Detached();
 
   // Protocol 'service worker' domain implementation.
   Response Enable();
   Response Disable();
-  Response SendMessage(const std::string& worker_id,
-                       const std::string& message);
-  Response Stop(const std::string& worker_id);
   Response Unregister(const std::string& scope_url);
   Response StartWorker(const std::string& scope_url);
   Response SkipWaiting(const std::string& scope_url);
@@ -66,27 +61,8 @@
                              const std::string& registration_id,
                              const std::string& tag,
                              bool last_chance);
-  Response GetTargetInfo(const std::string& target_id,
-                         scoped_refptr<TargetInfo>* target_info);
-  Response ActivateTarget(const std::string& target_id);
-
-  // WorkerDevToolsManager::Observer implementation.
-  void WorkerCreated(ServiceWorkerDevToolsAgentHost* host) override;
-  void WorkerReadyForInspection(ServiceWorkerDevToolsAgentHost* host) override;
-  void WorkerVersionInstalled(ServiceWorkerDevToolsAgentHost* host) override;
-  void WorkerVersionDoomed(ServiceWorkerDevToolsAgentHost* host) override;
-  void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) override;
 
  private:
-  // DevToolsAgentHostClient overrides.
-  void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
-                               const std::string& message) override;
-  void AgentHostClosed(DevToolsAgentHost* agent_host,
-                       bool replaced_with_another_client) override;
-
-  void ReportWorkerCreated(ServiceWorkerDevToolsAgentHost* host);
-  void ReportWorkerTerminated(ServiceWorkerDevToolsAgentHost* host);
-
   void OnWorkerRegistrationUpdated(
       const std::vector<ServiceWorkerRegistrationInfo>& registrations);
   void OnWorkerVersionUpdated(
@@ -100,9 +76,7 @@
 
   scoped_refptr<ServiceWorkerContextWrapper> context_;
   std::unique_ptr<Client> client_;
-  ServiceWorkerDevToolsAgentHost::Map attached_hosts_;
   bool enabled_;
-  std::set<GURL> urls_;
   scoped_refptr<ServiceWorkerContextWatcher> context_watcher_;
   RenderFrameHostImpl* render_frame_host_;
 
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc
new file mode 100644
index 0000000..ffd83ae
--- /dev/null
+++ b/content/browser/devtools/protocol/target_handler.cc
@@ -0,0 +1,291 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/devtools/protocol/target_handler.h"
+
+#include "content/browser/devtools/service_worker_devtools_agent_host.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+
+namespace content {
+namespace devtools {
+namespace target {
+
+using Response = DevToolsProtocolClient::Response;
+
+namespace {
+
+using ScopeAgentsMap =
+    std::map<GURL, std::unique_ptr<ServiceWorkerDevToolsAgentHost::List>>;
+
+void GetMatchingHostsByScopeMap(
+    const ServiceWorkerDevToolsAgentHost::List& agent_hosts,
+    const std::set<GURL>& urls,
+    ScopeAgentsMap* scope_agents_map) {
+  std::set<base::StringPiece> host_name_set;
+  for (const GURL& url : urls)
+    host_name_set.insert(url.host_piece());
+  for (const auto& host : agent_hosts) {
+    if (host_name_set.find(host->scope().host_piece()) == host_name_set.end())
+      continue;
+    const auto& it = scope_agents_map->find(host->scope());
+    if (it == scope_agents_map->end()) {
+      std::unique_ptr<ServiceWorkerDevToolsAgentHost::List> new_list(
+          new ServiceWorkerDevToolsAgentHost::List());
+      new_list->push_back(host);
+      (*scope_agents_map)[host->scope()] = std::move(new_list);
+    } else {
+      it->second->push_back(host);
+    }
+  }
+}
+
+void AddEligibleHosts(const ServiceWorkerDevToolsAgentHost::List& list,
+                      ServiceWorkerDevToolsAgentHost::Map* result) {
+  base::Time last_installed_time;
+  base::Time last_doomed_time;
+  for (const auto& host : list) {
+    if (host->version_installed_time() > last_installed_time)
+      last_installed_time = host->version_installed_time();
+    if (host->version_doomed_time() > last_doomed_time)
+      last_doomed_time = host->version_doomed_time();
+  }
+  for (const auto& host : list) {
+    // We don't attech old redundant Service Workers when there is newer
+    // installed Service Worker.
+    if (host->version_doomed_time().is_null() ||
+        (last_installed_time < last_doomed_time &&
+         last_doomed_time == host->version_doomed_time())) {
+      (*result)[host->GetId()] = host;
+    }
+  }
+}
+
+ServiceWorkerDevToolsAgentHost::Map GetMatchingServiceWorkers(
+    BrowserContext* browser_context,
+    const std::set<GURL>& urls) {
+  ServiceWorkerDevToolsAgentHost::Map result;
+  if (!browser_context)
+    return result;
+
+  ServiceWorkerDevToolsAgentHost::List agent_hosts;
+  ServiceWorkerDevToolsManager::GetInstance()
+      ->AddAllAgentHostsForBrowserContext(browser_context, &agent_hosts);
+
+  ScopeAgentsMap scope_agents_map;
+  GetMatchingHostsByScopeMap(agent_hosts, urls, &scope_agents_map);
+
+  for (const auto& it : scope_agents_map)
+    AddEligibleHosts(*it.second.get(), &result);
+
+  return result;
+}
+
+}  // namespace
+
+TargetHandler::TargetHandler()
+    : enabled_(false),
+      render_frame_host_(nullptr) {
+}
+
+TargetHandler::~TargetHandler() {
+  Disable();
+}
+
+void TargetHandler::SetRenderFrameHost(RenderFrameHostImpl* render_frame_host) {
+  render_frame_host_ = render_frame_host;
+}
+
+void TargetHandler::SetClient(std::unique_ptr<Client> client) {
+  client_.swap(client);
+}
+
+void TargetHandler::Detached() {
+  Disable();
+}
+
+void TargetHandler::UpdateServiceWorkers() {
+  if (!enabled_)
+    return;
+
+  frame_urls_.clear();
+  BrowserContext* browser_context = nullptr;
+  if (render_frame_host_) {
+    // TODO(dgozman): do not traverse inside cross-process subframes.
+    for (FrameTreeNode* node :
+         render_frame_host_->frame_tree_node()->frame_tree()->Nodes()) {
+      frame_urls_.insert(node->current_url());
+    }
+    browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
+  }
+
+  std::map<std::string, scoped_refptr<DevToolsAgentHost>> old_hosts =
+      attached_hosts_;
+  ServiceWorkerDevToolsAgentHost::Map new_hosts =
+      GetMatchingServiceWorkers(browser_context, frame_urls_);
+
+  for (const auto& pair : old_hosts) {
+    if (pair.second->GetType() == DevToolsAgentHost::kTypeServiceWorker &&
+        new_hosts.find(pair.first) == new_hosts.end()) {
+      DetachFromTargetInternal(pair.second.get());
+    }
+  }
+
+  for (const auto& pair : new_hosts) {
+    if (old_hosts.find(pair.first) == old_hosts.end())
+      AttachToTargetInternal(pair.second.get(), true);
+  }
+}
+
+void TargetHandler::AttachToTargetInternal(
+    DevToolsAgentHost* host, bool waiting_for_debugger) {
+  if (host->IsAttached())
+    return;
+  attached_hosts_[host->GetId()] = host;
+  host->AttachClient(this);
+  client_->TargetCreated(TargetCreatedParams::Create()
+      ->set_target_id(host->GetId())
+      ->set_url(host->GetURL().spec())
+      ->set_type(host->GetType())
+      ->set_waiting_for_debugger(waiting_for_debugger));
+}
+
+void TargetHandler::DetachFromTargetInternal(DevToolsAgentHost* host) {
+  auto it = attached_hosts_.find(host->GetId());
+  if (it == attached_hosts_.end())
+    return;
+  host->DetachClient(this);
+  client_->TargetRemoved(TargetRemovedParams::Create()->
+      set_target_id(host->GetId()));
+  attached_hosts_.erase(it);
+}
+
+// ----------------- Protocol ----------------------
+
+Response TargetHandler::Enable() {
+  if (enabled_)
+    return Response::OK();
+  enabled_ = true;
+  ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this);
+  UpdateServiceWorkers();
+  return Response::OK();
+}
+
+Response TargetHandler::Disable() {
+  if (!enabled_)
+    return Response::OK();
+  enabled_ = false;
+  ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this);
+  for (const auto& pair : attached_hosts_)
+    pair.second->DetachClient(this);
+  attached_hosts_.clear();
+  return Response::OK();
+}
+
+Response TargetHandler::SetWaitForDebuggerOnStart(bool value) {
+  // TODO(dgozman): implement this.
+  return Response::OK();
+}
+
+Response TargetHandler::SendMessageToTarget(
+    const std::string& target_id,
+    const std::string& message) {
+  auto it = attached_hosts_.find(target_id);
+  if (it == attached_hosts_.end())
+    return Response::InternalError("Not attached to the target");
+  it->second->DispatchProtocolMessage(this, message);
+  return Response::OK();
+}
+
+Response TargetHandler::GetTargetInfo(
+    const std::string& target_id,
+    scoped_refptr<TargetInfo>* target_info) {
+  scoped_refptr<DevToolsAgentHost> agent_host(
+      DevToolsAgentHost::GetForId(target_id));
+  if (!agent_host)
+    return Response::InvalidParams("No target with such id");
+  *target_info =TargetInfo::Create()
+      ->set_target_id(agent_host->GetId())
+      ->set_type(agent_host->GetType())
+      ->set_title(agent_host->GetTitle())
+      ->set_url(agent_host->GetURL().spec());
+  return Response::OK();
+}
+
+Response TargetHandler::ActivateTarget(const std::string& target_id) {
+  scoped_refptr<DevToolsAgentHost> agent_host(
+      DevToolsAgentHost::GetForId(target_id));
+  if (!agent_host)
+    return Response::InvalidParams("No target with such id");
+  agent_host->Activate();
+  return Response::OK();
+}
+
+// ---------------- DevToolsAgentHostClient ----------------
+
+void TargetHandler::DispatchProtocolMessage(
+    DevToolsAgentHost* host,
+    const std::string& message) {
+  auto it = attached_hosts_.find(host->GetId());
+  if (it == attached_hosts_.end())
+    return;  // Already disconnected.
+
+  client_->ReceivedMessageFromTarget(
+      ReceivedMessageFromTargetParams::Create()->
+          set_target_id(host->GetId())->
+          set_message(message));
+}
+
+void TargetHandler::AgentHostClosed(
+    DevToolsAgentHost* host,
+    bool replaced_with_another_client) {
+  client_->TargetRemoved(TargetRemovedParams::Create()->
+      set_target_id(host->GetId()));
+  attached_hosts_.erase(host->GetId());
+}
+
+// -------- ServiceWorkerDevToolsManager::Observer ----------
+
+void TargetHandler::WorkerCreated(
+    ServiceWorkerDevToolsAgentHost* host) {
+  BrowserContext* browser_context = nullptr;
+  if (render_frame_host_)
+    browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
+  auto hosts = GetMatchingServiceWorkers(browser_context, frame_urls_);
+  if (hosts.find(host->GetId()) != hosts.end() && !host->IsAttached() &&
+      !host->IsPausedForDebugOnStart()) {
+    host->PauseForDebugOnStart();
+  }
+}
+
+void TargetHandler::WorkerReadyForInspection(
+    ServiceWorkerDevToolsAgentHost* host) {
+  if (ServiceWorkerDevToolsManager::GetInstance()
+          ->debug_service_worker_on_start()) {
+    // When debug_service_worker_on_start is true, a new DevTools window will
+    // be opened in ServiceWorkerDevToolsManager::WorkerReadyForInspection.
+    return;
+  }
+  UpdateServiceWorkers();
+}
+
+void TargetHandler::WorkerVersionInstalled(
+    ServiceWorkerDevToolsAgentHost* host) {
+  UpdateServiceWorkers();
+}
+
+void TargetHandler::WorkerVersionDoomed(
+    ServiceWorkerDevToolsAgentHost* host) {
+  UpdateServiceWorkers();
+}
+
+void TargetHandler::WorkerDestroyed(
+    ServiceWorkerDevToolsAgentHost* host) {
+  UpdateServiceWorkers();
+}
+
+}  // namespace target
+}  // namespace devtools
+}  // namespace content
diff --git a/content/browser/devtools/protocol/target_handler.h b/content/browser/devtools/protocol/target_handler.h
new file mode 100644
index 0000000..0f73e5f
--- /dev/null
+++ b/content/browser/devtools/protocol/target_handler.h
@@ -0,0 +1,77 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_H_
+#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_H_
+
+#include <map>
+#include <set>
+
+#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/browser/devtools/service_worker_devtools_manager.h"
+#include "content/public/browser/devtools_agent_host_client.h"
+
+namespace content {
+
+class RenderFrameHostImpl;
+
+namespace devtools {
+namespace target {
+
+class TargetHandler : public DevToolsAgentHostClient,
+                      public ServiceWorkerDevToolsManager::Observer {
+ public:
+  using Response = DevToolsProtocolClient::Response;
+
+  TargetHandler();
+  ~TargetHandler() override;
+
+  void SetRenderFrameHost(RenderFrameHostImpl* render_frame_host);
+  void SetClient(std::unique_ptr<Client> client);
+  void Detached();
+
+  void UpdateServiceWorkers();
+
+  // Domain implementation.
+  Response Enable();
+  Response Disable();
+  Response SetWaitForDebuggerOnStart(bool value);
+  Response SendMessageToTarget(const std::string& target_id,
+                               const std::string& message);
+  Response GetTargetInfo(const std::string& target_id,
+                         scoped_refptr<TargetInfo>* target_info);
+  Response ActivateTarget(const std::string& target_id);
+
+ private:
+  void AttachToTargetInternal(DevToolsAgentHost* host,
+                              bool waiting_for_debugger);
+  void DetachFromTargetInternal(DevToolsAgentHost* host);
+
+  // ServiceWorkerDevToolsManager::Observer implementation.
+  void WorkerCreated(ServiceWorkerDevToolsAgentHost* host) override;
+  void WorkerReadyForInspection(ServiceWorkerDevToolsAgentHost* host) override;
+  void WorkerVersionInstalled(ServiceWorkerDevToolsAgentHost* host) override;
+  void WorkerVersionDoomed(ServiceWorkerDevToolsAgentHost* host) override;
+  void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) override;
+
+  // DevToolsAgentHostClient implementation.
+  void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
+                               const std::string& message) override;
+  void AgentHostClosed(DevToolsAgentHost* agent_host,
+                       bool replaced_with_another_client) override;
+
+  std::unique_ptr<Client> client_;
+  bool enabled_;
+  RenderFrameHostImpl* render_frame_host_;
+  std::map<std::string, scoped_refptr<DevToolsAgentHost>> attached_hosts_;
+  std::set<GURL> frame_urls_;
+
+  DISALLOW_COPY_AND_ASSIGN(TargetHandler);
+};
+
+}  // namespace target
+}  // namespace devtools
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_TARGET_HANDLER_H_
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
index 786472c..9a85982 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -29,6 +29,7 @@
 #include "content/browser/devtools/protocol/security_handler.h"
 #include "content/browser/devtools/protocol/service_worker_handler.h"
 #include "content/browser/devtools/protocol/storage_handler.h"
+#include "content/browser/devtools/protocol/target_handler.h"
 #include "content/browser/devtools/protocol/tracing_handler.h"
 #include "content/browser/frame_host/navigation_handle_impl.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
@@ -385,6 +386,7 @@
       service_worker_handler_(
           new devtools::service_worker::ServiceWorkerHandler()),
       storage_handler_(new devtools::storage::StorageHandler()),
+      target_handler_(new devtools::target::TargetHandler()),
       tracing_handler_(new devtools::tracing::TracingHandler(
           devtools::tracing::TracingHandler::Renderer,
           host->GetFrameTreeNodeId(),
@@ -405,6 +407,7 @@
   dispatcher->SetSchemaHandler(schema_handler_.get());
   dispatcher->SetServiceWorkerHandler(service_worker_handler_.get());
   dispatcher->SetStorageHandler(storage_handler_.get());
+  dispatcher->SetTargetHandler(target_handler_.get());
   dispatcher->SetTracingHandler(tracing_handler_.get());
 
   if (!host->GetParent()) {
@@ -544,6 +547,7 @@
   if (page_handler_)
     page_handler_->Detached();
   service_worker_handler_->Detached();
+  target_handler_->Detached();
   tracing_handler_->Detached();
   frame_trace_recorder_.reset();
   in_navigation_protocol_message_buffer_.clear();
@@ -609,7 +613,7 @@
   DispatchBufferedProtocolMessagesIfNecessary();
 
   if (navigation_handle->HasCommitted())
-    service_worker_handler_->UpdateHosts();
+    target_handler_->UpdateServiceWorkers();
 }
 
 void RenderFrameDevToolsAgentHost::AboutToNavigateRenderFrame(
@@ -776,7 +780,7 @@
     return;
   if (pending_ && pending_->host() == render_frame_host)
     CommitPending();
-  service_worker_handler_->UpdateHosts();
+  target_handler_->UpdateServiceWorkers();
 }
 
 void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
@@ -831,6 +835,7 @@
     security_handler_->SetRenderFrameHost(host);
   if (storage_handler_)
     storage_handler_->SetRenderFrameHost(host);
+  target_handler_->SetRenderFrameHost(host);
 }
 
 void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.h b/content/browser/devtools/render_frame_devtools_agent_host.h
index b69e8ea..d328694 100644
--- a/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -52,6 +52,7 @@
 namespace security { class SecurityHandler; }
 namespace service_worker { class ServiceWorkerHandler; }
 namespace storage { class StorageHandler; }
+namespace target { class TargetHandler; }
 namespace tracing { class TracingHandler; }
 }
 
@@ -184,6 +185,7 @@
       service_worker_handler_;
   std::unique_ptr<devtools::storage::StorageHandler>
       storage_handler_;
+  std::unique_ptr<devtools::target::TargetHandler> target_handler_;
   std::unique_ptr<devtools::tracing::TracingHandler> tracing_handler_;
   std::unique_ptr<devtools::emulation::EmulationHandler> emulation_handler_;
   std::unique_ptr<DevToolsFrameTraceRecorder> frame_trace_recorder_;
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index d633598e..9a1a596f 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -669,8 +669,7 @@
       break;
     case ui::ContextProviderFactory::GpuChannelHostResult::
         FAILURE_GPU_PROCESS_INITIALIZATION_FAILED:
-      // TODO(khushalsagar): Retry or have a fallback path after
-      // crbug.com/643282 is resolved.
+      HandlePendingCompositorFrameSinkRequest();
       break;
     case ui::ContextProviderFactory::GpuChannelHostResult::SUCCESS:
       // We don't need the context anymore if we are invisible.
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 78e6dc9..1c6011b 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1745,6 +1745,7 @@
     switches::kMaxUntiledLayerHeight,
     switches::kMemoryMetrics,
     switches::kMojoLocalStorage,
+    switches::kMojoServiceWorker,
     switches::kMSEAudioBufferSizeLimit,
     switches::kMSEVideoBufferSizeLimit,
     switches::kNoReferrers,
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index a08d207..17d4cd4 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -20,11 +20,14 @@
 #include "content/common/service_worker/embedded_worker_messages.h"
 #include "content/common/service_worker/embedded_worker_settings.h"
 #include "content/common/service_worker/embedded_worker_setup.mojom.h"
+#include "content/common/service_worker/embedded_worker_start_params.h"
 #include "content/common/service_worker/service_worker_types.h"
+#include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/child_process_host.h"
+#include "content/public/common/content_switches.h"
 #include "ipc/ipc_message.h"
 #include "services/shell/public/cpp/interface_provider.h"
 #include "services/shell/public/cpp/interface_registry.h"
@@ -69,7 +72,7 @@
       worker_process_id, worker_route_id);
 }
 
-void RegisterToWorkerDevToolsManagerOnUI(
+void SetupOnUI(
     int process_id,
     const ServiceWorkerContextCore* service_worker_context,
     const base::WeakPtr<ServiceWorkerContextCore>& service_worker_context_weak,
@@ -77,6 +80,7 @@
     const GURL& url,
     const GURL& scope,
     bool is_installed,
+    mojom::EmbeddedWorkerInstanceClientRequest request,
     const base::Callback<void(int worker_devtools_agent_route_id,
                               bool wait_for_debugger)>& callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -92,6 +96,8 @@
                 service_worker_context, service_worker_context_weak,
                 service_worker_version_id, url, scope),
             is_installed);
+    if (request.is_pending())
+      rph->GetRemoteInterfaces()->GetInterface(std::move(request));
   }
   BrowserThread::PostTask(
       BrowserThread::IO,
@@ -211,8 +217,11 @@
  public:
   enum class ProcessAllocationState { NOT_ALLOCATED, ALLOCATING, ALLOCATED };
 
-  StartTask(EmbeddedWorkerInstance* instance, const GURL& script_url)
+  StartTask(EmbeddedWorkerInstance* instance,
+            const GURL& script_url,
+            mojom::EmbeddedWorkerInstanceClientRequest request)
       : instance_(instance),
+        request_(std::move(request)),
         state_(ProcessAllocationState::NOT_ALLOCATED),
         is_installed_(false),
         started_during_browser_startup_(false),
@@ -254,7 +263,7 @@
     // TODO(nhiroki): Reconsider this bizarre layering.
   }
 
-  void Start(std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
+  void Start(std::unique_ptr<EmbeddedWorkerStartParams> params,
              const StatusCallback& callback) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     state_ = ProcessAllocationState::ALLOCATING;
@@ -289,12 +298,11 @@
   bool is_installed() const { return is_installed_; }
 
  private:
-  void OnProcessAllocated(
-      std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
-      ServiceWorkerStatusCode status,
-      int process_id,
-      bool is_new_process,
-      const EmbeddedWorkerSettings& settings) {
+  void OnProcessAllocated(std::unique_ptr<EmbeddedWorkerStartParams> params,
+                          ServiceWorkerStatusCode status,
+                          int process_id,
+                          bool is_new_process,
+                          const EmbeddedWorkerSettings& settings) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
     if (status != SERVICE_WORKER_OK) {
@@ -342,23 +350,22 @@
     GURL script_url(params->script_url);
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
-        base::Bind(RegisterToWorkerDevToolsManagerOnUI, process_id,
-                   instance_->context_.get(), instance_->context_,
-                   service_worker_version_id, script_url, scope, is_installed_,
-                   base::Bind(&StartTask::OnRegisteredToDevToolsManager,
+        base::Bind(&SetupOnUI, process_id, instance_->context_.get(),
+                   instance_->context_, service_worker_version_id, script_url,
+                   scope, is_installed_, base::Passed(&request_),
+                   base::Bind(&StartTask::OnSetupOnUICompleted,
                               weak_factory_.GetWeakPtr(), base::Passed(&params),
                               is_new_process)));
   }
 
-  void OnRegisteredToDevToolsManager(
-      std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
-      bool is_new_process,
-      int worker_devtools_agent_route_id,
-      bool wait_for_debugger) {
+  void OnSetupOnUICompleted(std::unique_ptr<EmbeddedWorkerStartParams> params,
+                            bool is_new_process,
+                            int worker_devtools_agent_route_id,
+                            bool wait_for_debugger) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker",
                                  "EmbeddedWorkerInstance::Start", this,
-                                 "OnRegisteredToDevToolsManager");
+                                 "OnSetupOnUICompleted");
 
     // Notify the instance that it is registered to the devtools manager.
     instance_->OnRegisteredToDevToolsManager(
@@ -366,11 +373,14 @@
 
     params->worker_devtools_agent_route_id = worker_devtools_agent_route_id;
     params->wait_for_debugger = wait_for_debugger;
-    SendStartWorker(std::move(params));
+
+    if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled())
+      instance_->SendMojoStartWorker(std::move(params));
+    else
+      SendStartWorker(std::move(params));
   }
 
-  void SendStartWorker(
-      std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params) {
+  void SendStartWorker(std::unique_ptr<EmbeddedWorkerStartParams> params) {
     DCHECK_CURRENTLY_ON(BrowserThread::IO);
     ServiceWorkerStatusCode status = instance_->registry_->SendStartWorker(
         std::move(params), instance_->process_id());
@@ -393,6 +403,10 @@
   // |instance_| must outlive |this|.
   EmbeddedWorkerInstance* instance_;
 
+  // Ownership is transferred by base::Passed() to a task after process
+  // allocation.
+  mojom::EmbeddedWorkerInstanceClientRequest request_;
+
   StatusCallback start_callback_;
   ProcessAllocationState state_;
 
@@ -421,7 +435,7 @@
 }
 
 void EmbeddedWorkerInstance::Start(
-    std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
+    std::unique_ptr<EmbeddedWorkerStartParams> params,
     const StatusCallback& callback) {
   if (!context_) {
     callback.Run(SERVICE_WORKER_ERROR_ABORT);
@@ -445,7 +459,12 @@
   params->wait_for_debugger = false;
   params->settings.v8_cache_options = GetV8CacheOptions();
 
-  inflight_start_task_.reset(new StartTask(this, params->script_url));
+  mojom::EmbeddedWorkerInstanceClientRequest request;
+  if (ServiceWorkerUtils::IsMojoForServiceWorkerEnabled())
+    request = mojo::GetProxy(&client_);
+
+  inflight_start_task_.reset(
+      new StartTask(this, params->script_url, std::move(request)));
   inflight_start_task_->Start(std::move(params), callback);
 }
 
@@ -566,6 +585,15 @@
   FOR_EACH_OBSERVER(Listener, listener_list_, OnRegisteredToDevToolsManager());
 }
 
+void EmbeddedWorkerInstance::SendMojoStartWorker(
+    std::unique_ptr<EmbeddedWorkerStartParams> params) {
+  client_->StartWorker(*params);
+  registry_->BindWorkerToProcess(process_id(), embedded_worker_id());
+  TRACE_EVENT_ASYNC_STEP_PAST1("ServiceWorker", "EmbeddedWorkerInstance::Start",
+                               this, "SendStartWorker", "Status", "mojo");
+  OnStartWorkerMessageSent();
+}
+
 void EmbeddedWorkerInstance::OnStartWorkerMessageSent() {
   if (!step_time_.is_null()) {
     base::TimeDelta duration = UpdateStepTime();
@@ -660,9 +688,10 @@
   FOR_EACH_OBSERVER(Listener, listener_list_, OnThreadStarted());
 
   shell::mojom::InterfaceProviderPtr exposed_interfaces;
-  interface_registry_->Bind(GetProxy(&exposed_interfaces));
+  interface_registry_->Bind(mojo::GetProxy(&exposed_interfaces));
   shell::mojom::InterfaceProviderPtr remote_interfaces;
-  shell::mojom::InterfaceProviderRequest request = GetProxy(&remote_interfaces);
+  shell::mojom::InterfaceProviderRequest request =
+      mojo::GetProxy(&remote_interfaces);
   remote_interfaces_->Bind(std::move(remote_interfaces));
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
diff --git a/content/browser/service_worker/embedded_worker_instance.h b/content/browser/service_worker/embedded_worker_instance.h
index 13aca7e3..705b773 100644
--- a/content/browser/service_worker/embedded_worker_instance.h
+++ b/content/browser/service_worker/embedded_worker_instance.h
@@ -23,6 +23,7 @@
 #include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/common/content_export.h"
+#include "content/common/service_worker/embedded_worker.mojom.h"
 #include "content/common/service_worker/service_worker_status_code.h"
 #include "content/public/common/console_message_level.h"
 #include "url/gurl.h"
@@ -32,8 +33,6 @@
 #undef SendMessage
 #endif
 
-struct EmbeddedWorkerMsg_StartWorker_Params;
-
 namespace IPC {
 class Message;
 }
@@ -46,6 +45,7 @@
 namespace content {
 
 class EmbeddedWorkerRegistry;
+struct EmbeddedWorkerStartParams;
 class MessagePortMessageFilter;
 class ServiceWorkerContextCore;
 
@@ -112,7 +112,7 @@
   // started and evaluated, or when an error occurs.
   // |params| should be populated with service worker version info needed
   // to start the worker.
-  void Start(std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
+  void Start(std::unique_ptr<EmbeddedWorkerStartParams> params,
              const StatusCallback& callback);
 
   // Stops the worker. It is invalid to call this when the worker is
@@ -224,6 +224,9 @@
                                      int worker_devtools_agent_route_id,
                                      bool wait_for_debugger);
 
+  // Sends StartWorker message via Mojo.
+  void SendMojoStartWorker(std::unique_ptr<EmbeddedWorkerStartParams> params);
+
   // Called back from StartTask after a start worker message is sent.
   void OnStartWorkerMessageSent();
 
@@ -306,8 +309,12 @@
   // Current running information.
   std::unique_ptr<EmbeddedWorkerInstance::WorkerProcessHandle> process_handle_;
   int thread_id_;
+
+  // These are connected to the renderer process after OnThreadStarted.
   std::unique_ptr<shell::InterfaceRegistry> interface_registry_;
   std::unique_ptr<shell::InterfaceProvider> remote_interfaces_;
+  // |client_| is used to send messages to the renderer process.
+  mojom::EmbeddedWorkerInstanceClientPtr client_;
 
   // Whether devtools is attached or not.
   bool devtools_attached_;
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index f2df6b57..1253a28 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
@@ -16,9 +17,13 @@
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/common/service_worker/embedded_worker.mojom.h"
 #include "content/common/service_worker/embedded_worker_messages.h"
+#include "content/common/service_worker/embedded_worker_start_params.h"
 #include "content/public/common/child_process_host.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -33,14 +38,15 @@
   callback.Run();
 }
 
-std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params>
+std::unique_ptr<EmbeddedWorkerStartParams>
 CreateStartParams(int version_id, const GURL& scope, const GURL& script_url) {
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
-      new EmbeddedWorkerMsg_StartWorker_Params);
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
+      new EmbeddedWorkerStartParams);
   params->service_worker_version_id = version_id;
   params->scope = scope;
   params->script_url = script_url;
   params->pause_after_download = false;
+  params->is_installed = false;
   return params;
 }
 
@@ -97,7 +103,7 @@
                                       const GURL& url) {
     ServiceWorkerStatusCode status;
     base::RunLoop run_loop;
-    std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params =
+    std::unique_ptr<EmbeddedWorkerStartParams> params =
         CreateStartParams(id, pattern, url);
     worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                                 run_loop.QuitClosure()));
@@ -122,6 +128,24 @@
   DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceTest);
 };
 
+class EmbeddedWorkerInstanceTestP : public EmbeddedWorkerInstanceTest,
+                                    public testing::WithParamInterface<bool> {
+ protected:
+  void SetUp() override {
+    is_mojo_enabled_ = GetParam();
+    if (is_mojo_enabled()) {
+      base::CommandLine::ForCurrentProcess()->AppendSwitch(
+          switches::kMojoServiceWorker);
+    }
+    EmbeddedWorkerInstanceTest::SetUp();
+  }
+
+  bool is_mojo_enabled() { return is_mojo_enabled_; }
+
+ private:
+  bool is_mojo_enabled_ = false;
+};
+
 // A helper to simulate the start worker sequence is stalled in a worker
 // process.
 class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
@@ -162,10 +186,11 @@
   }
 };
 
-TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
+TEST_P(EmbeddedWorkerInstanceTestP, StartAndStop) {
   std::unique_ptr<EmbeddedWorkerInstance> worker =
       embedded_worker_registry()->CreateWorker();
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
+  worker->AddListener(this);
 
   const int64_t service_worker_version_id = 55L;
   const GURL pattern("http://example.com/");
@@ -178,7 +203,7 @@
   // Start should succeed.
   ServiceWorkerStatusCode status;
   base::RunLoop run_loop;
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params =
+  std::unique_ptr<EmbeddedWorkerStartParams> params =
       CreateStartParams(service_worker_version_id, pattern, url);
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               run_loop.QuitClosure()));
@@ -200,11 +225,21 @@
   // EmbeddedWorkerTestHelper.
   EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, worker->status());
 
-  // Verify that we've sent two messages to start and terminate the worker.
-  ASSERT_TRUE(
-      ipc_sink()->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID));
+  if (!is_mojo_enabled()) {
+    // Verify that we've sent two messages to start and terminate the worker.
+    ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
+        EmbeddedWorkerMsg_StartWorker::ID));
+  }
+  // StopWorker should be sent in either case.
   ASSERT_TRUE(ipc_sink()->GetUniqueMessageMatching(
       EmbeddedWorkerMsg_StopWorker::ID));
+
+  // Check if the IPCs are fired in expected order.
+  ASSERT_EQ(4u, events_.size());
+  EXPECT_EQ(PROCESS_ALLOCATED, events_[0].type);
+  EXPECT_EQ(START_WORKER_MESSAGE_SENT, events_[1].type);
+  EXPECT_EQ(STARTED, events_[2].type);
+  EXPECT_EQ(STOPPED, events_[3].type);
 }
 
 // Test that a worker that failed twice will use a new render process
@@ -233,7 +268,7 @@
     // Start once normally.
     ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
     base::RunLoop run_loop;
-    std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+    std::unique_ptr<EmbeddedWorkerStartParams> params(
         CreateStartParams(service_worker_version_id, pattern, url));
     worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                                 run_loop.QuitClosure()));
@@ -257,7 +292,7 @@
     // Start again.
     ServiceWorkerStatusCode status;
     base::RunLoop run_loop;
-    std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+    std::unique_ptr<EmbeddedWorkerStartParams> params(
         CreateStartParams(service_worker_version_id, pattern, url));
     worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                                 run_loop.QuitClosure()));
@@ -337,7 +372,7 @@
     // Start worker1.
     ServiceWorkerStatusCode status;
     base::RunLoop run_loop;
-    std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+    std::unique_ptr<EmbeddedWorkerStartParams> params(
         CreateStartParams(version_id1, pattern, url));
     worker1->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                                  run_loop.QuitClosure()));
@@ -349,7 +384,7 @@
     // Start worker2.
     ServiceWorkerStatusCode status;
     base::RunLoop run_loop;
-    std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+    std::unique_ptr<EmbeddedWorkerStartParams> params(
         CreateStartParams(version_id2, pattern, url));
     worker2->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                                  run_loop.QuitClosure()));
@@ -386,7 +421,7 @@
 
   // Run the start worker sequence and detach during process allocation.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
       CreateStartParams(version_id, scope, url));
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               base::Bind(&base::DoNothing)));
@@ -418,7 +453,7 @@
 
   // Run the start worker sequence until a start worker message is sent.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
       CreateStartParams(version_id, scope, url));
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               base::Bind(&base::DoNothing)));
@@ -457,7 +492,7 @@
   // Stop the start worker sequence before a process is allocated.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
 
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
       CreateStartParams(version_id, scope, url));
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               base::Bind(&base::DoNothing)));
@@ -507,7 +542,7 @@
   // Run the start worker sequence until pause after download.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
 
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
       CreateStartParams(version_id, scope, url));
   params->pause_after_download = true;
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
@@ -538,7 +573,7 @@
 
   // Run the start worker sequence until a start worker message is sent.
   ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
       CreateStartParams(version_id, scope, url));
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               base::Bind(&base::DoNothing)));
@@ -600,7 +635,7 @@
 
   // Start the worker.
   base::RunLoop run_loop;
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
       CreateStartParams(version_id, pattern, url));
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               run_loop.QuitClosure()));
@@ -635,7 +670,7 @@
 
   // Attempt to start the worker.
   base::RunLoop run_loop;
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
       CreateStartParams(version_id, pattern, url));
   worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
                                               run_loop.QuitClosure()));
@@ -649,4 +684,8 @@
   EXPECT_EQ(EmbeddedWorkerStatus::STARTING, events_[1].status);
 }
 
+INSTANTIATE_TEST_CASE_P(EmbeddedWorkerInstanceTest,
+                        EmbeddedWorkerInstanceTestP,
+                        ::testing::Values(false, true));
+
 }  // namespace content
diff --git a/content/browser/service_worker/embedded_worker_registry.cc b/content/browser/service_worker/embedded_worker_registry.cc
index 1b75f94..3859b5aa 100644
--- a/content/browser/service_worker/embedded_worker_registry.cc
+++ b/content/browser/service_worker/embedded_worker_registry.cc
@@ -249,7 +249,7 @@
 }
 
 ServiceWorkerStatusCode EmbeddedWorkerRegistry::SendStartWorker(
-    std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
+    std::unique_ptr<EmbeddedWorkerStartParams> params,
     int process_id) {
   if (!context_)
     return SERVICE_WORKER_ERROR_ABORT;
@@ -269,10 +269,25 @@
   ServiceWorkerStatusCode status =
       Send(process_id, new EmbeddedWorkerMsg_StartWorker(*params));
   if (status == SERVICE_WORKER_OK)
-    worker_process_map_[process_id].insert(embedded_worker_id);
+    BindWorkerToProcess(process_id, embedded_worker_id);
   return status;
 }
 
+void EmbeddedWorkerRegistry::BindWorkerToProcess(int process_id,
+                                                 int embedded_worker_id) {
+  // The ServiceWorkerDispatcherHost is supposed to be created when the process
+  // is created, and keep an entry in process_sender_map_ for its whole
+  // lifetime.
+  DCHECK(base::ContainsKey(process_sender_map_, process_id));
+  DCHECK(GetWorker(embedded_worker_id));
+  DCHECK_EQ(GetWorker(embedded_worker_id)->process_id(), process_id);
+  DCHECK(
+      !base::ContainsKey(worker_process_map_, process_id) ||
+      !base::ContainsKey(worker_process_map_[process_id], embedded_worker_id));
+
+  worker_process_map_[process_id].insert(embedded_worker_id);
+}
+
 ServiceWorkerStatusCode EmbeddedWorkerRegistry::Send(
     int process_id, IPC::Message* message_ptr) {
   std::unique_ptr<IPC::Message> message(message_ptr);
diff --git a/content/browser/service_worker/embedded_worker_registry.h b/content/browser/service_worker/embedded_worker_registry.h
index 8e83b1d..70475ef 100644
--- a/content/browser/service_worker/embedded_worker_registry.h
+++ b/content/browser/service_worker/embedded_worker_registry.h
@@ -18,7 +18,6 @@
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_status_code.h"
 
-struct EmbeddedWorkerMsg_StartWorker_Params;
 class GURL;
 
 namespace IPC {
@@ -29,6 +28,7 @@
 namespace content {
 
 class EmbeddedWorkerInstance;
+struct EmbeddedWorkerStartParams;
 class MessagePortMessageFilter;
 class ServiceWorkerContextCore;
 
@@ -59,7 +59,7 @@
 
   // Called from EmbeddedWorkerInstance, relayed to the child process.
   ServiceWorkerStatusCode SendStartWorker(
-      std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
+      std::unique_ptr<EmbeddedWorkerStartParams> params,
       int process_id);
   ServiceWorkerStatusCode StopWorker(int process_id,
                                      int embedded_worker_id);
@@ -114,10 +114,10 @@
   FRIEND_TEST_ALL_PREFIXES(EmbeddedWorkerInstanceTest,
                            RemoveWorkerInSharedProcess);
 
-  typedef std::map<int, EmbeddedWorkerInstance*> WorkerInstanceMap;
-  typedef std::map<int, IPC::Sender*> ProcessToSenderMap;
-  typedef std::map<int, MessagePortMessageFilter*>
-      ProcessToMessagePortMessageFilterMap;
+  using WorkerInstanceMap = std::map<int, EmbeddedWorkerInstance*>;
+  using ProcessToSenderMap = std::map<int, IPC::Sender*>;
+  using ProcessToMessagePortMessageFilterMap =
+      std::map<int, MessagePortMessageFilter*>;
 
   EmbeddedWorkerRegistry(
       const base::WeakPtr<ServiceWorkerContextCore>& context,
@@ -126,6 +126,11 @@
 
   ServiceWorkerStatusCode Send(int process_id, IPC::Message* message);
 
+  // Called when EmbeddedWorkerInstance is ready for IPC. This function
+  // prepares a route to the child worker thread.
+  // TODO(shimazu): Remove this function once mojofication is completed.
+  void BindWorkerToProcess(int process_id, int embedded_worker_id);
+
   // RemoveWorker is called when EmbeddedWorkerInstance is destructed.
   // |process_id| could be invalid (i.e. ChildProcessHost::kInvalidUniqueID)
   // if it's not running.
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index daf636d..674827f 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -21,6 +21,7 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/common/service_worker/embedded_worker_messages.h"
 #include "content/common/service_worker/embedded_worker_setup.mojom.h"
+#include "content/common/service_worker/embedded_worker_start_params.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "content/public/common/push_event_payload.h"
 #include "content/public/test/mock_render_process_host.h"
@@ -82,13 +83,66 @@
   base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
 };
 
+EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
+    MockEmbeddedWorkerInstanceClient(
+        base::WeakPtr<EmbeddedWorkerTestHelper> helper)
+    : helper_(helper), binding_(this) {}
+
+EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
+    ~MockEmbeddedWorkerInstanceClient() {}
+
+void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
+    const EmbeddedWorkerStartParams& params) {
+  if (!helper_)
+    return;
+
+  embedded_worker_id_ = params.embedded_worker_id;
+
+  EmbeddedWorkerInstance* worker =
+      helper_->registry()->GetWorker(params.embedded_worker_id);
+  ASSERT_TRUE(worker != NULL);
+  EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
+
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
+                 helper_->weak_factory_.GetWeakPtr(), params.embedded_worker_id,
+                 params.service_worker_version_id, params.scope,
+                 params.script_url, params.pause_after_download));
+}
+
+// static
+void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::Bind(
+    const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+    mojom::EmbeddedWorkerInstanceClientRequest request) {
+  std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>* clients =
+      helper->mock_instance_clients();
+  size_t next_client_index = helper->mock_instance_clients_next_index_;
+
+  ASSERT_GE(clients->size(), next_client_index);
+  if (clients->size() == next_client_index) {
+    clients->push_back(
+        base::MakeUnique<MockEmbeddedWorkerInstanceClient>(helper));
+  }
+
+  std::unique_ptr<MockEmbeddedWorkerInstanceClient>& client =
+      clients->at(next_client_index);
+  helper->mock_instance_clients_next_index_ = next_client_index + 1;
+  if (client)
+    client->binding_.Bind(std::move(request));
+}
+
 EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
     const base::FilePath& user_data_directory)
     : browser_context_(new TestBrowserContext),
       render_process_host_(new MockRenderProcessHost(browser_context_.get())),
+      new_render_process_host_(
+          new MockRenderProcessHost(browser_context_.get())),
       wrapper_(new ServiceWorkerContextWrapper(browser_context_.get())),
+      mock_instance_clients_next_index_(0),
       next_thread_id_(0),
       mock_render_process_id_(render_process_host_->GetID()),
+      new_mock_render_process_id_(new_render_process_host_->GetID()),
       weak_factory_(this) {
   std::unique_ptr<MockServiceWorkerDatabaseTaskManager> database_task_manager(
       new MockServiceWorkerDatabaseTaskManager(
@@ -101,16 +155,10 @@
                                     NewMessagePortMessageFilter());
 
   // Setup process level interface registry.
-  render_process_interface_registry_.reset(new shell::InterfaceRegistry);
-  render_process_interface_registry_->AddInterface(
-      base::Bind(&MockEmbeddedWorkerSetup::Create, weak_factory_.GetWeakPtr()));
-  shell::mojom::InterfaceProviderPtr interfaces;
-  render_process_interface_registry_->Bind(mojo::GetProxy(&interfaces));
-
-  std::unique_ptr<shell::InterfaceProvider> host_remote_interfaces(
-      new shell::InterfaceProvider);
-  host_remote_interfaces->Bind(std::move(interfaces));
-  render_process_host_->SetRemoteInterfaces(std::move(host_remote_interfaces));
+  render_process_interface_registry_ =
+      CreateInterfaceRegistry(render_process_host_.get());
+  new_render_process_interface_registry_ =
+      CreateInterfaceRegistry(new_render_process_host_.get());
 }
 
 EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
@@ -327,7 +375,7 @@
 }
 
 void EmbeddedWorkerTestHelper::OnStartWorkerStub(
-    const EmbeddedWorkerMsg_StartWorker_Params& params) {
+    const EmbeddedWorkerStartParams& params) {
   EmbeddedWorkerInstance* worker =
       registry()->GetWorker(params.embedded_worker_id);
   ASSERT_TRUE(worker != NULL);
@@ -444,4 +492,23 @@
   return filter.get();
 }
 
+std::unique_ptr<shell::InterfaceRegistry>
+EmbeddedWorkerTestHelper::CreateInterfaceRegistry(MockRenderProcessHost* rph) {
+  std::unique_ptr<shell::InterfaceRegistry> registry(
+      new shell::InterfaceRegistry);
+  registry->AddInterface(
+      base::Bind(&MockEmbeddedWorkerSetup::Create, weak_factory_.GetWeakPtr()));
+  registry->AddInterface(base::Bind(&MockEmbeddedWorkerInstanceClient::Bind,
+                                    weak_factory_.GetWeakPtr()));
+
+  shell::mojom::InterfaceProviderPtr interfaces;
+  registry->Bind(mojo::GetProxy(&interfaces));
+
+  std::unique_ptr<shell::InterfaceProvider> remote_interfaces(
+      new shell::InterfaceProvider);
+  remote_interfaces->Bind(std::move(interfaces));
+  rph->SetRemoteInterfaces(std::move(remote_interfaces));
+  return registry;
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/embedded_worker_test_helper.h b/content/browser/service_worker/embedded_worker_test_helper.h
index 88bf11b..97ec1637 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/content/browser/service_worker/embedded_worker_test_helper.h
@@ -15,14 +15,16 @@
 #include "base/containers/hash_tables.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "content/common/service_worker/embedded_worker.mojom.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_test_sink.h"
+#include "mojo/public/cpp/bindings/binding.h"
 #include "services/shell/public/interfaces/interface_provider.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
 class GURL;
-struct EmbeddedWorkerMsg_StartWorker_Params;
 struct ServiceWorkerMsg_ExtendableMessageEvent_Params;
 
 namespace shell {
@@ -39,6 +41,7 @@
 class ServiceWorkerContextCore;
 class ServiceWorkerContextWrapper;
 class TestBrowserContext;
+struct EmbeddedWorkerStartParams;
 struct PushEventPayload;
 struct ServiceWorkerFetchRequest;
 
@@ -60,6 +63,28 @@
 class EmbeddedWorkerTestHelper : public IPC::Sender,
                                  public IPC::Listener {
  public:
+  class MockEmbeddedWorkerInstanceClient
+      : public mojom::EmbeddedWorkerInstanceClient {
+   public:
+    explicit MockEmbeddedWorkerInstanceClient(
+        base::WeakPtr<EmbeddedWorkerTestHelper> helper);
+    ~MockEmbeddedWorkerInstanceClient() override;
+
+    static void Bind(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+                     mojom::EmbeddedWorkerInstanceClientRequest request);
+
+   private:
+    // Implementation of mojo interfaces.
+    void StartWorker(const EmbeddedWorkerStartParams& params) override;
+
+    base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
+    mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_;
+
+    base::Optional<int> embedded_worker_id_;
+
+    DISALLOW_COPY_AND_ASSIGN(MockEmbeddedWorkerInstanceClient);
+  };
+
   // If |user_data_directory| is empty, the context makes storage stuff in
   // memory.
   explicit EmbeddedWorkerTestHelper(const base::FilePath& user_data_directory);
@@ -80,6 +105,11 @@
   // Inner IPC sink for script context messages sent via EmbeddedWorker.
   IPC::TestSink* inner_ipc_sink() { return &inner_sink_; }
 
+  std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>*
+  mock_instance_clients() {
+    return &mock_instance_clients_;
+  }
+
   ServiceWorkerContextCore* context();
   ServiceWorkerContextWrapper* context_wrapper() { return wrapper_.get(); }
   void ShutdownContext();
@@ -95,9 +125,8 @@
     return embedded_worker_id_service_worker_version_id_map_;
   }
 
-  // Only used for tests that force creating a new render process. There is no
-  // corresponding MockRenderProcessHost.
-  int new_render_process_id() const { return mock_render_process_id_ + 1; }
+  // Only used for tests that force creating a new render process.
+  int new_render_process_id() const { return new_mock_render_process_id_; }
 
   TestBrowserContext* browser_context() { return browser_context_.get(); }
 
@@ -158,7 +187,7 @@
 
   class MockEmbeddedWorkerSetup;
 
-  void OnStartWorkerStub(const EmbeddedWorkerMsg_StartWorker_Params& params);
+  void OnStartWorkerStub(const EmbeddedWorkerStartParams& params);
   void OnResumeAfterDownloadStub(int embedded_worker_id);
   void OnStopWorkerStub(int embedded_worker_id);
   void OnMessageToWorkerStub(int thread_id,
@@ -179,18 +208,29 @@
 
   MessagePortMessageFilter* NewMessagePortMessageFilter();
 
+  std::unique_ptr<shell::InterfaceRegistry> CreateInterfaceRegistry(
+      MockRenderProcessHost* rph);
+
   std::unique_ptr<TestBrowserContext> browser_context_;
   std::unique_ptr<MockRenderProcessHost> render_process_host_;
+  std::unique_ptr<MockRenderProcessHost> new_render_process_host_;
 
   scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
 
   IPC::TestSink sink_;
   IPC::TestSink inner_sink_;
 
+  std::vector<std::unique_ptr<MockEmbeddedWorkerInstanceClient>>
+      mock_instance_clients_;
+  size_t mock_instance_clients_next_index_;
+
   int next_thread_id_;
   int mock_render_process_id_;
+  int new_mock_render_process_id_;
 
   std::unique_ptr<shell::InterfaceRegistry> render_process_interface_registry_;
+  std::unique_ptr<shell::InterfaceRegistry>
+      new_render_process_interface_registry_;
 
   std::map<int, int64_t> embedded_worker_id_service_worker_version_id_map_;
 
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index fc1c655..63a1c47 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -337,10 +337,20 @@
 
 }  // namespace
 
-class ServiceWorkerBrowserTest : public ContentBrowserTest {
+class ServiceWorkerBrowserTest : public testing::WithParamInterface<bool>,
+                                 public ContentBrowserTest {
  protected:
   using self = ServiceWorkerBrowserTest;
 
+  void SetUp() override {
+    is_mojo_enabled_ = GetParam();
+    if (is_mojo_enabled()) {
+      base::CommandLine::ForCurrentProcess()->AppendSwitch(
+          switches::kMojoServiceWorker);
+    }
+    ContentBrowserTest::SetUp();
+  }
+
   void SetUpOnMainThread() override {
     ASSERT_TRUE(embedded_test_server()->Start());
     StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
@@ -368,6 +378,7 @@
 
   ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
   ServiceWorkerContext* public_context() { return wrapper(); }
+  bool is_mojo_enabled() const { return is_mojo_enabled_; }
 
   void AssociateRendererProcessToPattern(const GURL& pattern) {
     wrapper_->process_manager()->AddProcessReferenceToPattern(
@@ -376,6 +387,7 @@
 
  private:
   scoped_refptr<ServiceWorkerContextWrapper> wrapper_;
+  bool is_mojo_enabled_ = false;
 };
 
 class ConsoleListener : public EmbeddedWorkerInstance::Listener {
@@ -787,7 +799,7 @@
   std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, StartAndStop) {
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
                            "/service_worker/worker.js"));
@@ -813,7 +825,7 @@
   ASSERT_EQ(SERVICE_WORKER_OK, status);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartNotFound) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, StartNotFound) {
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
                            "/service_worker/nonexistent.js"));
@@ -822,7 +834,7 @@
   StartWorker(SERVICE_WORKER_ERROR_NETWORK);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, ReadResourceFailure) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, ReadResourceFailure) {
   // Create a registration.
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
@@ -853,7 +865,7 @@
                         SERVICE_WORKER_ERROR_NOT_FOUND);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        ReadResourceFailure_WaitingWorker) {
   // Create a registration and active version.
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
@@ -902,24 +914,24 @@
                         SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, Install) {
   InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_Fulfilled) {
   InstallTestHelper("/service_worker/worker_install_fulfilled.js",
                     SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        InstallWithFetchHandler) {
   InstallTestHelper("/service_worker/fetch_event.js", SERVICE_WORKER_OK);
   EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::EXISTS,
             version_->fetch_handler_existence());
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        InstallWithoutFetchHandler) {
   InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
   EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST,
@@ -928,31 +940,31 @@
 
 // Check that ServiceWorker script requests set a "Service-Worker: script"
 // header.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        ServiceWorkerScriptHeader) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifyServiceWorkerHeaderInRequest));
   InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        Activate_NoEventListener) {
   ActivateTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
   ASSERT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
   ActivateTestHelper("/service_worker/worker_activate_rejected.js",
                      SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_Rejected) {
   InstallTestHelper("/service_worker/worker_install_rejected.js",
                     SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_RejectConsoleMessage) {
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
@@ -997,7 +1009,7 @@
   base::Closure quit_;
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
                            "/service_worker/while_true_worker.js"));
@@ -1034,7 +1046,7 @@
   EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
   RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread,
                            base::Unretained(this),
                            "/service_worker/while_true_in_install_worker.js"));
@@ -1069,7 +1081,7 @@
   EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
   ServiceWorkerFetchEventResult result;
   ServiceWorkerResponse response;
   std::unique_ptr<storage::BlobDataHandle> blob_data_handle;
@@ -1091,7 +1103,7 @@
   EXPECT_EQ("This resource is gone. Gone, gone, gone.", body);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        FetchEvent_ResponseViaCache) {
   ServiceWorkerFetchEventResult result;
   ServiceWorkerResponse response1;
@@ -1118,7 +1130,7 @@
   EXPECT_EQ("cache_name", response2.cache_storage_cache_name);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        FetchEvent_respondWithRejection) {
   ServiceWorkerFetchEventResult result;
   ServiceWorkerResponse response;
@@ -1173,7 +1185,7 @@
   bool data_saver_enabled_;
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifySaveDataHeaderInRequest));
   MockContentBrowserClient content_browser_client;
@@ -1184,7 +1196,7 @@
   SetBrowserClientForTesting(old_client);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest,
                        RequestWorkerScriptWithSaveData) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifySaveDataHeaderInRequest));
@@ -1196,7 +1208,7 @@
   SetBrowserClientForTesting(old_client);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
   embedded_test_server()->RegisterRequestHandler(
       base::Bind(&VerifySaveDataHeaderNotInRequest));
   MockContentBrowserClient content_browser_client;
@@ -1206,7 +1218,7 @@
   SetBrowserClientForTesting(old_client);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
   const char kPageUrl[] = "/service_worker/handle_fetch.html";
   const char kWorkerUrl[] = "/service_worker/add_save_data_to_title.js";
   MockContentBrowserClient content_browser_client;
@@ -1241,7 +1253,7 @@
 // Tests that when data saver is enabled and a cross-origin fetch by a webpage
 // is intercepted by a serviceworker, and the serviceworker does a fetch, the
 // preflight request does not have save-data in Access-Control-Request-Headers.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
   const char kPageUrl[] = "/service_worker/fetch_cross_origin.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
   net::EmbeddedTestServer cross_origin_server;
@@ -1284,7 +1296,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
                        FetchPageWithSaveDataPassThroughOnFetch) {
   const char kPageUrl[] = "/service_worker/pass_through_fetch.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
@@ -1318,7 +1330,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, Reload) {
   const char kPageUrl[] = "/service_worker/reload.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_reload.js";
   scoped_refptr<WorkerActivatedObserver> observer =
@@ -1355,7 +1367,7 @@
 #else
 #define MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure ResponseFromHTTPSServiceWorkerIsMarkedAsSecure
 #endif
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
                        MAYBE_ResponseFromHTTPSServiceWorkerIsMarkedAsSecure) {
   const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js";
@@ -1391,7 +1403,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest,
                        ResponseFromHTTPServiceWorkerIsNotMarkedAsSecure) {
   const char kPageUrl[] = "/service_worker/fetch_event_blob.html";
   const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js";
@@ -1423,7 +1435,7 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, ImportsBustMemcache) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, ImportsBustMemcache) {
   const char kScopeUrl[] = "/service_worker/imports_bust_memcache_scope/";
   const char kPageUrl[] = "/service_worker/imports_bust_memcache.html";
   const char kScriptUrl[] = "/service_worker/worker_with_one_import.js";
@@ -1488,7 +1500,7 @@
   return result;
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBlackBoxBrowserTest, Registration) {
   // Close the only window to be sure we're not re-using its RenderProcessHost.
   shell()->Close();
   EXPECT_EQ(0, CountRenderProcessHosts());
@@ -1570,7 +1582,7 @@
 #else
 #define MAYBE_CrossSiteTransfer CrossSiteTransfer
 #endif
-IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, MAYBE_CrossSiteTransfer) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBrowserTest, MAYBE_CrossSiteTransfer) {
   // The first page registers a service worker.
   const char kRegisterPageUrl[] = "/service_worker/cross_site_xfer.html";
   const base::string16 kOKTitle1(base::ASCIIToUTF16("OK_1"));
@@ -1624,7 +1636,7 @@
   base::Closure cache_updated_closure_;
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerVersionBrowserV8CacheTest, Restart) {
   RunOnIOThread(base::Bind(&self::SetUpRegistrationAndListenerOnIOThread,
                            base::Unretained(this),
                            "/service_worker/worker.js"));
@@ -1891,7 +1903,7 @@
 const int ServiceWorkerV8CacheStrategiesTest::kV8CacheTimeStampDataSize =
     sizeof(unsigned) + sizeof(double);
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesTest,
                        V8CacheOnCacheStorage) {
   // The strategy is "aggressive" on default.
   CheckStrategyIsAggressive();
@@ -1911,7 +1923,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesNoneTest);
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesNoneTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesNoneTest,
                        V8CacheOnCacheStorage) {
   CheckStrategyIsNone();
 }
@@ -1930,7 +1942,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesNormalTest);
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesNormalTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesNormalTest,
                        V8CacheOnCacheStorage) {
   CheckStrategyIsNormal();
 }
@@ -1949,7 +1961,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerV8CacheStrategiesAggressiveTest);
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerV8CacheStrategiesAggressiveTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerV8CacheStrategiesAggressiveTest,
                        V8CacheOnCacheStorage) {
   CheckStrategyIsAggressive();
 }
@@ -2000,7 +2012,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDisableWebSecurityTest);
 };
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest,
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest,
                        GetRegistrationNoCrash) {
   const char kPageUrl[] =
       "/service_worker/disable_web_security_get_registration.html";
@@ -2008,13 +2020,13 @@
   RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, RegisterNoCrash) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, RegisterNoCrash) {
   const char kPageUrl[] = "/service_worker/disable_web_security_register.html";
   const char kScopeUrl[] = "/service_worker/";
   RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UnregisterNoCrash) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, UnregisterNoCrash) {
   const char kPageUrl[] =
       "/service_worker/disable_web_security_unregister.html";
   const char kScopeUrl[] = "/service_worker/scope/";
@@ -2023,7 +2035,7 @@
   RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
 }
 
-IN_PROC_BROWSER_TEST_F(ServiceWorkerDisableWebSecurityTest, UpdateNoCrash) {
+IN_PROC_BROWSER_TEST_P(ServiceWorkerDisableWebSecurityTest, UpdateNoCrash) {
   const char kPageUrl[] = "/service_worker/disable_web_security_update.html";
   const char kScopeUrl[] = "/service_worker/scope/";
   const char kWorkerUrl[] = "/service_worker/fetch_event_blob.js";
@@ -2031,4 +2043,32 @@
   RunTestWithCrossOriginURL(kPageUrl, kScopeUrl);
 }
 
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerBrowserTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerVersionBrowserV8CacheTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerVersionBrowserTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerBlackBoxBrowserTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerV8CacheStrategiesTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerV8CacheStrategiesNoneTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerV8CacheStrategiesNormalTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerV8CacheStrategiesAggressiveTest,
+                        ::testing::Values(true, false));
+INSTANTIATE_TEST_CASE_P(ServiceWorkerBrowserTest,
+                        ServiceWorkerDisableWebSecurityTest,
+                        ::testing::Values(true, false));
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 7762d42..50ed74f0 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -1620,7 +1620,7 @@
     ASSERT_TRUE(start_msg);
     EmbeddedWorkerMsg_StartWorker::Param param;
     EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
-    EmbeddedWorkerMsg_StartWorker_Params start_params = std::get<0>(param);
+    const EmbeddedWorkerStartParams& start_params = std::get<0>(param);
     EXPECT_FALSE(start_params.pause_after_download);
     sink->ClearMessages();
   }
@@ -1635,7 +1635,7 @@
     ASSERT_TRUE(start_msg);
     EmbeddedWorkerMsg_StartWorker::Param param;
     EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
-    EmbeddedWorkerMsg_StartWorker_Params start_params = std::get<0>(param);
+    const EmbeddedWorkerStartParams& start_params = std::get<0>(param);
     EXPECT_TRUE(start_params.pause_after_download);
     sink->ClearMessages();
   }
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 7c33cb28..337e676 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -35,6 +35,7 @@
 #include "content/browser/service_worker/service_worker_metrics.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/common/service_worker/embedded_worker_messages.h"
+#include "content/common/service_worker/embedded_worker_start_params.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "content/common/service_worker/service_worker_type_converters.h"
 #include "content/common/service_worker/service_worker_utils.h"
@@ -1406,8 +1407,8 @@
 
   StartTimeoutTimer();
 
-  std::unique_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
-      new EmbeddedWorkerMsg_StartWorker_Params());
+  std::unique_ptr<EmbeddedWorkerStartParams> params(
+      new EmbeddedWorkerStartParams());
   params->service_worker_version_id = version_id_;
   params->scope = scope_;
   params->script_url = script_url_;
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index df6d152..63e8ba5 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -306,6 +306,8 @@
     "send_zygote_child_ping_linux.cc",
     "service_worker/embedded_worker_messages.h",
     "service_worker/embedded_worker_settings.h",
+    "service_worker/embedded_worker_start_params.cc",
+    "service_worker/embedded_worker_start_params.h",
     "service_worker/service_worker_client_info.cc",
     "service_worker/service_worker_client_info.h",
     "service_worker/service_worker_messages.h",
@@ -564,6 +566,7 @@
     "render_frame_message_filter.mojom",
     "render_message_filter.mojom",
     "render_widget_window_tree_client_factory.mojom",
+    "service_worker/embedded_worker.mojom",
     "service_worker/embedded_worker_setup.mojom",
     "storage_partition_service.mojom",
     "url_loader.mojom",
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
new file mode 100644
index 0000000..d15d62b
--- /dev/null
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -0,0 +1,16 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content.mojom;
+
+import "services/shell/public/interfaces/interface_provider.mojom";
+import "url/mojo/url.mojom";
+
+[Native]
+struct EmbeddedWorkerStartParams;
+
+// Interface to control a renderer-side worker's environment.
+interface EmbeddedWorkerInstanceClient {
+  StartWorker(EmbeddedWorkerStartParams params);
+};
diff --git a/content/common/service_worker/embedded_worker.typemap b/content/common/service_worker/embedded_worker.typemap
new file mode 100644
index 0000000..664936b
--- /dev/null
+++ b/content/common/service_worker/embedded_worker.typemap
@@ -0,0 +1,10 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//content/common/service_worker/embedded_worker.mojom"
+public_headers =
+    [ "//content/common/service_worker/embedded_worker_start_params.h" ]
+traits_headers =
+    [ "//content/common/service_worker/embedded_worker_messages.h" ]
+type_mappings = [ "content.mojom.EmbeddedWorkerStartParams=::content::EmbeddedWorkerStartParams" ]
diff --git a/content/common/service_worker/embedded_worker_messages.h b/content/common/service_worker/embedded_worker_messages.h
index a245c4e0..34dc1eb 100644
--- a/content/common/service_worker/embedded_worker_messages.h
+++ b/content/common/service_worker/embedded_worker_messages.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "content/common/service_worker/embedded_worker_settings.h"
+#include "content/common/service_worker/embedded_worker_start_params.h"
 #include "content/public/common/console_message_level.h"
 #include "content/public/common/web_preferences.h"
 #include "ipc/ipc_message.h"
@@ -27,17 +28,17 @@
 IPC_STRUCT_TRAITS_END()
 
 // Parameters structure for EmbeddedWorkerMsg_StartWorker.
-IPC_STRUCT_BEGIN(EmbeddedWorkerMsg_StartWorker_Params)
-  IPC_STRUCT_MEMBER(int, embedded_worker_id)
-  IPC_STRUCT_MEMBER(int64_t, service_worker_version_id)
-  IPC_STRUCT_MEMBER(GURL, scope)
-  IPC_STRUCT_MEMBER(GURL, script_url)
-  IPC_STRUCT_MEMBER(int, worker_devtools_agent_route_id)
-  IPC_STRUCT_MEMBER(bool, pause_after_download)
-  IPC_STRUCT_MEMBER(bool, wait_for_debugger)
-  IPC_STRUCT_MEMBER(bool, is_installed)
-  IPC_STRUCT_MEMBER(content::EmbeddedWorkerSettings, settings)
-IPC_STRUCT_END()
+IPC_STRUCT_TRAITS_BEGIN(content::EmbeddedWorkerStartParams)
+  IPC_STRUCT_TRAITS_MEMBER(embedded_worker_id)
+  IPC_STRUCT_TRAITS_MEMBER(service_worker_version_id)
+  IPC_STRUCT_TRAITS_MEMBER(scope)
+  IPC_STRUCT_TRAITS_MEMBER(script_url)
+  IPC_STRUCT_TRAITS_MEMBER(worker_devtools_agent_route_id)
+  IPC_STRUCT_TRAITS_MEMBER(pause_after_download)
+  IPC_STRUCT_TRAITS_MEMBER(wait_for_debugger)
+  IPC_STRUCT_TRAITS_MEMBER(is_installed)
+  IPC_STRUCT_TRAITS_MEMBER(settings)
+IPC_STRUCT_TRAITS_END()
 
 // Parameters structure for EmbeddedWorkerHostMsg_ReportConsoleMessage.
 // The data members directly correspond to parameters of
@@ -52,7 +53,7 @@
 
 // Browser -> Renderer message to create a new embedded worker context.
 IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_StartWorker,
-                     EmbeddedWorkerMsg_StartWorker_Params /* params */)
+                     content::EmbeddedWorkerStartParams /* params */)
 
 // Browser -> Renderer message to resume a worker that has been started
 // with the pause_after_download option.
diff --git a/content/common/service_worker/embedded_worker_start_params.cc b/content/common/service_worker/embedded_worker_start_params.cc
new file mode 100644
index 0000000..93f62ff
--- /dev/null
+++ b/content/common/service_worker/embedded_worker_start_params.cc
@@ -0,0 +1,11 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/service_worker/embedded_worker_start_params.h"
+
+namespace content {
+
+EmbeddedWorkerStartParams::EmbeddedWorkerStartParams() {}
+
+}  // namespace content
diff --git a/content/common/service_worker/embedded_worker_start_params.h b/content/common/service_worker/embedded_worker_start_params.h
new file mode 100644
index 0000000..9e2ef2a5
--- /dev/null
+++ b/content/common/service_worker/embedded_worker_start_params.h
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/content_export.h"
+#include "content/common/service_worker/embedded_worker_settings.h"
+#include "url/gurl.h"
+
+#ifndef CONTENT_COMMON_SERVICE_WORKER_EMBEDDED_WORKER_START_PARAMS_H_
+#define CONTENT_COMMON_SERVICE_WORKER_EMBEDDED_WORKER_START_PARAMS_H_
+
+namespace content {
+
+struct CONTENT_EXPORT EmbeddedWorkerStartParams {
+  EmbeddedWorkerStartParams();
+
+  int embedded_worker_id;
+  int64_t service_worker_version_id;
+  GURL scope;
+  GURL script_url;
+  int worker_devtools_agent_route_id;
+  bool pause_after_download;
+  bool wait_for_debugger;
+  bool is_installed;
+  EmbeddedWorkerSettings settings;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_COMMON_SERVICE_WORKER_EMBEDDED_WORKER_START_PARAMS_H_
diff --git a/content/common/service_worker/service_worker_utils.cc b/content/common/service_worker/service_worker_utils.cc
index 30faed4..fb3e7251 100644
--- a/content/common/service_worker/service_worker_utils.cc
+++ b/content/common/service_worker/service_worker_utils.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "base/command_line.h"
 #include "base/logging.h"
 #include "base/strings/string_util.h"
 #include "content/public/common/origin_util.h"
@@ -118,6 +119,12 @@
          OriginCanAccessServiceWorkers(script_url);
 }
 
+// static
+bool ServiceWorkerUtils::IsMojoForServiceWorkerEnabled() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kMojoServiceWorker);
+}
+
 bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
   if (!ServiceWorkerUtils::ScopeMatches(scope, url_))
     return false;
diff --git a/content/common/service_worker/service_worker_utils.h b/content/common/service_worker/service_worker_utils.h
index 4ea403a3..b0c3cc8de 100644
--- a/content/common/service_worker/service_worker_utils.h
+++ b/content/common/service_worker/service_worker_utils.h
@@ -46,6 +46,8 @@
                                        const GURL& pattern,
                                        const GURL& script_url);
 
+  static bool IsMojoForServiceWorkerEnabled();
+
   // Returns true when '--disable-web-security' flag is set. Otherwise returns
   // whether the all origins of |urls| are same as the origin of |url|.
   template <typename... Args>
diff --git a/content/common/typemaps.gni b/content/common/typemaps.gni
index 2dd3ed67..1b08a89 100644
--- a/content/common/typemaps.gni
+++ b/content/common/typemaps.gni
@@ -6,4 +6,5 @@
   "//content/common/url_loader_status.typemap",
   "//content/common/url_request.typemap",
   "//content/common/url_response_head.typemap",
+  "//content/common/service_worker/embedded_worker.typemap",
 ]
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json
index 399f7dc..bfb147b 100644
--- a/content/public/app/mojo/content_renderer_manifest.json
+++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -6,6 +6,7 @@
     "provided": {
       "all_interfaces": [ "*" ],
       "browser": [
+        "content::mojom::EmbeddedWorkerInstanceClient",
         "content::mojom::EmbeddedWorkerSetup",
         "content::mojom::FrameFactory",
         "content::mojom::TestMojoService",
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 223d56d..2db58be 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -653,6 +653,9 @@
 // Use a Mojo-based LocalStorage implementation.
 const char kMojoLocalStorage[]              = "mojo-local-storage";
 
+// Use a Mojo-based ServiceWorker implementation.
+const char kMojoServiceWorker[]             = "mojo-service-worker";
+
 // Mutes audio sent to the audio device so it is not audible during
 // automated testing.
 const char kMuteAudio[]                     = "mute-audio";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 4d065ca..3a36973a 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -197,6 +197,7 @@
 CONTENT_EXPORT extern const char kMHTMLSkipNostoreMain[];
 CONTENT_EXPORT extern const char kMHTMLSkipNostoreAll[];
 CONTENT_EXPORT extern const char kMojoLocalStorage[];
+CONTENT_EXPORT extern const char kMojoServiceWorker[];
 CONTENT_EXPORT extern const char kMuteAudio[];
 CONTENT_EXPORT extern const char kNoReferrers[];
 CONTENT_EXPORT extern const char kNoSandbox[];
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 8df6b73..cb51761 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -345,6 +345,8 @@
     "service_worker/embedded_worker_devtools_agent.h",
     "service_worker/embedded_worker_dispatcher.cc",
     "service_worker/embedded_worker_dispatcher.h",
+    "service_worker/embedded_worker_instance_client_impl.cc",
+    "service_worker/embedded_worker_instance_client_impl.h",
     "service_worker/service_worker_context_client.cc",
     "service_worker/service_worker_context_client.h",
     "service_worker/service_worker_context_message_filter.cc",
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 8160520..96b146c 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -119,6 +119,7 @@
 #include "content/renderer/renderer_blink_platform_impl.h"
 #include "content/renderer/scheduler/resource_dispatch_throttler.h"
 #include "content/renderer/service_worker/embedded_worker_dispatcher.h"
+#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
 #include "content/renderer/service_worker/service_worker_context_client.h"
 #include "content/renderer/service_worker/service_worker_context_message_filter.h"
 #include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
@@ -848,8 +849,11 @@
   GetContentClient()->renderer()->ExposeInterfacesToBrowser(
       GetInterfaceRegistry());
 
-  GetInterfaceRegistry()->AddInterface(base::Bind(CreateFrameFactory));
-  GetInterfaceRegistry()->AddInterface(base::Bind(CreateEmbeddedWorkerSetup));
+  GetInterfaceRegistry()->AddInterface(base::Bind(&CreateFrameFactory));
+  GetInterfaceRegistry()->AddInterface(base::Bind(&CreateEmbeddedWorkerSetup));
+  GetInterfaceRegistry()->AddInterface(
+      base::Bind(&EmbeddedWorkerInstanceClientImpl::Create,
+                 base::Unretained(embedded_worker_dispatcher_.get())));
 
   GetRemoteInterfaces()->GetInterface(
       mojo::GetProxy(&storage_partition_service_));
diff --git a/content/renderer/service_worker/embedded_worker_dispatcher.cc b/content/renderer/service_worker/embedded_worker_dispatcher.cc
index ec12c06d..bd49677 100644
--- a/content/renderer/service_worker/embedded_worker_dispatcher.cc
+++ b/content/renderer/service_worker/embedded_worker_dispatcher.cc
@@ -10,7 +10,6 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/child/child_process.h"
-#include "content/child/scoped_child_process_reference.h"
 #include "content/child/thread_safe_sender.h"
 #include "content/child/worker_thread_registry.h"
 #include "content/common/devtools_messages.h"
@@ -27,23 +26,14 @@
 
 namespace content {
 
-// A thin wrapper of WebEmbeddedWorker which also adds and releases process
-// references automatically.
-class EmbeddedWorkerDispatcher::WorkerWrapper {
- public:
-  WorkerWrapper(blink::WebEmbeddedWorker* worker, int devtools_agent_route_id)
-      : worker_(worker),
-        dev_tools_agent_(
-            new EmbeddedWorkerDevToolsAgent(worker, devtools_agent_route_id)) {}
-  ~WorkerWrapper() {}
+EmbeddedWorkerDispatcher::WorkerWrapper::WorkerWrapper(
+    blink::WebEmbeddedWorker* worker,
+    int devtools_agent_route_id)
+    : worker_(worker),
+      dev_tools_agent_(
+          new EmbeddedWorkerDevToolsAgent(worker, devtools_agent_route_id)) {}
 
-  blink::WebEmbeddedWorker* worker() { return worker_.get(); }
-
- private:
-  ScopedChildProcessReference process_ref_;
-  std::unique_ptr<blink::WebEmbeddedWorker> worker_;
-  std::unique_ptr<EmbeddedWorkerDevToolsAgent> dev_tools_agent_;
-};
+EmbeddedWorkerDispatcher::WorkerWrapper::~WorkerWrapper() {}
 
 EmbeddedWorkerDispatcher::EmbeddedWorkerDispatcher() : weak_factory_(this) {}
 
@@ -79,35 +69,15 @@
 }
 
 void EmbeddedWorkerDispatcher::OnStartWorker(
-    const EmbeddedWorkerMsg_StartWorker_Params& params) {
+    const EmbeddedWorkerStartParams& params) {
   DCHECK(!workers_.Lookup(params.embedded_worker_id));
   TRACE_EVENT0("ServiceWorker", "EmbeddedWorkerDispatcher::OnStartWorker");
-  std::unique_ptr<WorkerWrapper> wrapper(new WorkerWrapper(
-      blink::WebEmbeddedWorker::create(
-          new ServiceWorkerContextClient(params.embedded_worker_id,
-                                         params.service_worker_version_id,
-                                         params.scope, params.script_url,
-                                         params.worker_devtools_agent_route_id),
-          NULL),
-      params.worker_devtools_agent_route_id));
-
-  blink::WebEmbeddedWorkerStartData start_data;
-  start_data.scriptURL = params.script_url;
-  start_data.userAgent = base::UTF8ToUTF16(GetContentClient()->GetUserAgent());
-  start_data.waitForDebuggerMode =
-      params.wait_for_debugger ?
-          blink::WebEmbeddedWorkerStartData::WaitForDebugger :
-          blink::WebEmbeddedWorkerStartData::DontWaitForDebugger;
-  start_data.v8CacheOptions = static_cast<blink::WebSettings::V8CacheOptions>(
-      params.settings.v8_cache_options);
-  start_data.dataSaverEnabled = params.settings.data_saver_enabled;
-  start_data.pauseAfterDownloadMode =
-      params.pause_after_download
-          ? blink::WebEmbeddedWorkerStartData::PauseAfterDownload
-          : blink::WebEmbeddedWorkerStartData::DontPauseAfterDownload;
-
-  wrapper->worker()->startWorkerContext(start_data);
-  workers_.AddWithID(wrapper.release(), params.embedded_worker_id);
+  std::unique_ptr<WorkerWrapper> wrapper = StartWorkerContext(
+      params, base::MakeUnique<ServiceWorkerContextClient>(
+                  params.embedded_worker_id, params.service_worker_version_id,
+                  params.scope, params.script_url,
+                  params.worker_devtools_agent_route_id));
+  RegisterWorker(params.embedded_worker_id, std::move(wrapper));
 }
 
 void EmbeddedWorkerDispatcher::OnStopWorker(int embedded_worker_id) {
@@ -163,4 +133,37 @@
       target_level, blink::WebString::fromUTF8(message)));
 }
 
+std::unique_ptr<EmbeddedWorkerDispatcher::WorkerWrapper>
+EmbeddedWorkerDispatcher::StartWorkerContext(
+    const EmbeddedWorkerStartParams& params,
+    std::unique_ptr<ServiceWorkerContextClient> context_client) {
+  std::unique_ptr<WorkerWrapper> wrapper(new WorkerWrapper(
+      blink::WebEmbeddedWorker::create(context_client.release(), nullptr),
+      params.worker_devtools_agent_route_id));
+
+  blink::WebEmbeddedWorkerStartData start_data;
+  start_data.scriptURL = params.script_url;
+  start_data.userAgent = base::UTF8ToUTF16(GetContentClient()->GetUserAgent());
+  start_data.waitForDebuggerMode =
+      params.wait_for_debugger
+          ? blink::WebEmbeddedWorkerStartData::WaitForDebugger
+          : blink::WebEmbeddedWorkerStartData::DontWaitForDebugger;
+  start_data.v8CacheOptions = static_cast<blink::WebSettings::V8CacheOptions>(
+      params.settings.v8_cache_options);
+  start_data.dataSaverEnabled = params.settings.data_saver_enabled;
+  start_data.pauseAfterDownloadMode =
+      params.pause_after_download
+          ? blink::WebEmbeddedWorkerStartData::PauseAfterDownload
+          : blink::WebEmbeddedWorkerStartData::DontPauseAfterDownload;
+
+  wrapper->worker()->startWorkerContext(start_data);
+  return wrapper;
+}
+
+void EmbeddedWorkerDispatcher::RegisterWorker(
+    int embedded_worker_id,
+    std::unique_ptr<WorkerWrapper> wrapper) {
+  workers_.AddWithID(wrapper.release(), embedded_worker_id);
+}
+
 }  // namespace content
diff --git a/content/renderer/service_worker/embedded_worker_dispatcher.h b/content/renderer/service_worker/embedded_worker_dispatcher.h
index e77086f7..9c706fa8 100644
--- a/content/renderer/service_worker/embedded_worker_dispatcher.h
+++ b/content/renderer/service_worker/embedded_worker_dispatcher.h
@@ -6,19 +6,30 @@
 #define CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_DISPATCHER_H_
 
 #include <map>
+#include <memory>
 
 #include "base/id_map.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
+#include "content/child/scoped_child_process_reference.h"
 #include "content/public/common/console_message_level.h"
 #include "ipc/ipc_listener.h"
 
-struct EmbeddedWorkerMsg_StartWorker_Params;
 class GURL;
 
+namespace blink {
+
+class WebEmbeddedWorker;
+
+}  // namespace blink
+
 namespace content {
 
+class EmbeddedWorkerDevToolsAgent;
+class ServiceWorkerContextClient;
+struct EmbeddedWorkerStartParams;
+
 // A tiny dispatcher which handles embedded worker start/stop messages.
 class EmbeddedWorkerDispatcher : public IPC::Listener {
  public:
@@ -31,15 +42,37 @@
   void WorkerContextDestroyed(int embedded_worker_id);
 
  private:
-  class WorkerWrapper;
+  friend class EmbeddedWorkerInstanceClientImpl;
 
-  void OnStartWorker(const EmbeddedWorkerMsg_StartWorker_Params& params);
+  // A thin wrapper of WebEmbeddedWorker which also adds and releases process
+  // references automatically.
+  class WorkerWrapper {
+   public:
+    WorkerWrapper(blink::WebEmbeddedWorker* worker,
+                  int devtools_agent_route_id);
+    ~WorkerWrapper();
+
+    blink::WebEmbeddedWorker* worker() { return worker_.get(); }
+
+   private:
+    ScopedChildProcessReference process_ref_;
+    std::unique_ptr<blink::WebEmbeddedWorker> worker_;
+    std::unique_ptr<EmbeddedWorkerDevToolsAgent> dev_tools_agent_;
+  };
+
+  void OnStartWorker(const EmbeddedWorkerStartParams& params);
   void OnStopWorker(int embedded_worker_id);
   void OnResumeAfterDownload(int embedded_worker_id);
   void OnAddMessageToConsole(int embedded_worker_id,
                              ConsoleMessageLevel level,
                              const std::string& message);
 
+  std::unique_ptr<WorkerWrapper> StartWorkerContext(
+      const EmbeddedWorkerStartParams& params,
+      std::unique_ptr<ServiceWorkerContextClient> context_client);
+  void RegisterWorker(int embedded_worker_id,
+                      std::unique_ptr<WorkerWrapper> wrapper);
+
   IDMap<WorkerWrapper, IDMapOwnPointer> workers_;
   std::map<int /* embedded_worker_id */, base::TimeTicks> stop_worker_times_;
   base::WeakPtrFactory<EmbeddedWorkerDispatcher> weak_factory_;
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
new file mode 100644
index 0000000..1d045dd
--- /dev/null
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/service_worker/embedded_worker_instance_client_impl.h"
+
+#include <memory>
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/child/scoped_child_process_reference.h"
+#include "content/common/service_worker/embedded_worker_messages.h"
+#include "content/public/common/content_client.h"
+#include "content/renderer/service_worker/embedded_worker_devtools_agent.h"
+#include "content/renderer/service_worker/service_worker_context_client.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/WebKit/public/web/WebEmbeddedWorker.h"
+#include "third_party/WebKit/public/web/WebEmbeddedWorkerStartData.h"
+
+namespace content {
+
+namespace {
+
+void OnError() {
+  // TODO(shimazu): Implement here
+  NOTIMPLEMENTED();
+}
+
+}  // namespace
+
+// static
+void EmbeddedWorkerInstanceClientImpl::Create(
+    EmbeddedWorkerDispatcher* dispatcher,
+    mojo::InterfaceRequest<mojom::EmbeddedWorkerInstanceClient> request) {
+  auto binding = mojo::MakeStrongBinding(
+      base::MakeUnique<EmbeddedWorkerInstanceClientImpl>(dispatcher),
+      std::move(request));
+  binding->set_connection_error_handler(base::Bind(&OnError));
+}
+
+void EmbeddedWorkerInstanceClientImpl::StartWorker(
+    const EmbeddedWorkerStartParams& params) {
+  TRACE_EVENT0("ServiceWorker",
+               "EmbeddedWorkerInstanceClientImpl::StartWorker");
+
+  std::unique_ptr<EmbeddedWorkerDispatcher::WorkerWrapper> wrapper =
+      dispatcher_->StartWorkerContext(
+          params,
+          base::MakeUnique<ServiceWorkerContextClient>(
+              params.embedded_worker_id, params.service_worker_version_id,
+              params.scope, params.script_url,
+              params.worker_devtools_agent_route_id));
+  wrapper_ = wrapper.get();
+  dispatcher_->RegisterWorker(params.embedded_worker_id, std::move(wrapper));
+}
+
+EmbeddedWorkerInstanceClientImpl::EmbeddedWorkerInstanceClientImpl(
+    EmbeddedWorkerDispatcher* dispatcher)
+    : dispatcher_(dispatcher) {}
+
+EmbeddedWorkerInstanceClientImpl::~EmbeddedWorkerInstanceClientImpl() {}
+
+}  // namespace content
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.h b/content/renderer/service_worker/embedded_worker_instance_client_impl.h
new file mode 100644
index 0000000..893ae1d
--- /dev/null
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_CLIENT_IMPL_H_
+#define CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_CLIENT_IMPL_H_
+
+#include "base/id_map.h"
+#include "content/common/service_worker/embedded_worker.mojom.h"
+#include "content/renderer/service_worker/embedded_worker_dispatcher.h"
+
+namespace content {
+
+class EmbeddedWorkerInstanceClientImpl
+    : public mojom::EmbeddedWorkerInstanceClient {
+ public:
+  static void Create(
+      EmbeddedWorkerDispatcher* dispatcher,
+      mojo::InterfaceRequest<mojom::EmbeddedWorkerInstanceClient> request);
+
+  explicit EmbeddedWorkerInstanceClientImpl(
+      EmbeddedWorkerDispatcher* dispatcher);
+  ~EmbeddedWorkerInstanceClientImpl() override;
+
+  // Implementation of mojo interface
+  void StartWorker(const EmbeddedWorkerStartParams& params) override;
+
+ private:
+  EmbeddedWorkerDispatcher* dispatcher_;
+
+  EmbeddedWorkerDispatcher::WorkerWrapper* wrapper_;
+
+  DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceClientImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_SERVICE_WORKER_EMBEDDED_WORKER_INSTANCE_CLIENT_IMPL_H_
diff --git a/device/media_transfer_protocol/BUILD.gn b/device/media_transfer_protocol/BUILD.gn
index d3ced9153f..4175651 100644
--- a/device/media_transfer_protocol/BUILD.gn
+++ b/device/media_transfer_protocol/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/features.gni")
 import("//third_party/protobuf/proto_library.gni")
 
+assert(is_chromeos)
 assert(use_dbus)
 
 proto_library("mtp_file_entry_proto") {
@@ -34,13 +35,8 @@
     ":mtp_storage_info_proto",
     "//base",
   ]
-  if (use_dbus) {
-    deps = [
-      "//dbus",
-    ]
-  }
-
-  if (is_chromeos) {
-    deps += [ "//chromeos" ]
-  }
+  deps = [
+    "//chromeos",
+    "//dbus",
+  ]
 }
diff --git a/extensions/renderer/i18n_custom_bindings.cc b/extensions/renderer/i18n_custom_bindings.cc
index 7799d9d..34dd6c89 100644
--- a/extensions/renderer/i18n_custom_bindings.cc
+++ b/extensions/renderer/i18n_custom_bindings.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
@@ -135,6 +136,7 @@
     LanguageDetectionResult* result) {
   std::vector<std::unique_ptr<DetectedLanguage>>* detected_languages =
       &result->languages;
+  DCHECK(detected_languages->empty());
   bool* is_reliable = &result->is_reliable;
 
   // is_reliable is set to "true", so that the reliability can be calculated by
@@ -144,20 +146,33 @@
     const chrome_lang_id::NNetLanguageIdentifier::Result& lang_result =
         lang_results.at(i);
     const std::string& language_code = lang_result.language;
+
+    // If a language is kUnknown, then the remaining ones are also kUnknown.
     if (language_code == chrome_lang_id::NNetLanguageIdentifier::kUnknown) {
-      // If the first language is kUnknown, then all languages are kUnknown.
-      // Thus, is_reliable is set to "false".
-      if (i == 0) {
-        *is_reliable = false;
-      }
       break;
     }
 
+    // The list of languages supported by CLD3 is saved in kLanguageNames
+    // in the following file:
+    // //src/third_party/cld_3/src/src/task_context_params.cc
+    // Among the entries in this list are transliterated languages
+    // (called xx-Latn) which don't belong to the spec ISO639-1 used by
+    // the previous model, CLD2. Thus, to maintain backwards compatibility,
+    // xx-Latn predictions are ignored for now.
+    if (base::EndsWith(language_code, "-Latn",
+                       base::CompareCase::INSENSITIVE_ASCII)) {
+      continue;
+    }
+
     *is_reliable = *is_reliable && lang_result.is_reliable;
     const int percent = static_cast<int>(100 * lang_result.proportion);
     detected_languages->push_back(
         base::MakeUnique<DetectedLanguage>(language_code, percent));
   }
+
+  if (detected_languages->empty()) {
+    *is_reliable = false;
+  }
 }
 #else
 # error "CLD_VERSION must be 2 or 3"
diff --git a/infra/config/recipes.cfg b/infra/config/recipes.cfg
index f35dcde..dd76de7 100644
--- a/infra/config/recipes.cfg
+++ b/infra/config/recipes.cfg
@@ -5,7 +5,7 @@
   project_id: "build"
   url: "https://chromium.googlesource.com/chromium/tools/build.git"
   branch: "master"
-  revision: "64d2a7926de02d5dbacc5cc8ba7a09f626cc6eaf"
+  revision: "597c27e7cd712b9a07dd091a44f22af5b957c54a"
 }
 deps {
   project_id: "depot_tools"
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 6ca1743..ae654fe 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -3327,12 +3327,16 @@
     // Purge web view if last committed URL is different from the document URL.
     // This can happen if external URL was added to the navigation stack and was
     // loaded using Go Back or Go Forward navigation (in which case document URL
-    // will point to the previous page).
-    GURL lastCommittedURL =
-        self.webState->GetNavigationManager()->GetLastCommittedItem()->GetURL();
-    if (lastCommittedURL != _documentURL) {
-      [self requirePageReconstruction];
-      [self setDocumentURL:lastCommittedURL];
+    // will point to the previous page).  If this is the first load for a
+    // NavigationManager, there will be no last committed item, so check here.
+    web::NavigationItem* lastCommittedItem =
+        self.webState->GetNavigationManager()->GetLastCommittedItem();
+    if (lastCommittedItem) {
+      GURL lastCommittedURL = lastCommittedItem->GetURL();
+      if (lastCommittedURL != _documentURL) {
+        [self requirePageReconstruction];
+        [self setDocumentURL:lastCommittedURL];
+      }
     }
 
     if ([_delegate openExternalURL:requestURL
@@ -4797,6 +4801,10 @@
 
   GURL requestURL = net::GURLWithNSURL(action.request.URL);
 
+  // Don't create web views for invalid URLs.
+  if (!requestURL.is_valid())
+    return nil;
+
   if (![self userIsInteracting]) {
     NSString* referer = [self refererFromNavigationAction:action];
     GURL referrerURL =
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 3f87c8e..f59e9d4d 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -401,6 +401,17 @@
     // Avoids hitting CHECK in dtor of AudioManagerBase.
     stream->Close();
   }
+  // Perform same type of cleanup as above but for high-latency input streams.
+  auto basic_input_streams_copy = basic_input_streams_;
+  for (auto* stream : basic_input_streams_copy) {
+    LOG(WARNING)
+        << "Closing existing high-latency audio input stream at destruction";
+    // Prevents active AudioQueue callbacks to use possibly invalid objects
+    // in its OnData() callback.
+    stream->Stop();
+    // Avoids hitting CHECK in dtor of AudioManagerBase.
+    stream->Close();
+  }
   Shutdown();
 }
 
diff --git a/media/gpu/media_foundation_video_encode_accelerator_win.cc b/media/gpu/media_foundation_video_encode_accelerator_win.cc
index 71ecb0e..2058a16 100644
--- a/media/gpu/media_foundation_video_encode_accelerator_win.cc
+++ b/media/gpu/media_foundation_video_encode_accelerator_win.cc
@@ -481,7 +481,7 @@
     DVLOG(3) << "No bitstream buffers.";
     // We need to copy the output so that encoding can continue.
     std::unique_ptr<EncodeOutput> encode_output(
-        new EncodeOutput(size, keyframe, base::TimeDelta()));
+        new EncodeOutput(size, keyframe, base::Time::Now() - base::Time()));
     {
       MediaBufferScopedPointer scoped_buffer(output_buffer.get());
       memcpy(encode_output->memory(), scoped_buffer.get(), size);
@@ -500,8 +500,9 @@
   }
 
   client_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
-                            buffer_ref->id, size, keyframe, base::TimeDelta()));
+      FROM_HERE,
+      base::Bind(&Client::BitstreamBufferReady, client_, buffer_ref->id, size,
+                 keyframe, base::Time::Now() - base::Time()));
 
   // Keep calling ProcessOutput recursively until MF_E_TRANSFORM_NEED_MORE_INPUT
   // is returned to flush out all the output.
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc
index b01cc8fe..a3f468d 100644
--- a/net/http/transport_security_state.cc
+++ b/net/http/transport_security_state.cc
@@ -813,7 +813,8 @@
                                    &serialized_report)) {
     return;
   }
-  report_sender_->Send(expect_staple_state.report_uri, serialized_report);
+  report_sender_->Send(expect_staple_state.report_uri,
+                       "application/json; charset=utf-8", serialized_report);
 }
 
 bool TransportSecurityState::HasPublicKeyPins(const std::string& host) {
@@ -1071,7 +1072,8 @@
       base::TimeTicks::Now() +
           base::TimeDelta::FromMinutes(kTimeToRememberHPKPReportsMins));
 
-  report_sender_->Send(pkp_state.report_uri, serialized_report);
+  report_sender_->Send(pkp_state.report_uri, "application/json; charset=utf-8",
+                       serialized_report);
   return PKPStatus::VIOLATED;
 }
 
diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h
index 14ddfc0..3326ca2 100644
--- a/net/http/transport_security_state.h
+++ b/net/http/transport_security_state.h
@@ -13,6 +13,7 @@
 #include "base/callback.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/strings/string_piece.h"
 #include "base/threading/non_thread_safe.h"
 #include "base/time/time.h"
 #include "net/base/expiring_cache.h"
@@ -252,8 +253,12 @@
   // An interface for asynchronously sending HPKP violation reports.
   class NET_EXPORT ReportSenderInterface {
    public:
-    // Sends the given serialized |report| to |report_uri|.
-    virtual void Send(const GURL& report_uri, const std::string& report) = 0;
+    // Sends the given serialized |report| to |report_uri| with
+    // Content-Type header as specified in
+    // |content_type|. |content_type| should be non-empty.
+    virtual void Send(const GURL& report_uri,
+                      base::StringPiece content_type,
+                      base::StringPiece report) = 0;
 
     // Sets a callback to be called when report sending fails.
     virtual void SetErrorCallback(
diff --git a/net/http/transport_security_state_unittest.cc b/net/http/transport_security_state_unittest.cc
index 2026aa5..35536d91 100644
--- a/net/http/transport_security_state_unittest.cc
+++ b/net/http/transport_security_state_unittest.cc
@@ -90,9 +90,12 @@
   MockCertificateReportSender() {}
   ~MockCertificateReportSender() override {}
 
-  void Send(const GURL& report_uri, const std::string& report) override {
+  void Send(const GURL& report_uri,
+            base::StringPiece content_type,
+            base::StringPiece report) override {
     latest_report_uri_ = report_uri;
-    latest_report_ = report;
+    report.CopyToString(&latest_report_);
+    content_type.CopyToString(&latest_content_type_);
   }
 
   void SetErrorCallback(
@@ -101,14 +104,17 @@
   void Clear() {
     latest_report_uri_ = GURL();
     latest_report_ = std::string();
+    latest_content_type_ = std::string();
   }
 
   const GURL& latest_report_uri() { return latest_report_uri_; }
   const std::string& latest_report() { return latest_report_; }
+  const std::string& latest_content_type() { return latest_content_type_; }
 
  private:
   GURL latest_report_uri_;
   std::string latest_report_;
+  std::string latest_content_type_;
 };
 
 // A mock ReportSenderInterface that simulates a net error on every report sent.
@@ -121,7 +127,9 @@
   int net_error() { return net_error_; }
 
   // TransportSecurityState::ReportSenderInterface:
-  void Send(const GURL& report_uri, const std::string& report) override {
+  void Send(const GURL& report_uri,
+            base::StringPiece content_type,
+            base::StringPiece report) override {
     ASSERT_FALSE(error_callback_.is_null());
     error_callback_.Run(report_uri, net_error_);
   }
@@ -339,6 +347,7 @@
   state->SetReportSender(reporter);
   state->CheckExpectStaple(host_port, ssl_info, ocsp_response);
   EXPECT_EQ(GURL(kExpectStapleStaticReportURI), reporter->latest_report_uri());
+  EXPECT_EQ("application/json; charset=utf-8", reporter->latest_content_type());
   std::string serialized_report = reporter->latest_report();
   EXPECT_NO_FATAL_FAILURE(CheckSerializedExpectStapleReport(
       serialized_report, host_port, ssl_info, ocsp_response, response_status,
@@ -1444,6 +1453,8 @@
   EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
   std::string report = mock_report_sender.latest_report();
   ASSERT_FALSE(report.empty());
+  EXPECT_EQ("application/json; charset=utf-8",
+            mock_report_sender.latest_content_type());
   ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, host_port_pair, true, kHost,
                                           cert1.get(), cert2.get(),
                                           good_hashes));
@@ -1459,6 +1470,8 @@
   EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
   report = mock_report_sender.latest_report();
   ASSERT_FALSE(report.empty());
+  EXPECT_EQ("application/json; charset=utf-8",
+            mock_report_sender.latest_content_type());
   ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, subdomain_host_port_pair,
                                           true, kHost, cert1.get(), cert2.get(),
                                           good_hashes));
@@ -1569,6 +1582,8 @@
   EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
   std::string report = mock_report_sender.latest_report();
   ASSERT_FALSE(report.empty());
+  EXPECT_EQ("application/json; charset=utf-8",
+            mock_report_sender.latest_content_type());
   ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, host_port_pair, true, kHost,
                                           cert1.get(), cert2.get(),
                                           ssl_info.public_key_hashes));
@@ -1695,6 +1710,8 @@
 
   std::string report = mock_report_sender.latest_report();
   ASSERT_FALSE(report.empty());
+  EXPECT_EQ("application/json; charset=utf-8",
+            mock_report_sender.latest_content_type());
   ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(
       report, host_port_pair, pkp_state.include_subdomains, pkp_state.domain,
       cert1.get(), cert2.get(), pkp_state.spki_hashes));
diff --git a/net/url_request/report_sender.cc b/net/url_request/report_sender.cc
index 76f171d..1650360 100644
--- a/net/url_request/report_sender.cc
+++ b/net/url_request/report_sender.cc
@@ -32,7 +32,10 @@
   base::STLDeleteElements(&inflight_requests_);
 }
 
-void ReportSender::Send(const GURL& report_uri, const std::string& report) {
+void ReportSender::Send(const GURL& report_uri,
+                        base::StringPiece content_type,
+                        base::StringPiece report) {
+  DCHECK(!content_type.empty());
   std::unique_ptr<URLRequest> url_request =
       request_context_->CreateRequest(report_uri, DEFAULT_PRIORITY, this);
 
@@ -43,10 +46,15 @@
   }
   url_request->SetLoadFlags(load_flags);
 
+  HttpRequestHeaders extra_headers;
+  extra_headers.SetHeader(HttpRequestHeaders::kContentType, content_type);
+  url_request->SetExtraRequestHeaders(extra_headers);
+
   url_request->set_method("POST");
 
+  std::vector<char> report_data(report.begin(), report.end());
   std::unique_ptr<UploadElementReader> reader(
-      UploadOwnedBytesElementReader::CreateWithString(report));
+      new UploadOwnedBytesElementReader(&report_data));
   url_request->set_upload(
       ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
 
diff --git a/net/url_request/report_sender.h b/net/url_request/report_sender.h
index f74899f..0bcf2873 100644
--- a/net/url_request/report_sender.h
+++ b/net/url_request/report_sender.h
@@ -54,7 +54,9 @@
   ~ReportSender() override;
 
   // TransportSecurityState::ReportSenderInterface implementation.
-  void Send(const GURL& report_uri, const std::string& report) override;
+  void Send(const GURL& report_uri,
+            base::StringPiece content_type,
+            base::StringPiece report) override;
   void SetErrorCallback(const ErrorCallback& error_callback) override;
 
   // net::URLRequest::Delegate implementation.
diff --git a/net/url_request/report_sender_unittest.cc b/net/url_request/report_sender_unittest.cc
index 2143fbac..4d1096dd 100644
--- a/net/url_request/report_sender_unittest.cc
+++ b/net/url_request/report_sender_unittest.cc
@@ -87,6 +87,10 @@
     expect_cookies_ = expect_cookies;
   }
 
+  void set_expected_content_type(const std::string& content_type) {
+    expected_content_type_ = content_type;
+  }
+
   // NetworkDelegateImpl implementation.
   int OnBeforeURLRequest(URLRequest* request,
                          const CompletionCallback& callback,
@@ -103,6 +107,12 @@
       EXPECT_TRUE(request->load_flags() & LOAD_DO_NOT_SAVE_COOKIES);
     }
 
+    const HttpRequestHeaders& extra_headers = request->extra_request_headers();
+    std::string content_type;
+    EXPECT_TRUE(extra_headers.GetHeader(HttpRequestHeaders::kContentType,
+                                        &content_type));
+    EXPECT_EQ(expected_content_type_, content_type);
+
     CheckUploadData(*request, &expect_reports_);
 
     // Unconditionally return OK, since the sender ignores the results
@@ -123,6 +133,7 @@
   GURL expect_url_;
   std::set<std::string> expect_reports_;
   bool expect_cookies_;
+  std::string expected_content_type_;
 
   DISALLOW_COPY_AND_ASSIGN(TestReportSenderNetworkDelegate);
 };
@@ -154,10 +165,11 @@
 
     network_delegate_.set_expect_url(url);
     network_delegate_.ExpectReport(report);
+    network_delegate_.set_expected_content_type("application/foobar");
 
     EXPECT_EQ(request_sequence_number, network_delegate_.num_requests());
 
-    reporter->Send(url, report);
+    reporter->Send(url, "application/foobar", report);
 
     // The report is sent asynchronously, so wait for the report's
     // URLRequest to be destroyed before checking that the report was
@@ -197,13 +209,14 @@
   network_delegate_.set_expect_url(url);
   network_delegate_.ExpectReport(kDummyReport);
   network_delegate_.ExpectReport(kSecondDummyReport);
+  network_delegate_.set_expected_content_type("application/foobar");
 
   ReportSender reporter(context(), ReportSender::DO_NOT_SEND_COOKIES);
 
   EXPECT_EQ(0u, network_delegate_.num_requests());
 
-  reporter.Send(url, kDummyReport);
-  reporter.Send(url, kSecondDummyReport);
+  reporter.Send(url, "application/foobar", kDummyReport);
+  reporter.Send(url, "application/foobar", kSecondDummyReport);
 
   run_loop.Run();
 
@@ -221,12 +234,13 @@
       URLRequestFailedJob::START, ERR_IO_PENDING);
   network_delegate_.set_expect_url(url);
   network_delegate_.ExpectReport(kDummyReport);
+  network_delegate_.set_expected_content_type("application/foobar");
 
   EXPECT_EQ(0u, network_delegate_.num_requests());
 
   std::unique_ptr<ReportSender> reporter(
       new ReportSender(context(), ReportSender::DO_NOT_SEND_COOKIES));
-  reporter->Send(url, kDummyReport);
+  reporter->Send(url, "application/foobar", kDummyReport);
   reporter.reset();
 
   EXPECT_EQ(1u, network_delegate_.num_requests());
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 328d53b..e855224f6 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -675,9 +675,12 @@
   MockCertificateReportSender() {}
   ~MockCertificateReportSender() override {}
 
-  void Send(const GURL& report_uri, const std::string& report) override {
+  void Send(const GURL& report_uri,
+            base::StringPiece content_type,
+            base::StringPiece report) override {
     latest_report_uri_ = report_uri;
-    latest_report_ = report;
+    report.CopyToString(&latest_report_);
+    content_type.CopyToString(&latest_content_type_);
   }
 
   void SetErrorCallback(
@@ -685,10 +688,12 @@
 
   const GURL& latest_report_uri() { return latest_report_uri_; }
   const std::string& latest_report() { return latest_report_; }
+  const std::string& latest_content_type() { return latest_content_type_; }
 
  private:
   GURL latest_report_uri_;
   std::string latest_report_;
+  std::string latest_content_type_;
 };
 
 class TestExperimentalFeaturesNetworkDelegate : public TestNetworkDelegate {
@@ -6022,6 +6027,8 @@
   // Check that a report was sent.
   EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
   ASSERT_FALSE(mock_report_sender.latest_report().empty());
+  EXPECT_EQ("application/json; charset=utf-8",
+            mock_report_sender.latest_content_type());
   std::unique_ptr<base::Value> value(
       base::JSONReader::Read(mock_report_sender.latest_report()));
   ASSERT_TRUE(value);
@@ -6085,6 +6092,8 @@
   // Check that a report was sent.
   EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri());
   ASSERT_FALSE(mock_report_sender.latest_report().empty());
+  EXPECT_EQ("application/json; charset=utf-8",
+            mock_report_sender.latest_content_type());
   std::unique_ptr<base::Value> value(
       base::JSONReader::Read(mock_report_sender.latest_report()));
   ASSERT_TRUE(value);
diff --git a/pdf/pdfium/fuzzers/BUILD.gn b/pdf/pdfium/fuzzers/BUILD.gn
index a2297d7..1300910 100644
--- a/pdf/pdfium/fuzzers/BUILD.gn
+++ b/pdf/pdfium/fuzzers/BUILD.gn
@@ -50,6 +50,13 @@
   dict = "dicts/pdf_codec_icc.dict"
 }
 
+fuzzer_test("pdf_codec_jbig2_fuzzer") {
+  sources = []
+  deps = [
+    "//third_party/pdfium/testing/libfuzzer:pdf_codec_jbig2_fuzzer",
+  ]
+}
+
 fuzzer_test("pdf_hint_table_fuzzer") {
   sources = []
   deps = [
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index e91db24..e2ca33c5 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -74,8 +74,8 @@
     "label": "//:All_syzygy",
     "type": "additional_compile_target",
   },
-  "AppRTCDemoTest": {
-    "label": "//webrtc/examples:AppRTCDemoTest",
+  "AppRTCMobileTest": {
+    "label": "//webrtc/examples:AppRTCMobileTest",
     "type": "additional_compile_target",
   },
   "accessibility_unittests":  {
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py
index 75741b9..fa746b9 100755
--- a/testing/buildbot/manage.py
+++ b/testing/buildbot/manage.py
@@ -174,7 +174,7 @@
   'webapk_shell_apk_junit_tests',
 
   # These tests are only run on WebRTC CI.
-  'AppRTCDemoTest',
+  'AppRTCMobileTest',
   'android_junit_tests',
   'audio_decoder_unittests',
   'common_audio_unittests',
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index ea0760b..6d75989 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -288,5 +288,10 @@
     "prefix": "enable_wasm",
     "base": "http/tests/wasm",
     "args": ["--enable-wasm"]
+  },
+  {
+    "prefix": "mojo-service-worker",
+    "base": "http/tests/serviceworker",
+    "args": ["--mojo-service-worker"]
   }
 ]
diff --git a/third_party/WebKit/LayoutTests/editing/pasteboard/drag-drop-modifies-page.html b/third_party/WebKit/LayoutTests/editing/pasteboard/drag-drop-modifies-page.html
index c933b19..66bf00f 100644
--- a/third_party/WebKit/LayoutTests/editing/pasteboard/drag-drop-modifies-page.html
+++ b/third_party/WebKit/LayoutTests/editing/pasteboard/drag-drop-modifies-page.html
@@ -1,38 +1,30 @@
-<html> 
-<head>
-<script src=../editing.js type="text/javascript"></script>
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
 <script>
-function editingTest() {
-  
-    if (!window.testRunner)
-        return;
-    if (window.internals)
-        internals.settings.setEditingBehavior("mac");
+test(() => {
+    assert_not_equals(window.eventSender, undefined,
+        'This test requires eventSender');
 
-    extendSelectionForwardByWordCommand();
-    
-    window.testRunner.waitUntilDone();
-    
-    // Drag 'hello'
-    var e = document.getElementById("dragme");
-    x = e.offsetLeft + 10;
-    y = e.offsetTop + e.offsetHeight / 2;
-    eventSender.mouseMoveTo(x, y);
-    eventSender.mouseDown();
-    // and drop it off to the right somewhere
-    eventSender.leapForward(500);
-    eventSender.mouseMoveTo(x + 300, y);
-    eventSender.mouseUp();
-
-    window.testRunner.notifyDone();
-}
+    assert_selection(
+        '<div contenteditable><span id="dragme">^hello|</span> world</div>',
+        selection => {
+            // Drag 'hello'
+            const dragMe = selection.document.getElementById('dragme');
+            const editor = dragMe.parentNode;
+            const editorLeft = editor.offsetLeft + selection.document.offsetLeft;
+            const editorTop = editor.offsetTop + selection.document.offsetTop;
+            const x = editorLeft + dragMe.offsetWidth / 2;
+            const y = editorTop + dragMe.offsetHeight / 2;
+            eventSender.mouseMoveTo(x, y);
+            eventSender.mouseDown();
+            // and drop it off to the right somewhere
+            eventSender.leapForward(500);
+            eventSender.mouseMoveTo(editorLeft + editor.offsetWidth, y);
+            eventSender.mouseUp();
+        },
+        '<div contenteditable>world^hello|</div>',
+        'Drag "hello" after "wold"');
+});
 </script>
-<title>Drag and drop within a text input field modifies page</title> 
-</head> 
-<body>
-<p>This tests non-smartmove drag/drop. The space should be deleted on move,
-but not reinserted on drop, resulting in "worldhello".</p>
-<div contenteditable="true" id="test"><span id="dragme">hello</span> world</div>
-<script>runEditingTest();</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength-expected.txt
index dfe1d55..ba2704f 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength-expected.txt
@@ -28,7 +28,7 @@
 PASS textArea.value is "abcde"
 PASS textArea.value is "A\nB"
 PASS textArea.value is "a\n\n"
-PASS textArea.value is "\n\n\n"
+PASS textArea.value is "\n\n\n\n\n\n"
 Inserts 2 normal characters + a combining letter with 3 code points into a maxlength=3 element.
 PASS textArea.value is "ABx"
 PASS textArea.value.length is 3
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength.html
index 5992fe2f..93ebdb74 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength.html
+++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-maxlength.html
@@ -122,7 +122,10 @@
 document.execCommand('insertLineBreak');
 document.execCommand('insertLineBreak');
 document.execCommand('insertLineBreak');
-shouldBe('textArea.value', '"\\n\\n\\n"');
+document.execCommand('insertLineBreak');
+document.execCommand('insertLineBreak');
+document.execCommand('insertLineBreak');
+shouldBeEqualToString('textArea.value', '\n\n\n\n\n\n');
 
 // According to the HTML5 specification, maxLength is code-point length.
 // Blink follows it though WebKit handles it as grapheme length.
diff --git a/third_party/WebKit/LayoutTests/fast/forms/validationMessage-expected.txt b/third_party/WebKit/LayoutTests/fast/forms/validationMessage-expected.txt
index 64c7e4a..4cffc329 100644
--- a/third_party/WebKit/LayoutTests/fast/forms/validationMessage-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/forms/validationMessage-expected.txt
@@ -32,12 +32,12 @@
 input tooLong: Please shorten this text to 3 characters or less (you are currently using 5 characters).
 input tooLong: Please shorten this text to 2 characters or less (you are currently using 3 characters).
 input tooLong: Please shorten this text to Ù¢ characters or less (you are currently using Ù£ characters).
-textarea tooLong: Please shorten this text to 3 characters or less (you are currently using 5 characters).
+textarea tooLong: Please shorten this text to 3 characters or less (you are currently using 4 characters).
 tooShort:
 input tooShort: Please lengthen this text to 3 characters or more (you are currently using 1 characters).
 input tooShort: Please lengthen this text to 4 characters or more (you are currently using 3 characters).
 input tooShort: Please lengthen this text to Ù¤ characters or more (you are currently using Ù£ characters).
-textarea tooShort: Please lengthen this text to 4 characters or more (you are currently using 3 characters).
+textarea tooShort: Please lengthen this text to 4 characters or more (you are currently using 2 characters).
 PASS but.validationMessage is ''
 PASS anoninput.validationMessage is ''
 PASS happyFieldset.validationMessage is ''
diff --git a/third_party/WebKit/LayoutTests/inspector/agents-enable-disable.html b/third_party/WebKit/LayoutTests/inspector/agents-enable-disable.html
index c121d0c..7814384 100644
--- a/third_party/WebKit/LayoutTests/inspector/agents-enable-disable.html
+++ b/third_party/WebKit/LayoutTests/inspector/agents-enable-disable.html
@@ -25,7 +25,7 @@
     targets.forEach(function(target) {
         var agentNames = Object.keys(target._agentsMap).filter(function(agentName) {
             var agent = target._agentsMap[agentName];
-            return agent["enable"] && agent["disable"] && agentName !== "ServiceWorker" && agentName !== "Security" && agentName !== "Inspector";  // async wrt others.
+            return agent["enable"] && agent["disable"] && agentName !== "ServiceWorker" && agentName !== "Security" && agentName !== "Inspector" && agentName !== "Target";  // async wrt others.
         }).sort();
 
         function disableAgent(agentName)
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt
index 2258546..20cb68c1 100644
--- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt
@@ -79,6 +79,9 @@
             removeListener : <function>
         }
     }
+    timeline : {
+        addTraceProvider : <function>
+    }
 }
 All tests done.
 
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api-expected.txt b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api-expected.txt
new file mode 100644
index 0000000..7bb476b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api-expected.txt
@@ -0,0 +1,19 @@
+Tests timeline support in WebInspector Extensions API
+
+ Started extension.
+Running tests...
+RUNNING TEST: extension_testTimeline
+{
+    onRecordingStarted : {
+        addListener : <function>
+        removeListener : <function>
+    }
+    onRecordingStopped : {
+        addListener : <function>
+        removeListener : <function>
+    }
+}
+traceProvider.onRecordingStarted fired.
+traceProvider.onRecordingStopped fired.
+All tests done.
+
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api.html b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api.html
new file mode 100644
index 0000000..1ed18900
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api.html
@@ -0,0 +1,41 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/extensions-test.js"></script>
+<script src="../../http/tests/inspector/timeline-test.js"></script>
+
+<script type="text/javascript">
+function extension_testTimeline(nextTest)
+{
+    function onRecordingStarted()
+    {
+        output("traceProvider.onRecordingStarted fired.");
+    }
+    function onRecordingStopped()
+    {
+        output("traceProvider.onRecordingStopped fired.");
+        nextTest();
+    }
+    var traceProvider = webInspector.timeline.addTraceProvider("extension trace provider", "tooltip");
+    dumpObject(traceProvider);
+    traceProvider.onRecordingStarted.addListener(onRecordingStarted);
+    traceProvider.onRecordingStopped.addListener(onRecordingStopped);
+    extension_startTimeline(() => extension_stopTimeline(() => {}));
+}
+
+function extension_startTimeline(callback)
+{
+    evaluateOnFrontend("InspectorTest.startTimeline(reply);", callback);
+}
+
+function extension_stopTimeline(callback)
+{
+    evaluateOnFrontend("InspectorTest.stopTimeline(reply);", callback);
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Tests timeline support in WebInspector Extensions API</p>
+<span id="test-element"><b></b></span>
+</body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
index dcbd4324..2694699 100644
--- a/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
+++ b/third_party/WebKit/LayoutTests/inspector/profiler/agents-disabled-check-expected.txt
@@ -8,6 +8,7 @@
 frontend: {"id":<number>,"method":"Page.configureOverlay","params":{"suspended":true}}
 frontend: {"id":<number>,"method":"DOM.disable"}
 frontend: {"id":<number>,"method":"CSS.disable"}
+frontend: {"id":<number>,"method":"Target.setWaitForDebuggerOnStart","params":{"value":false}}
 
 --> WebInspector.targetManager.resumeAllTargets();
 frontend: {"id":<number>,"method":"Page.configureOverlay","params":{"suspended":false}}
@@ -17,6 +18,7 @@
 frontend: {"id":<number>,"method":"Debugger.setAsyncCallStackDepth","params":{"maxDepth":4}}
 frontend: {"id":<number>,"method":"DOM.enable"}
 frontend: {"id":<number>,"method":"CSS.enable"}
+frontend: {"id":<number>,"method":"Target.setWaitForDebuggerOnStart","params":{"value":true}}
 
 --> done
 
diff --git a/third_party/WebKit/LayoutTests/media/remoteplayback/disable-remote-playback-prompt-throws.html b/third_party/WebKit/LayoutTests/media/remoteplayback/disable-remote-playback-prompt-throws.html
new file mode 100644
index 0000000..1434565
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/media/remoteplayback/disable-remote-playback-prompt-throws.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Test that calling prompt() when disableRemotePlayback attribute is set throws an exception</title>
+        <script src="../../resources/testharness.js"></script>
+        <script src="../../resources/testharnessreport.js"></script>
+        <script src="../media-file.js"></script>
+    </head>
+    <body>
+        <script>
+            promise_test(function(test)
+            {
+                var v = document.createElement('video');
+                v.src = findMediaFile('video', 'content/test');
+                v.disableRemotePlayback = true
+                document.body.appendChild(v);
+
+                return promise_rejects(
+                    test,
+                    new DOMException('disableRemotePlayback attribute is present.', 'InvalidStateError'),
+                    v.remote.prompt());
+            }, 'Test that calling prompt() when disableRemotePlayback attribute is set throws an exception.');
+        </script>
+    </body>
+</html>
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/display-table-row-crash-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/display-table-row-crash-expected.txt
new file mode 100644
index 0000000..efae139
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/display-table-row-crash-expected.txt
@@ -0,0 +1,2 @@
+Passes if no crash.
+
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/display-table-row-crash.html b/third_party/WebKit/LayoutTests/paint/invalidation/display-table-row-crash.html
new file mode 100644
index 0000000..62d1e576
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/paint/invalidation/display-table-row-crash.html
@@ -0,0 +1,12 @@
+<!doctype HTML>
+Passes if no crash.
+<style>
+   div {
+        -webkit-box-reflect: below;
+</style>
+<div id="splitter"></div>
+<script>
+if (window.testRunner)
+    window.testRunner.dumpAsText();
+document.getElementById("splitter").style.display = "table-row";
+</script>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/pasteboard/drag-drop-modifies-page-expected.png b/third_party/WebKit/LayoutTests/platform/linux/editing/pasteboard/drag-drop-modifies-page-expected.png
deleted file mode 100644
index 242ea3d..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/editing/pasteboard/drag-drop-modifies-page-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/editing/pasteboard/drag-drop-modifies-page-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/editing/pasteboard/drag-drop-modifies-page-expected.txt
deleted file mode 100644
index 0da9a0f6..0000000
--- a/third_party/WebKit/LayoutTests/platform/linux/editing/pasteboard/drag-drop-modifies-page-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x20
-        LayoutText {#text} at (0,0) size 771x19
-          text run at (0,0) width 771: "This tests non-smartmove drag/drop. The space should be deleted on move, but not reinserted on drop, resulting in \"worldhello\"."
-      LayoutBlockFlow {DIV} at (0,36) size 784x20
-        LayoutText {#text} at (0,0) size 63x19
-          text run at (0,0) width 63: "worldhello"
-selection start: position 5 of child 0 {#text} of child 3 {DIV} of body
-selection end:   position 10 of child 0 {#text} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/pasteboard/drag-drop-modifies-page-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/pasteboard/drag-drop-modifies-page-expected.png
deleted file mode 100644
index 02cfe7b..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/pasteboard/drag-drop-modifies-page-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/pasteboard/drag-drop-modifies-page-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/editing/pasteboard/drag-drop-modifies-page-expected.txt
deleted file mode 100644
index b4e658c..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/pasteboard/drag-drop-modifies-page-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x36
-        LayoutText {#text} at (0,0) size 734x36
-          text run at (0,0) width 734: "This tests non-smartmove drag/drop. The space should be deleted on move, but not reinserted on drop, resulting in"
-          text run at (0,18) width 87: "\"worldhello\"."
-      LayoutBlockFlow {DIV} at (0,52) size 784x18
-        LayoutText {#text} at (0,0) size 70x18
-          text run at (0,0) width 70: "worldhello"
-selection start: position 5 of child 0 {#text} of child 3 {DIV} of body
-selection end:   position 10 of child 0 {#text} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/pasteboard/drag-drop-modifies-page-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/pasteboard/drag-drop-modifies-page-expected.png
deleted file mode 100644
index fdedd47..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/editing/pasteboard/drag-drop-modifies-page-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/pasteboard/drag-drop-modifies-page-expected.txt b/third_party/WebKit/LayoutTests/platform/win/editing/pasteboard/drag-drop-modifies-page-expected.txt
deleted file mode 100644
index 6d9c089..0000000
--- a/third_party/WebKit/LayoutTests/platform/win/editing/pasteboard/drag-drop-modifies-page-expected.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutBlockFlow {HTML} at (0,0) size 800x600
-    LayoutBlockFlow {BODY} at (8,8) size 784x584
-      LayoutBlockFlow {P} at (0,0) size 784x36
-        LayoutText {#text} at (0,0) size 734x35
-          text run at (0,0) width 734: "This tests non-smartmove drag/drop. The space should be deleted on move, but not reinserted on drop, resulting in"
-          text run at (0,18) width 87: "\"worldhello\"."
-      LayoutBlockFlow {DIV} at (0,52) size 784x18
-        LayoutText {#text} at (0,0) size 70x17
-          text run at (0,0) width 70: "worldhello"
-selection start: position 5 of child 0 {#text} of child 3 {DIV} of body
-selection end:   position 10 of child 0 {#text} of child 3 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/virtual/mojo-service-worker/http/tests/serviceworker/README.txt b/third_party/WebKit/LayoutTests/virtual/mojo-service-worker/http/tests/serviceworker/README.txt
new file mode 100644
index 0000000..0310ec9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/mojo-service-worker/http/tests/serviceworker/README.txt
@@ -0,0 +1 @@
+This directory is for testing the service workers with mojo by using '--mojo-service-worker' flag.
diff --git a/third_party/WebKit/Source/bindings/bindings.gni b/third_party/WebKit/Source/bindings/bindings.gni
index 049b33b..8009e6b 100644
--- a/third_party/WebKit/Source/bindings/bindings.gni
+++ b/third_party/WebKit/Source/bindings/bindings.gni
@@ -151,13 +151,13 @@
                     "core/v8/V8EventListener.cpp",
                     "core/v8/V8EventListener.h",
                     "core/v8/V8EventListenerInfo.h",
-                    "core/v8/V8EventListenerList.cpp",
-                    "core/v8/V8EventListenerList.h",
                     "core/v8/V8GCController.cpp",
                     "core/v8/V8GCController.h",
                     "core/v8/ScriptWrappableVisitor.cpp",
                     "core/v8/ScriptWrappableVisitor.h",
                     "core/v8/ScriptWrappableVisitorVerifier.h",
+                    "core/v8/V8EventListenerHelper.cpp",
+                    "core/v8/V8EventListenerHelper.h",
                     "core/v8/V8GCForContextDispose.cpp",
                     "core/v8/V8GCForContextDispose.h",
                     "core/v8/V8GlobalValueMap.h",
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp b/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp
index 5da2531c..34963df 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8AbstractEventListener.cpp
@@ -32,7 +32,7 @@
 
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8Event.h"
-#include "bindings/core/v8/V8EventListenerList.h"
+#include "bindings/core/v8/V8EventListenerHelper.h"
 #include "bindings/core/v8/V8EventTarget.h"
 #include "bindings/core/v8/V8HiddenValue.h"
 #include "core/events/BeforeUnloadEvent.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerList.cpp b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerHelper.cpp
similarity index 78%
rename from third_party/WebKit/Source/bindings/core/v8/V8EventListenerList.cpp
rename to third_party/WebKit/Source/bindings/core/v8/V8EventListenerHelper.cpp
index 387ca17..5bbdda5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerList.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerHelper.cpp
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "bindings/core/v8/V8EventListenerList.h"
+#include "bindings/core/v8/V8EventListenerHelper.h"
 
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8Window.h"
@@ -36,17 +36,17 @@
 
 namespace blink {
 
-EventListener* V8EventListenerList::getEventListener(ScriptState* scriptState, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+EventListener* V8EventListenerHelper::getEventListener(ScriptState* scriptState, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
 {
     if (lookup == ListenerFindOnly) {
         // Used by EventTarget::removeEventListener, specifically
         // EventTargetV8Internal::removeEventListenerMethod
-        ASSERT(!isAttribute);
-        return V8EventListenerList::findWrapper(value, scriptState);
+        DCHECK(!isAttribute);
+        return V8EventListenerHelper::existingEventListener(value, scriptState);
     }
     if (toDOMWindow(scriptState->context()))
-        return V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute, scriptState);
-    return V8EventListenerList::findOrCreateWrapper<V8WorkerGlobalScopeEventListener>(value, isAttribute, scriptState);
+        return V8EventListenerHelper::ensureEventListener<V8EventListener>(value, isAttribute, scriptState);
+    return V8EventListenerHelper::ensureEventListener<V8WorkerGlobalScopeEventListener>(value, isAttribute, scriptState);
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerList.h b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerHelper.h
similarity index 65%
rename from third_party/WebKit/Source/bindings/core/v8/V8EventListenerList.h
rename to third_party/WebKit/Source/bindings/core/v8/V8EventListenerHelper.h
index 63f2817..33d0afd5 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8EventListenerList.h
+++ b/third_party/WebKit/Source/bindings/core/v8/V8EventListenerHelper.h
@@ -28,8 +28,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef V8EventListenerList_h
-#define V8EventListenerList_h
+#ifndef V8EventListenerHelper_h
+#define V8EventListenerHelper_h
 
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8EventListener.h"
@@ -45,32 +45,32 @@
 };
 
 // This is a container for V8EventListener objects that uses hidden properties of v8::Object to speed up lookups.
-class V8EventListenerList {
-    STATIC_ONLY(V8EventListenerList);
+class V8EventListenerHelper {
+    STATIC_ONLY(V8EventListenerHelper);
 public:
-    static V8EventListener* findWrapper(v8::Local<v8::Value> value, ScriptState* scriptState)
+    static V8EventListener* existingEventListener(v8::Local<v8::Value> value, ScriptState* scriptState)
     {
-        ASSERT(scriptState->isolate()->InContext());
+        DCHECK(scriptState->isolate()->InContext());
         if (!value->IsObject())
             return nullptr;
 
-        v8::Local<v8::String> wrapperProperty = getHiddenProperty(false, scriptState->isolate());
-        return doFindWrapper(v8::Local<v8::Object>::Cast(value), wrapperProperty, scriptState);
+        v8::Local<v8::String> listenerProperty = getHiddenProperty(false, scriptState->isolate());
+        return findEventListener(v8::Local<v8::Object>::Cast(value), listenerProperty, scriptState);
     }
 
-    template<typename WrapperType>
-    static V8EventListener* findOrCreateWrapper(v8::Local<v8::Value>, bool isAttribute, ScriptState*);
+    template<typename ListenerType>
+    static V8EventListener* ensureEventListener(v8::Local<v8::Value>, bool isAttribute, ScriptState*);
 
     CORE_EXPORT static EventListener* getEventListener(ScriptState*, v8::Local<v8::Value>, bool isAttribute, ListenerLookupType);
 
 private:
-    static V8EventListener* doFindWrapper(v8::Local<v8::Object> object, v8::Local<v8::String> wrapperProperty, ScriptState* scriptState)
+    static V8EventListener* findEventListener(v8::Local<v8::Object> object, v8::Local<v8::String> listenerProperty, ScriptState* scriptState)
     {
         v8::HandleScope scope(scriptState->isolate());
-        ASSERT(scriptState->isolate()->InContext());
-        v8::Local<v8::Value> listener = V8HiddenValue::getHiddenValue(scriptState, object, wrapperProperty);
+        DCHECK(scriptState->isolate()->InContext());
+        v8::Local<v8::Value> listener = V8HiddenValue::getHiddenValue(scriptState, object, listenerProperty);
         if (listener.IsEmpty())
-            return 0;
+            return nullptr;
         return static_cast<V8EventListener*>(v8::External::Cast(*listener)->Value());
     }
 
@@ -80,28 +80,28 @@
     }
 };
 
-template<typename WrapperType>
-V8EventListener* V8EventListenerList::findOrCreateWrapper(v8::Local<v8::Value> value, bool isAttribute, ScriptState* scriptState)
+template<typename ListenerType>
+V8EventListener* V8EventListenerHelper::ensureEventListener(v8::Local<v8::Value> value, bool isAttribute, ScriptState* scriptState)
 {
     v8::Isolate* isolate = scriptState->isolate();
-    ASSERT(isolate->InContext());
+    DCHECK(isolate->InContext());
     if (!value->IsObject())
         return nullptr;
 
     v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
-    v8::Local<v8::String> wrapperProperty = getHiddenProperty(isAttribute, isolate);
+    v8::Local<v8::String> listenerProperty = getHiddenProperty(isAttribute, isolate);
 
-    V8EventListener* wrapper = doFindWrapper(object, wrapperProperty, scriptState);
-    if (wrapper)
-        return wrapper;
+    V8EventListener* listener = findEventListener(object, listenerProperty, scriptState);
+    if (listener)
+        return listener;
 
-    wrapper = WrapperType::create(object, isAttribute, scriptState);
-    if (wrapper)
-        V8HiddenValue::setHiddenValue(scriptState, object, wrapperProperty, v8::External::New(isolate, wrapper));
+    listener = ListenerType::create(object, isAttribute, scriptState);
+    if (listener)
+        V8HiddenValue::setHiddenValue(scriptState, object, listenerProperty, v8::External::New(isolate, listener));
 
-    return wrapper;
+    return listener;
 }
 
 } // namespace blink
 
-#endif // V8EventListenerList_h
+#endif // V8EventListenerHelper_h
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp
index 58c4eda..0d321b3 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8EventTargetCustom.cpp
@@ -30,7 +30,6 @@
 
 #include "bindings/core/v8/V8EventTarget.h"
 
-#include "bindings/core/v8/V8EventListenerList.h"
 #include "bindings/core/v8/V8Window.h"
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/UseCounter.h"
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
index 3db26ef..f850005 100644
--- a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
@@ -40,7 +40,6 @@
 #include "bindings/core/v8/Transferables.h"
 #include "bindings/core/v8/V8Binding.h"
 #include "bindings/core/v8/V8EventListener.h"
-#include "bindings/core/v8/V8EventListenerList.h"
 #include "bindings/core/v8/V8HTMLCollection.h"
 #include "bindings/core/v8/V8HiddenValue.h"
 #include "bindings/core/v8/V8Node.h"
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
index 776a3f5..5ea7d1c3 100644
--- a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
+++ b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
@@ -54,7 +54,7 @@
 import v8_callback_function
 import v8_callback_interface
 import v8_dictionary
-from v8_globals import includes, interfaces
+from v8_globals import includes
 import v8_interface
 import v8_types
 import v8_union
@@ -170,9 +170,6 @@
         raise ValueError('%s is not in IDL definitions' % definition_name)
 
     def generate_interface_code(self, definitions, interface_name, interface):
-        # Store other interfaces for introspection
-        interfaces.update(definitions.interfaces)
-
         interface_info = self.info_provider.interfaces_info[interface_name]
         full_path = interface_info.get('full_path')
         component = idl_filename_to_component(full_path)
@@ -196,7 +193,7 @@
             cpp_template_filename = 'interface.cpp.tmpl'
             interface_context = v8_interface.interface_context
 
-        template_context = interface_context(interface)
+        template_context = interface_context(interface, definitions.interfaces)
         includes.update(interface_info.get('cpp_includes', {}).get(component, set()))
         if not interface.is_partial and not is_testing_target(full_path):
             template_context['header_includes'].add(self.info_provider.include_path_for_export)
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
index 4e48f68..2f0f27665 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_attributes.py
@@ -26,6 +26,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# pylint: disable=relative-import
+
 """Generate template values for attributes.
 
 Extends IdlType with property |constructor_type_name|.
@@ -35,7 +37,7 @@
 
 import idl_types
 from idl_types import inherits_interface
-from v8_globals import includes, interfaces
+from v8_globals import includes
 import v8_types
 import v8_utilities
 from v8_utilities import (cpp_name_or_partial, capitalize, cpp_name, has_extended_attribute,
@@ -44,7 +46,19 @@
                           is_legacy_interface_type_checking)
 
 
-def attribute_context(interface, attribute):
+def attribute_context(interface, attribute, interfaces):
+    """Creates a Jinja template context for an attribute of an interface.
+
+    Args:
+        interface: An interface which |attribute| belongs to
+        attribute: An attribute to create the context for
+        interfaces: A dict which maps an interface name to the definition
+            which can be referred if needed
+
+    Returns:
+        A Jinja template context for |attribute|
+    """
+
     idl_type = attribute.idl_type
     base_idl_type = idl_type.base_type
     extended_attributes = attribute.extended_attributes
@@ -181,7 +195,7 @@
     if not has_custom_getter(attribute):
         getter_context(interface, attribute, context)
     if not has_custom_setter(attribute) and has_setter(interface, attribute):
-        setter_context(interface, attribute, context)
+        setter_context(interface, attribute, interfaces, context)
 
     return context
 
@@ -365,7 +379,7 @@
 # Setter
 ################################################################################
 
-def setter_context(interface, attribute, context):
+def setter_context(interface, attribute, interfaces, context):
     if 'PutForwards' in attribute.extended_attributes:
         # Use target interface and attribute in place of original interface and
         # attribute from this point onwards.
@@ -444,9 +458,9 @@
         if (interface.name in ['Window', 'WorkerGlobalScope'] and
                 attribute.name == 'onerror'):
             includes.add('bindings/core/v8/V8ErrorHandler.h')
-            arguments.append('V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(v8Value, true, ScriptState::current(info.GetIsolate()))')
+            arguments.append('V8EventListenerHelper::ensureEventListener<V8ErrorHandler>(v8Value, true, ScriptState::current(info.GetIsolate()))')
         else:
-            arguments.append('V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate)')
+            arguments.append('V8EventListenerHelper::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate)')
     else:
         arguments.append('cppValue')
     if context['is_setter_raises_exception']:
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py
index d6316bd..a9c70a6 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py
@@ -71,7 +71,7 @@
 IdlTypeBase.callback_cpp_type = property(cpp_type)
 
 
-def callback_interface_context(callback_interface):
+def callback_interface_context(callback_interface, _):
     includes.clear()
     includes.update(CALLBACK_INTERFACE_CPP_INCLUDES)
     return {
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_globals.py b/third_party/WebKit/Source/bindings/scripts/v8_globals.py
index 9ca2a35..55ed257 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_globals.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_globals.py
@@ -29,4 +29,3 @@
 """Module to share global variables (includes and interfaces) across modules."""
 
 includes = set()
-interfaces = {}
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
index f410fb6..86a5963 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -132,7 +132,18 @@
     return sorted(features)
 
 
-def interface_context(interface):
+def interface_context(interface, interfaces):
+    """Creates a Jinja template context for an interface.
+
+    Args:
+        interface: An interface to create the context for
+        interfaces: A dict which maps an interface name to the definition
+            which can be referred if needed
+
+    Returns:
+        A Jinja template context for |interface|
+    """
+
     includes.clear()
     includes.update(INTERFACE_CPP_INCLUDES)
     header_includes = set(INTERFACE_H_INCLUDES)
@@ -333,7 +344,7 @@
     })
 
     # Attributes
-    attributes = [v8_attributes.attribute_context(interface, attribute)
+    attributes = [v8_attributes.attribute_context(interface, attribute, interfaces)
                   for attribute in interface.attributes]
 
     has_conditional_attributes = any(attribute['exposed_test'] for attribute in attributes)
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_types.py b/third_party/WebKit/Source/bindings/scripts/v8_types.py
index 22d41a9..50eeeb1 100644
--- a/third_party/WebKit/Source/bindings/scripts/v8_types.py
+++ b/third_party/WebKit/Source/bindings/scripts/v8_types.py
@@ -337,9 +337,9 @@
                             'core/dom/FlexibleArrayBufferView.h']),
     'Dictionary': set(['bindings/core/v8/Dictionary.h']),
     'EventHandler': set(['bindings/core/v8/V8AbstractEventListener.h',
-                         'bindings/core/v8/V8EventListenerList.h']),
+                         'bindings/core/v8/V8EventListenerHelper.h']),
     'EventListener': set(['bindings/core/v8/BindingSecurity.h',
-                          'bindings/core/v8/V8EventListenerList.h',
+                          'bindings/core/v8/V8EventListenerHelper.h',
                           'core/frame/LocalDOMWindow.h']),
     'HTMLCollection': set(['bindings/core/v8/V8HTMLCollection.h',
                            'core/dom/ClassCollection.h',
diff --git a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
index 23fcbded..a3727ff5 100644
--- a/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
+++ b/third_party/WebKit/Source/bindings/templates/methods.cpp.tmpl
@@ -148,9 +148,9 @@
 {# FIXME: remove EventListener special case #}
 {% if argument.idl_type == 'EventListener' %}
 {% if method.name == 'removeEventListener' or method.name == 'removeListener' %}
-{{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[{{argument.index}}], false, ListenerFindOnly);
+{{argument.name}} = V8EventListenerHelper::getEventListener(ScriptState::current(info.GetIsolate()), info[{{argument.index}}], false, ListenerFindOnly);
 {% else %}{# method.name == 'addEventListener' #}
-{{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[{{argument.index}}], false, ListenerFindOrCreate);
+{{argument.name}} = V8EventListenerHelper::getEventListener(ScriptState::current(info.GetIsolate()), info[{{argument.index}}], false, ListenerFindOrCreate);
 {% endif %}{# method.name #}
 {% else %}{# argument.idl_type == 'EventListener' #}
 {# Callback functions must be functions:
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
index 2e3c4d3..cad420e4 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterface.cpp
@@ -15,7 +15,7 @@
 #include "bindings/core/v8/ScriptValue.h"
 #include "bindings/core/v8/V8AbstractEventListener.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
-#include "bindings/core/v8/V8EventListenerList.h"
+#include "bindings/core/v8/V8EventListenerHelper.h"
 #include "bindings/core/v8/V8HiddenValue.h"
 #include "bindings/core/v8/V8Iterator.h"
 #include "bindings/core/v8/V8Node.h"
@@ -1076,7 +1076,7 @@
     // Prepare the value to be set.
     moveEventListenerToNewWrapper(info.GetIsolate(), holder, impl->implementsEventHandlerAttribute(), v8Value, V8TestInterface::eventListenerCacheIndex);
 
-    impl->setImplementsEventHandlerAttribute(V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate));
+    impl->setImplementsEventHandlerAttribute(V8EventListenerHelper::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate));
 }
 
 void implementsEventHandlerAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
index d050655..ddcb974 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestInterfaceNode.cpp
@@ -11,7 +11,7 @@
 #include "bindings/core/v8/GeneratedCodeHelper.h"
 #include "bindings/core/v8/V8AbstractEventListener.h"
 #include "bindings/core/v8/V8DOMConfiguration.h"
-#include "bindings/core/v8/V8EventListenerList.h"
+#include "bindings/core/v8/V8EventListenerHelper.h"
 #include "bindings/core/v8/V8ObjectConstructor.h"
 #include "bindings/core/v8/V8TestInterfaceEmpty.h"
 #include "core/HTMLNames.h"
@@ -158,7 +158,7 @@
 
     // Prepare the value to be set.
 
-    impl->setEventHandlerAttribute(V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate));
+    impl->setEventHandlerAttribute(V8EventListenerHelper::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate));
 }
 
 void eventHandlerAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
index 51f258c..21f053fa 100644
--- a/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
+++ b/third_party/WebKit/Source/bindings/tests/results/core/V8TestObject.cpp
@@ -38,7 +38,7 @@
 #include "bindings/core/v8/V8DocumentFragment.h"
 #include "bindings/core/v8/V8DocumentType.h"
 #include "bindings/core/v8/V8Element.h"
-#include "bindings/core/v8/V8EventListenerList.h"
+#include "bindings/core/v8/V8EventListenerHelper.h"
 #include "bindings/core/v8/V8EventTarget.h"
 #include "bindings/core/v8/V8Float32Array.h"
 #include "bindings/core/v8/V8HTMLCollection.h"
@@ -2245,7 +2245,7 @@
     // Prepare the value to be set.
     moveEventListenerToNewWrapper(info.GetIsolate(), holder, impl->eventHandlerAttribute(), v8Value, V8TestObject::eventListenerCacheIndex);
 
-    impl->setEventHandlerAttribute(V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate));
+    impl->setEventHandlerAttribute(V8EventListenerHelper::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate));
 }
 
 void eventHandlerAttributeAttributeSetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp
index 38f5f24..cf0b323 100644
--- a/third_party/WebKit/Source/core/dom/Node.cpp
+++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -272,8 +272,6 @@
     // this condition (we cannot directly access it here.)
     RELEASE_ASSERT(hasRareData() || !layoutObject());
     InstanceCounters::decrementCounter(InstanceCounters::NodeCounter);
-    if (!hasRareData() && m_data.m_computedStyle)
-        m_data.m_computedStyle->deref();
 }
 
 NodeRareData* Node::rareData() const
@@ -288,9 +286,9 @@
         return *rareData();
 
     if (isElementNode())
-        m_data.m_rareData = ElementRareData::create(layoutObject());
+        m_data.m_rareData = ElementRareData::create(m_data.m_layoutObject);
     else
-        m_data.m_rareData = NodeRareData::create(layoutObject());
+        m_data.m_rareData = NodeRareData::create(m_data.m_layoutObject);
 
     DCHECK(m_data.m_rareData);
 
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h
index ec52860..28e011ea 100644
--- a/third_party/WebKit/Source/core/dom/Node.h
+++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -481,19 +481,13 @@
 
     // As layoutObject() includes a branch you should avoid calling it repeatedly in hot code paths.
     // Note that if a Node has a layoutObject, it's parentNode is guaranteed to have one as well.
-    LayoutObject* layoutObject() const
-    {
-        if (hasRareData())
-            return m_data.m_rareData->layoutObject();
-        return hasLayoutObject() ? m_data.m_layoutObject : nullptr;
-    }
+    LayoutObject* layoutObject() const { return hasRareData() ? m_data.m_rareData->layoutObject() : m_data.m_layoutObject; }
     void setLayoutObject(LayoutObject* layoutObject)
     {
         if (hasRareData())
             m_data.m_rareData->setLayoutObject(layoutObject);
         else
             m_data.m_layoutObject = layoutObject;
-        setFlag(static_cast<bool>(layoutObject), HasLayoutObjectFlag);
     }
 
     // Use these two methods with caution.
@@ -706,12 +700,10 @@
         V0CustomElementFlag = 1 << 28,
         V0CustomElementUpgradedFlag = 1 << 29,
 
-        HasLayoutObjectFlag = 1 << 30,
-
         DefaultNodeFlags = IsFinishedParsingChildrenFlag | NeedsReattachStyleChange
     };
 
-    // 1 bit remaining.
+    // 3 bits remaining.
 
     bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
     void setFlag(bool f, NodeFlags mask) { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); }
@@ -743,7 +735,6 @@
 
     static void reattachWhitespaceSiblingsIfNeeded(Text* start);
 
-    bool hasLayoutObject() const { return getFlag(HasLayoutObjectFlag); }
     bool hasRareData() const { return getFlag(HasRareDataFlag); }
 
     NodeRareData* rareData() const;
@@ -798,7 +789,6 @@
     // When a node has rare data we move the layoutObject into the rare data.
     union DataUnion {
         DataUnion() : m_layoutObject(nullptr) { }
-        ComputedStyle* m_computedStyle;
         // LayoutObjects are fully owned by their DOM node. See LayoutObject's
         // LIFETIME documentation section.
         LayoutObject* m_layoutObject;
diff --git a/third_party/WebKit/Source/core/dom/NodeComputedStyle.h b/third_party/WebKit/Source/core/dom/NodeComputedStyle.h
index d734526..78872cd 100644
--- a/third_party/WebKit/Source/core/dom/NodeComputedStyle.h
+++ b/third_party/WebKit/Source/core/dom/NodeComputedStyle.h
@@ -25,10 +25,8 @@
 #ifndef NodeComputedStyle_h
 #define NodeComputedStyle_h
 
-#include "core/dom/ElementRareData.h"
 #include "core/dom/LayoutTreeBuilderTraversal.h"
 #include "core/dom/Node.h"
-#include "core/dom/NodeRareData.h"
 #include "core/dom/shadow/InsertionPoint.h"
 #include "core/html/HTMLOptGroupElement.h"
 #include "core/layout/LayoutObject.h"
@@ -43,20 +41,14 @@
 
 inline ComputedStyle* Node::mutableComputedStyle() const
 {
-    if (hasLayoutObject())
-        return layoutObject()->mutableStyle();
+    if (LayoutObject* layoutObject = this->layoutObject())
+        return layoutObject->mutableStyle();
     // <option> and <optgroup> can be styled even if they don't get layout objects,
     // so they store their style internally and return it through nonLayoutObjectComputedStyle().
     // We check here explicitly to avoid the virtual call in the common case.
     if (isHTMLOptGroupElement(*this) || isHTMLOptionElement(this))
         return nonLayoutObjectComputedStyle();
-    if (hasRareData()) {
-        NodeRareData* rareData = this->rareData();
-        if (!rareData->isElementRareData())
-            return nullptr;
-        return static_cast<ElementRareData*>(rareData)->computedStyle();
-    }
-    return m_data.m_computedStyle;
+    return 0;
 }
 
 inline const ComputedStyle* Node::parentComputedStyle() const
diff --git a/third_party/WebKit/Source/core/dom/NodeRareData.cpp b/third_party/WebKit/Source/core/dom/NodeRareData.cpp
index ce200b3..9b60294 100644
--- a/third_party/WebKit/Source/core/dom/NodeRareData.cpp
+++ b/third_party/WebKit/Source/core/dom/NodeRareData.cpp
@@ -58,7 +58,7 @@
 
 DEFINE_TRACE(NodeRareData)
 {
-    if (isElementRareData())
+    if (m_isElementRareData)
         static_cast<ElementRareData*>(this)->traceAfterDispatch(visitor);
     else
         traceAfterDispatch(visitor);
@@ -66,7 +66,7 @@
 
 DEFINE_TRACE_WRAPPERS(NodeRareData)
 {
-    if (isElementRareData())
+    if (m_isElementRareData)
         static_cast<const ElementRareData*>(this)->traceWrappersAfterDispatch(visitor);
     else
         traceWrappersAfterDispatch(visitor);
@@ -81,7 +81,7 @@
 void NodeRareData::finalizeGarbageCollectedObject()
 {
     RELEASE_ASSERT(!layoutObject());
-    if (isElementRareData())
+    if (m_isElementRareData)
         static_cast<ElementRareData*>(this)->~ElementRareData();
     else
         this->~NodeRareData();
diff --git a/third_party/WebKit/Source/core/dom/NodeRareData.h b/third_party/WebKit/Source/core/dom/NodeRareData.h
index 3eef31f..a15ff99 100644
--- a/third_party/WebKit/Source/core/dom/NodeRareData.h
+++ b/third_party/WebKit/Source/core/dom/NodeRareData.h
@@ -93,8 +93,6 @@
         --m_connectedFrameCount;
     }
 
-    bool isElementRareData() const { return m_isElementRareData; }
-
     bool hasElementFlag(ElementFlags mask) const { return m_elementFlags & mask; }
     void setElementFlag(ElementFlags mask, bool value) { m_elementFlags = (m_elementFlags & ~mask) | (-(int32_t)value & mask); }
     void clearElementFlag(ElementFlags mask) { m_elementFlags &= ~mask; }
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index 0ec2325e..238a2d4 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1745,7 +1745,7 @@
 static VisiblePositionTemplate<Strategy> endOfParagraphAlgorithm(const VisiblePositionTemplate<Strategy>& visiblePosition, EditingBoundaryCrossingRule boundaryCrossingRule)
 {
     DCHECK(visiblePosition.isValid()) << visiblePosition;
-    return createVisiblePositionDeprecated(endOfParagraphAlgorithm(visiblePosition.deepEquivalent(), boundaryCrossingRule));
+    return createVisiblePosition(endOfParagraphAlgorithm(visiblePosition.deepEquivalent(), boundaryCrossingRule));
 }
 
 VisiblePosition endOfParagraph(const VisiblePosition& c, EditingBoundaryCrossingRule boundaryCrossingRule)
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index ae69dff..ff59f69 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -662,7 +662,8 @@
         insertNodeAt(HTMLBRElement::create(document()), m_upstreamStart, editingState);
         if (editingState->isAborted())
             return;
-        mergeDestination = createVisiblePositionDeprecated(m_upstreamStart);
+        document().updateStyleAndLayoutIgnorePendingStylesheets();
+        mergeDestination = createVisiblePosition(m_upstreamStart);
         startOfParagraphToMove = createVisiblePosition(storedStartOfParagraphToMove);
     }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h b/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h
index e244034..1e12275 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLOptGroupElement.h
@@ -65,7 +65,6 @@
 
     void updateGroupLabel();
 
-    // TODO(bugsnash): Use Node's ComputedStyle instead
     RefPtr<ComputedStyle> m_style;
 };
 
diff --git a/third_party/WebKit/Source/core/html/HTMLOptionElement.h b/third_party/WebKit/Source/core/html/HTMLOptionElement.h
index 4be991d..14254d39 100644
--- a/third_party/WebKit/Source/core/html/HTMLOptionElement.h
+++ b/third_party/WebKit/Source/core/html/HTMLOptionElement.h
@@ -117,7 +117,6 @@
     // Represents 'dirtiness'.
     // https://html.spec.whatwg.org/multipage/forms.html#concept-option-dirtiness
     bool m_isDirty = false;
-    // TODO(bugsnash): Use Node's ComputedStyle instead
     RefPtr<ComputedStyle> m_style;
 };
 
diff --git a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp
index 0dff370..06e9204 100644
--- a/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTextAreaElement.cpp
@@ -60,22 +60,15 @@
 static const unsigned defaultRows = 2;
 static const unsigned defaultCols = 20;
 
-// On submission, LF characters are converted into CRLF.
-// This function returns number of characters considering this.
-static unsigned numberOfLineBreaks(const String& text)
+static inline unsigned computeLengthForAPIValue(const String& text)
 {
     unsigned length = text.length();
-    unsigned count = 0;
-    for (unsigned i = 0; i < length; i++) {
-        if (text[i] == '\n')
-            count++;
+    unsigned crlfCount = 0;
+    for (unsigned i = 0; i < length; ++i) {
+        if (text[i] == '\r' && i + 1 < length && text[i + 1] == '\n')
+            crlfCount++;
     }
-    return count;
-}
-
-static inline unsigned computeLengthForSubmission(const String& text)
-{
-    return text.length() + numberOfLineBreaks(text);
+    return text.length() - crlfCount;
 }
 
 HTMLTextAreaElement::HTMLTextAreaElement(Document& document, HTMLFormElement* form)
@@ -320,8 +313,8 @@
     unsigned unsignedMaxLength = static_cast<unsigned>(signedMaxLength);
 
     const String& currentValue = innerEditorValue();
-    unsigned currentLength = computeLengthForSubmission(currentValue);
-    if (currentLength + computeLengthForSubmission(event->text()) < unsignedMaxLength)
+    unsigned currentLength = computeLengthForAPIValue(currentValue);
+    if (currentLength + computeLengthForAPIValue(event->text()) < unsignedMaxLength)
         return;
 
     // selectionLength represents the selection length of this text field to be
@@ -335,7 +328,7 @@
         // needs to be audited.  See http://crbug.com/590369 for more details.
         document().updateStyleAndLayoutIgnorePendingStylesheets();
 
-        selectionLength = computeLengthForSubmission(document().frame()->selection().selectedText());
+        selectionLength = computeLengthForAPIValue(document().frame()->selection().selectedText());
     }
     DCHECK_GE(currentLength, selectionLength);
     unsigned baseLength = currentLength - selectionLength;
@@ -348,7 +341,9 @@
     unsigned submissionLength = 0;
     unsigned i = 0;
     for (; i < proposedValue.length(); ++i) {
-        submissionLength += proposedValue[i] == '\n' ? 2 : 1;
+        if (proposedValue[i] == '\r' && i + 1 < proposedValue.length() && proposedValue[i + 1] == '\n')
+            continue;
+        ++submissionLength;
         if (submissionLength == maxLength) {
             ++i;
             break;
@@ -550,10 +545,10 @@
         return locale().queryString(WebLocalizedString::ValidationValueMissing);
 
     if (tooLong())
-        return locale().validationMessageTooLongText(computeLengthForSubmission(value()), maxLength());
+        return locale().validationMessageTooLongText(value().length(), maxLength());
 
     if (tooShort())
-        return locale().validationMessageTooShortText(computeLengthForSubmission(value()), minLength());
+        return locale().validationMessageTooShortText(value().length(), minLength());
 
     return String();
 }
@@ -591,7 +586,8 @@
     int max = maxLength();
     if (max < 0)
         return false;
-    return computeLengthForSubmission(value ? *value : this->value()) > static_cast<unsigned>(max);
+    unsigned len = value ? computeLengthForAPIValue(*value) : this->value().length();
+    return len > static_cast<unsigned>(max);
 }
 
 bool HTMLTextAreaElement::tooShort(const String* value, NeedsToCheckDirtyFlag check) const
@@ -605,7 +601,7 @@
     if (min <= 0)
         return false;
     // An empty string is excluded from minlength check.
-    unsigned len = computeLengthForSubmission(value ? *value : this->value());
+    unsigned len = value ? computeLengthForAPIValue(*value) : this->value().length();
     return len > 0 && len < static_cast<unsigned>(min);
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLTextAreaElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLTextAreaElementTest.cpp
index c475bb9..1ff4681 100644
--- a/third_party/WebKit/Source/core/html/HTMLTextAreaElementTest.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLTextAreaElementTest.cpp
@@ -22,11 +22,13 @@
     EXPECT_EQ("", HTMLTextAreaElement::sanitizeUserInputValue("", 1));
     EXPECT_EQ("", HTMLTextAreaElement::sanitizeUserInputValue(leadSurrogate, 1));
     EXPECT_EQ("a", HTMLTextAreaElement::sanitizeUserInputValue("a", 1));
-    EXPECT_EQ("", HTMLTextAreaElement::sanitizeUserInputValue("\n", 1));
+    EXPECT_EQ("\n", HTMLTextAreaElement::sanitizeUserInputValue("\n", 1));
     EXPECT_EQ("\n", HTMLTextAreaElement::sanitizeUserInputValue("\n", 2));
 
     EXPECT_EQ("abc", HTMLTextAreaElement::sanitizeUserInputValue(String("abc") + leadSurrogate, 4));
-    EXPECT_EQ("a\nc", HTMLTextAreaElement::sanitizeUserInputValue("a\ncdef", 4));
+    EXPECT_EQ("a\ncd", HTMLTextAreaElement::sanitizeUserInputValue("a\ncdef", 4));
+    EXPECT_EQ("a\rcd", HTMLTextAreaElement::sanitizeUserInputValue("a\rcdef", 4));
+    EXPECT_EQ("a\r\ncd", HTMLTextAreaElement::sanitizeUserInputValue("a\r\ncdef", 4));
 }
 
 } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
index 332f680..205258a 100644
--- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
+++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
@@ -10,8 +10,8 @@
 #include "bindings/core/v8/V8DOMTokenList.h"
 #include "bindings/core/v8/V8Event.h"
 #include "bindings/core/v8/V8EventListener.h"
+#include "bindings/core/v8/V8EventListenerHelper.h"
 #include "bindings/core/v8/V8EventListenerInfo.h"
-#include "bindings/core/v8/V8EventListenerList.h"
 #include "bindings/core/v8/V8HTMLAllCollection.h"
 #include "bindings/core/v8/V8HTMLCollection.h"
 #include "bindings/core/v8/V8Node.h"
@@ -278,7 +278,7 @@
     if (!eventTarget)
         return;
     Vector<String> types = normalizeEventTypes(info);
-    EventListener* eventListener = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8::Local<v8::Function>::Cast(info.Data()), false, enabled ? ListenerFindOrCreate : ListenerFindOnly);
+    EventListener* eventListener = V8EventListenerHelper::getEventListener(ScriptState::current(info.GetIsolate()), v8::Local<v8::Function>::Cast(info.Data()), false, enabled ? ListenerFindOrCreate : ListenerFindOnly);
     if (!eventListener)
         return;
     for (size_t i = 0; i < types.size(); ++i) {
diff --git a/third_party/WebKit/Source/core/inspector/browser_protocol.json b/third_party/WebKit/Source/core/inspector/browser_protocol.json
index ea4a945b..5931848 100644
--- a/third_party/WebKit/Source/core/inspector/browser_protocol.json
+++ b/third_party/WebKit/Source/core/inspector/browser_protocol.json
@@ -3263,6 +3263,103 @@
         ]
     },
     {
+        "domain": "Target",
+        "description": "Supports discovery and auto-attach to related targets.",
+        "experimental": true,
+        "types": [
+            {
+                "id": "TargetID",
+                "type": "string"
+            },
+            {
+                "id": "TargetType",
+                "type": "string",
+                "enum": ["page", "frame", "worker", "service_worker"]
+            },
+            {
+                "id": "TargetInfo",
+                "type": "object",
+                "properties": [
+                    { "name": "targetId", "$ref": "TargetID" },
+                    { "name": "type", "$ref": "TargetType" },
+                    { "name": "title", "type": "string" },
+                    { "name": "url", "type": "string" }
+                ]
+            }
+        ],
+        "commands": [
+            {
+                "name": "enable",
+                "description": "Start discovering targets and attach to all related targets from now on.",
+                "handlers": ["browser"]
+            },
+            {
+                "name": "disable",
+                "description": "Stop discovering targets and detach from all currently attached targets.",
+                "handlers": ["browser"]
+            },
+            {
+                "name": "setWaitForDebuggerOnStart",
+                "parameters": [
+                    { "name": "value", "type": "boolean", "description": "Whether to pause new targets when attaching to them. Use <code>Runtime.runIfWaitingForDebugger</code> to run puased targets." }
+                ],
+                "handlers": ["browser"]
+            },
+            {
+                "name": "sendMessageToTarget",
+                "parameters": [
+                    { "name": "targetId", "type": "string" },
+                    { "name": "message", "type": "string" }
+                ],
+                "handlers": ["browser"]
+            },
+            {
+                "name": "getTargetInfo",
+                "parameters": [
+                    { "name": "targetId", "$ref": "TargetID" }
+                ],
+                "returns": [
+                    { "name": "targetInfo","$ref": "TargetInfo" }
+                ],
+                "handlers": ["browser"]
+            },
+            {
+                "name": "activateTarget",
+                "parameters": [
+                    { "name": "targetId", "$ref": "TargetID" }
+                ],
+                "handlers": ["browser"]
+            }
+        ],
+        "events": [
+            {
+                "name": "targetCreated",
+                "parameters": [
+                    { "name": "targetId", "$ref": "TargetID" },
+                    { "name": "type", "$ref": "TargetType" },
+                    { "name": "url", "type": "string" },
+                    { "name": "waitingForDebugger", "type": "boolean" }
+                ],
+                "handlers": ["browser"]
+            },
+            {
+                "name": "targetRemoved",
+                "parameters": [
+                    { "name": "targetId", "$ref": "TargetID" }
+                ],
+                "handlers": ["browser"]
+            },
+            {
+                "name": "receivedMessageFromTarget",
+                "parameters": [
+                    { "name": "targetId", "$ref": "TargetID" },
+                    { "name": "message", "type": "string" }
+                ],
+                "handlers": ["browser"]
+            }
+        ]
+    },
+    {
         "domain": "Worker",
         "experimental": true,
         "types": [],
@@ -3336,10 +3433,6 @@
                 "enum": ["new", "installing", "installed", "activating", "activated", "redundant"]
             },
             {
-                "id": "TargetID",
-                "type": "string"
-            },
-            {
                 "id": "ServiceWorkerVersion",
                 "type": "object",
                 "description": "ServiceWorker version.",
@@ -3351,7 +3444,8 @@
                     { "name": "status", "$ref": "ServiceWorkerVersionStatus" },
                     { "name": "scriptLastModified", "type": "number", "optional": true, "description": "The Last-Modified header value of the main script." },
                     { "name": "scriptResponseTime", "type": "number", "optional": true, "description": "The time at which the response headers of the main script were received from the server.  For cached script it is the last time the cache entry was validated." },
-                    { "name": "controlledClients", "type": "array", "optional": true, "items": { "$ref": "TargetID" } }
+                    { "name": "controlledClients", "type": "array", "optional": true, "items": { "$ref": "Target.TargetID" } },
+                    { "name": "targetId", "$ref": "Target.TargetID", "optional": true }
                 ]
             },
             {
@@ -3366,16 +3460,6 @@
                     { "name": "lineNumber", "type": "integer" },
                     { "name": "columnNumber", "type": "integer" }
                 ]
-            },
-            {
-                "id": "TargetInfo",
-                "type": "object",
-                "properties": [
-                    { "name": "id", "$ref": "TargetID" },
-                    { "name": "type", "type": "string" },
-                    { "name": "title", "type": "string" },
-                    { "name": "url", "type": "string" }
-                ]
             }
         ],
         "commands": [
@@ -3388,21 +3472,6 @@
                 "handlers": ["browser"]
             },
             {
-                "name": "sendMessage",
-                "parameters": [
-                    { "name": "workerId", "type": "string" },
-                    { "name": "message", "type": "string" }
-                ],
-                "handlers": ["browser"]
-            },
-            {
-                "name": "stop",
-                "parameters": [
-                    { "name": "workerId", "type": "string" }
-                ],
-                "handlers": ["browser"]
-            },
-            {
                 "name": "unregister",
                 "parameters": [
                     { "name": "scopeURL", "type": "string" }
@@ -3469,51 +3538,10 @@
                     { "name": "lastChance", "type": "boolean" }
                 ],
                 "handlers": ["browser"]
-            },
-            {
-                "name": "getTargetInfo",
-                "parameters": [
-                    { "name": "targetId", "$ref": "TargetID" }
-                ],
-                "returns": [
-                    { "name": "targetInfo","$ref": "TargetInfo" }
-                ],
-                "handlers": ["browser"]
-            },
-            {
-                "name": "activateTarget",
-                "parameters": [
-                    { "name": "targetId", "$ref": "TargetID" }
-                ],
-                "handlers": ["browser"]
             }
         ],
         "events": [
             {
-                "name": "workerCreated",
-                "parameters": [
-                    { "name": "workerId", "type": "string" },
-                    { "name": "url", "type": "string" },
-                    { "name": "versionId", "type": "string" }
-                ],
-                "handlers": ["browser"]
-            },
-            {
-                "name": "workerTerminated",
-                "parameters": [
-                    { "name": "workerId", "type": "string" }
-                ],
-                "handlers": ["browser"]
-            },
-            {
-                "name": "dispatchMessage",
-                "parameters": [
-                    { "name": "workerId", "type": "string" },
-                    { "name": "message", "type": "string" }
-                ],
-                "handlers": ["browser"]
-            },
-            {
                 "name": "workerRegistrationUpdated",
                 "parameters": [
                     { "name": "registrations", "type": "array", "items": { "$ref": "ServiceWorkerRegistration" } }
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index d2214743..5fd4d716 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2161,8 +2161,9 @@
     LayoutBox* tableRowContainer = nullptr;
     // Skip table row because cells and rows are in the same coordinate space
     // (see below, however for more comments about when |ancestor| is the table row).
-    if (container->isTableRow()) {
-        DCHECK(isTableCell() && parentBox() == container);
+    // The second and third conditionals below are to skip cases where content has display: table-row or display: table-cell but is not
+    // parented like a cell/row combo.
+    if (container->isTableRow() && isTableCell() && parentBox() == container) {
         if (container != ancestor)
             container = container->parent();
         else
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
index 5c58aa44..2673420 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -362,7 +362,7 @@
     LayoutRect clipRect;
     if (box.hasControlClip()) {
         clipRect = box.controlClipRect(context.current.paintOffset);
-    } else if (box.hasOverflowClip() || (box.isSVGRoot() && toLayoutSVGRoot(box).shouldApplyViewportClip())) {
+    } else if (box.hasOverflowClip() || box.styleRef().containsPaint() || (box.isSVGRoot() && toLayoutSVGRoot(box).shouldApplyViewportClip())) {
         clipRect = box.overflowClipRect(context.current.paintOffset);
     } else {
         if (ObjectPaintProperties* properties = object.getMutableForPainting().objectPaintProperties())
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
index bbb88a6..2ed81f8 100644
--- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
+++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -1648,6 +1648,37 @@
     CHECK_EXACT_VISUAL_RECT(LayoutRect(0, 0, 500, 600), child, clipper);
 }
 
+TEST_P(PaintPropertyTreeBuilderTest, ContainsPaintContentsProperties)
+{
+    setBodyInnerHTML(
+        "<style>body { margin: 0; }</style>"
+        "<div id='clipper' style='contain:paint; width:400px; height:300px;'>"
+        "  <div id='child' style='position:relative; width:500px; height: 600px;'></div>"
+        "</div>"
+    );
+
+    LayoutBoxModelObject* clipper = toLayoutBoxModelObject(document().getElementById("clipper")->layoutObject());
+    const ObjectPaintProperties* clipProperties = clipper->objectPaintProperties();
+    LayoutObject* child = document().getElementById("child")->layoutObject();
+    const ObjectPaintProperties* childProperties = child->objectPaintProperties();
+
+    // No scroll translation because the document does not scroll (not enough content).
+    EXPECT_TRUE(!frameScrollTranslation());
+    EXPECT_EQ(framePreTranslation(), clipProperties->localBorderBoxProperties()->geometryPropertyTreeState.transform);
+    EXPECT_EQ(frameContentClip(), clipProperties->localBorderBoxProperties()->geometryPropertyTreeState.clip);
+
+    GeometryPropertyTreeState contentsProperties;
+    clipProperties->getContentsProperties(contentsProperties);
+    EXPECT_EQ(framePreTranslation(), contentsProperties.transform);
+    EXPECT_EQ(clipProperties->overflowClip(), contentsProperties.clip);
+
+    EXPECT_EQ(framePreTranslation(), childProperties->localBorderBoxProperties()->geometryPropertyTreeState.transform);
+    EXPECT_EQ(clipProperties->overflowClip(), childProperties->localBorderBoxProperties()->geometryPropertyTreeState.clip);
+
+    EXPECT_NE(nullptr, childProperties->localBorderBoxProperties()->geometryPropertyTreeState.effect);
+    CHECK_EXACT_VISUAL_RECT(LayoutRect(0, 0, 500, 600), child, clipper);
+}
+
 TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollContentsProperties)
 {
     // This test verifies the tree builder correctly computes and records the property tree context
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
index 999f26b..4c5cd14 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerThread.cpp
@@ -46,7 +46,7 @@
 
 DedicatedWorkerThread::DedicatedWorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, InProcessWorkerObjectProxy& workerObjectProxy, double timeOrigin)
     : WorkerThread(std::move(workerLoaderProxy), workerObjectProxy)
-    , m_workerBackingThread(WorkerBackingThread::create("DedicatedWorker Thread", BlinkGC::MainThreadHeapMode))
+    , m_workerBackingThread(WorkerBackingThread::create("DedicatedWorker Thread", BlinkGC::PerThreadHeapMode))
     , m_workerObjectProxy(workerObjectProxy)
     , m_timeOrigin(timeOrigin)
 {
diff --git a/third_party/WebKit/Source/devtools/BUILD.gn b/third_party/WebKit/Source/devtools/BUILD.gn
index cda1d5c9..fc9325d 100644
--- a/third_party/WebKit/Source/devtools/BUILD.gn
+++ b/third_party/WebKit/Source/devtools/BUILD.gn
@@ -131,6 +131,7 @@
   "front_end/sdk/ServiceWorkerCacheModel.js",
   "front_end/sdk/ServiceWorkerManager.js",
   "front_end/sdk/SourceMap.js",
+  "front_end/sdk/SubTargetsManager.js",
   "front_end/sdk/Target.js",
   "front_end/sdk/TargetManager.js",
   "front_end/sdk/TracingManager.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js
index 4475652..86e5253 100644
--- a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js
+++ b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionAPI.js
@@ -57,6 +57,8 @@
         NetworkRequestFinished: "network-request-finished",
         OpenResource: "open-resource",
         PanelSearch: "panel-search-",
+        RecordingStarted: "trace-recording-started-",
+        RecordingStopped: "trace-recording-stopped-",
         ResourceAdded: "resource-added",
         ResourceContentCommitted: "resource-content-committed",
         ViewShown: "view-shown-",
@@ -68,6 +70,7 @@
         AddAuditCategory: "addAuditCategory",
         AddAuditResult: "addAuditResult",
         AddRequestHeaders: "addRequestHeaders",
+        AddTraceProvider: "addTraceProvider",
         ApplyStyleSheet: "applyStyleSheet",
         CreatePanel: "createPanel",
         CreateSidebarPane: "createSidebarPane",
@@ -183,6 +186,7 @@
     this.inspectedWindow = new InspectedWindow();
     this.panels = new Panels();
     this.network = new Network();
+    this.timeline = new Timeline();
     defineDeprecatedProperty(this, "webInspector", "resources", "network");
 }
 
@@ -549,6 +553,37 @@
 /**
  * @constructor
  */
+function Timeline()
+{
+}
+
+Timeline.prototype = {
+    /**
+     * @param {string} categoryName
+     * @param {string} categoryTooltip
+     * @return {!TraceProvider}
+     */
+    addTraceProvider: function(categoryName, categoryTooltip)
+    {
+        var id = "extension-trace-provider-" + extensionServer.nextObjectId();
+        extensionServer.sendRequest({ command: commands.AddTraceProvider, id: id, categoryName: categoryName, categoryTooltip: categoryTooltip});
+        return new TraceProvider(id);
+    }
+}
+
+/**
+ * @constructor
+ * @param {string} id
+ */
+function TraceProvider(id)
+{
+    this.onRecordingStarted = new EventSink(events.RecordingStarted + id);
+    this.onRecordingStopped = new EventSink(events.RecordingStopped + id);
+}
+
+/**
+ * @constructor
+ */
 function Audits()
 {
 }
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js
index a3b5b44..a92694f8 100644
--- a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js
+++ b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionServer.js
@@ -49,12 +49,15 @@
     this._sidebarPanes = [];
     /** @type {!Array.<!WebInspector.ExtensionAuditCategory>} */
     this._auditCategories = [];
+    /** @type {!Array.<!WebInspector.ExtensionTraceProvider>} */
+    this._traceProviders = [];
 
     var commands = WebInspector.extensionAPI.Commands;
 
     this._registerHandler(commands.AddAuditCategory, this._onAddAuditCategory.bind(this));
     this._registerHandler(commands.AddAuditResult, this._onAddAuditResult.bind(this));
     this._registerHandler(commands.AddRequestHeaders, this._onAddRequestHeaders.bind(this));
+    this._registerHandler(commands.AddTraceProvider, this._onAddTraceProvider.bind(this));
     this._registerHandler(commands.ApplyStyleSheet, this._onApplyStyleSheet.bind(this));
     this._registerHandler(commands.CreatePanel, this._onCreatePanel.bind(this));
     this._registerHandler(commands.CreateSidebarPane, this._onCreateSidebarPane.bind(this));
@@ -154,7 +157,6 @@
         this._postNotification(WebInspector.extensionAPI.Events.InspectedURLChanged, url);
     },
 
-
     /**
      * @param {string} categoryId
      * @param {!WebInspector.ExtensionAuditCategoryResults} auditResults
@@ -174,6 +176,22 @@
     },
 
     /**
+     * @param {string} traceProviderId
+     */
+    startTraceRecording: function(traceProviderId)
+    {
+        this._postNotification("trace-recording-started-" + traceProviderId);
+    },
+
+     /**
+     * @param {string} traceProviderId
+     */
+    stopTraceRecording: function(traceProviderId)
+    {
+        this._postNotification("trace-recording-stopped-" + traceProviderId);
+    },
+
+    /**
      * @param {string} type
      * @return {boolean}
      */
@@ -597,6 +615,25 @@
     },
 
     /**
+     * @param {!Object} message
+     * @param {!MessagePort} port
+     */
+    _onAddTraceProvider: function(message, port)
+    {
+        var provider = new WebInspector.ExtensionTraceProvider(port._extensionOrigin, message.id, message.categoryName, message.categoryTooltip);
+        this._clientObjects[message.id] = provider;
+        this._traceProviders.push(provider);
+    },
+
+    /**
+     * @return {!Array<!WebInspector.ExtensionTraceProvider>}
+     */
+    traceProviders: function()
+    {
+        return this._traceProviders;
+    },
+
+    /**
      * @return {!Array.<!WebInspector.ExtensionAuditCategory>}
      */
     auditCategories: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionTraceProvider.js b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionTraceProvider.js
new file mode 100644
index 0000000..b6cf93c5
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/extensions/ExtensionTraceProvider.js
@@ -0,0 +1,26 @@
+/**
+ * @constructor
+ * @param {string} extensionOrigin
+ * @param {string} id
+ * @param {string} categoryName
+ * @param {string} categoryTooltip
+ */
+WebInspector.ExtensionTraceProvider = function(extensionOrigin, id, categoryName, categoryTooltip)
+{
+    this._extensionOrigin = extensionOrigin;
+    this._id = id;
+    this._categoryName = categoryName;
+    this._categoryTooltip = categoryTooltip;
+}
+
+WebInspector.ExtensionTraceProvider.prototype = {
+    start: function()
+    {
+        WebInspector.extensionServer.startTraceRecording(this._id);
+    },
+
+    stop: function()
+    {
+        WebInspector.extensionServer.stopTraceRecording(this._id);
+    }
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/extensions/module.json b/third_party/WebKit/Source/devtools/front_end/extensions/module.json
index 334ccfaf..32e04fb 100644
--- a/third_party/WebKit/Source/devtools/front_end/extensions/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/extensions/module.json
@@ -6,6 +6,7 @@
         "ExtensionAPI.js",
         "ExtensionAuditCategory.js",
         "ExtensionRegistryStub.js",
+        "ExtensionTraceProvider.js",
         "ExtensionServer.js",
         "ExtensionPanel.js",
         "ExtensionView.js"
diff --git a/third_party/WebKit/Source/devtools/front_end/externs.js b/third_party/WebKit/Source/devtools/front_end/externs.js
index aa6ae75..e28311f 100644
--- a/third_party/WebKit/Source/devtools/front_end/externs.js
+++ b/third_party/WebKit/Source/devtools/front_end/externs.js
@@ -289,8 +289,6 @@
 function PanelWithSidebar() {}
 /** @constructor */
 function Resource() {}
-/** @constructor */
-function Timeline() {}
 
 var extensionServer;
 
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
index 0bac180..049bcf8 100644
--- a/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
+++ b/third_party/WebKit/Source/devtools/front_end/resources/ServiceWorkersView.js
@@ -33,6 +33,7 @@
         if (this._manager || !target.serviceWorkerManager || !securityOriginManager)
             return;
         this._manager = target.serviceWorkerManager;
+        this._subTargetsManager = target.subTargetsManager;
         this._securityOriginManager = securityOriginManager;
 
         this._toolbar.appendToolbarItem(WebInspector.NetworkConditionsSelector.createOfflineToolbarCheckbox());
@@ -108,7 +109,7 @@
     {
         var section = this._sections.get(registration);
         if (!section) {
-            section = new WebInspector.ServiceWorkersView.Section(this._manager, this._reportView.appendSection(""), registration);
+            section = new WebInspector.ServiceWorkersView.Section(this._manager, this._subTargetsManager, this._reportView.appendSection(""), registration);
             this._sections.set(registration, section);
         }
         this._updateSectionVisibility();
@@ -133,12 +134,14 @@
 /**
  * @constructor
  * @param {!WebInspector.ServiceWorkerManager} manager
+ * @param {!WebInspector.SubTargetsManager} subTargetsManager
  * @param {!WebInspector.ReportView.Section} section
  * @param {!WebInspector.ServiceWorkerRegistration} registration
  */
-WebInspector.ServiceWorkersView.Section = function(manager, section, registration)
+WebInspector.ServiceWorkersView.Section = function(manager, subTargetsManager, section, registration)
 {
     this._manager = manager;
+    this._subTargetsManager = subTargetsManager;
     this._section = section;
     this._registration = registration;
 
@@ -184,6 +187,18 @@
     },
 
     /**
+     * @param {string} versionId
+     * @return {?WebInspector.Target}
+     */
+    _targetForVersionId: function(versionId)
+    {
+        var version = this._manager.findVersion(versionId);
+        if (!version || !version.targetId)
+            return null;
+        return this._subTargetsManager.targetForId(version.targetId);
+    },
+
+    /**
      * @return {!Promise}
      */
     _update: function()
@@ -221,7 +236,7 @@
 
             if (active.isRunning() || active.isStarting()) {
                 createLink(activeEntry, WebInspector.UIString("stop"), this._stopButtonClicked.bind(this, active.id));
-                if (!this._manager.targetForVersionId(active.id))
+                if (!this._targetForVersionId(active.id))
                     createLink(activeEntry, WebInspector.UIString("inspect"), this._inspectButtonClicked.bind(this, active.id));
             } else if (active.isStartable()) {
                 createLink(activeEntry, WebInspector.UIString("start"), this._startButtonClicked.bind(this));
@@ -234,7 +249,7 @@
                 var clientLabelText = clientsList.createChild("div", "service-worker-client");
                 if (this._clientInfoCache.has(client))
                     this._updateClientInfo(clientLabelText, /** @type {!WebInspector.TargetInfo} */(this._clientInfoCache.get(client)));
-                this._manager.getTargetInfo(client, this._onClientInfo.bind(this, clientLabelText));
+                this._subTargetsManager.getTargetInfo(client, this._onClientInfo.bind(this, clientLabelText));
             }
         }
 
@@ -244,7 +259,7 @@
             waitingEntry.createChild("span").textContent = WebInspector.UIString("#%s waiting to activate", waiting.id);
             createLink(waitingEntry, WebInspector.UIString("skipWaiting"), this._skipButtonClicked.bind(this));
             waitingEntry.createChild("div", "service-worker-subtitle").textContent = new Date(waiting.scriptResponseTime * 1000).toLocaleString();
-            if (!this._manager.targetForVersionId(waiting.id) && (waiting.isRunning() || waiting.isStarting()))
+            if (!this._targetForVersionId(waiting.id) && (waiting.isRunning() || waiting.isStarting()))
                 createLink(waitingEntry, WebInspector.UIString("inspect"), this._inspectButtonClicked.bind(this, waiting.id));
         }
         if (installing) {
@@ -252,7 +267,7 @@
             installingEntry.createChild("div", "service-worker-installing-circle");
             installingEntry.createChild("span").textContent = WebInspector.UIString("#%s installing", installing.id);
             installingEntry.createChild("div", "service-worker-subtitle").textContent = new Date(installing.scriptResponseTime * 1000).toLocaleString();
-            if (!this._manager.targetForVersionId(installing.id) && (installing.isRunning() || installing.isStarting()))
+            if (!this._targetForVersionId(installing.id) && (installing.isRunning() || installing.isStarting()))
                 createLink(installingEntry, WebInspector.UIString("inspect"), this._inspectButtonClicked.bind(this, installing.id));
         }
 
@@ -285,7 +300,7 @@
      */
     _addError: function(error)
     {
-        var target = this._manager.targetForVersionId(error.versionId);
+        var target = this._targetForVersionId(error.versionId);
         var message = this._errorsList.createChild("div");
         if (this._errorsList.childElementCount > 100)
             this._errorsList.firstElementChild.remove();
@@ -334,8 +349,8 @@
      */
     _updateClientInfo: function(element, targetInfo)
     {
-        if (!(targetInfo.isWebContents() || targetInfo.isFrame())) {
-            element.createTextChild(WebInspector.UIString("Worker: %s", targetInfo.url));
+        if (!targetInfo.canActivate) {
+            element.createTextChild(targetInfo.title);
             return;
         }
         element.removeChildren();
@@ -350,7 +365,7 @@
      */
     _activateTarget: function(targetId)
     {
-        this._manager.activateTarget(targetId);
+        this._subTargetsManager.activateTarget(targetId);
     },
 
     _startButtonClicked: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js
index 23c70c3..ea199de7 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js
@@ -32,15 +32,14 @@
  * @constructor
  * @extends {WebInspector.SDKObject}
  * @param {!WebInspector.Target} target
+ * @param {!WebInspector.SubTargetsManager} subTargetsManager
  */
-WebInspector.ServiceWorkerManager = function(target)
+WebInspector.ServiceWorkerManager = function(target, subTargetsManager)
 {
     WebInspector.SDKObject.call(this, target);
     target.registerServiceWorkerDispatcher(new WebInspector.ServiceWorkerDispatcher(this));
     this._lastAnonymousTargetId = 0;
     this._agent = target.serviceWorkerAgent();
-    /** @type {!Map.<string, !WebInspector.ServiceWorker>} */
-    this._workers = new Map();
     /** @type {!Map.<string, !WebInspector.ServiceWorkerRegistration>} */
     this._registrations = new Map();
     this.enable();
@@ -48,12 +47,11 @@
     if (this._forceUpdateSetting.get())
         this._forceUpdateSettingChanged();
     this._forceUpdateSetting.addChangeListener(this._forceUpdateSettingChanged, this);
-    WebInspector.targetManager.addModelListener(WebInspector.RuntimeModel, WebInspector.RuntimeModel.Events.ExecutionContextCreated, this._executionContextCreated, this);
+    new WebInspector.ServiceWorkerContextNamer(target, this, subTargetsManager);
 }
 
 /** @enum {symbol} */
 WebInspector.ServiceWorkerManager.Events = {
-    WorkersUpdated: Symbol("WorkersUpdated"),
     RegistrationUpdated: Symbol("RegistrationUpdated"),
     RegistrationErrorAdded: Symbol("RegistrationErrorAdded"),
     RegistrationDeleted: Symbol("RegistrationDeleted")
@@ -65,9 +63,7 @@
         if (this._enabled)
             return;
         this._enabled = true;
-
         this._agent.enable();
-        WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.MainFrameNavigated, this._mainFrameNavigated, this);
     },
 
     disable: function()
@@ -75,42 +71,8 @@
         if (!this._enabled)
             return;
         this._enabled = false;
-
-        for (var worker of this._workers.values())
-            worker._connection.close();
-        this._workers.clear();
         this._registrations.clear();
         this._agent.disable();
-        WebInspector.targetManager.removeEventListener(WebInspector.TargetManager.Events.MainFrameNavigated, this._mainFrameNavigated, this);
-    },
-
-    /**
-     * @return {!Iterable.<!WebInspector.ServiceWorker>}
-     */
-    workers: function()
-    {
-        return this._workers.values();
-    },
-
-    /**
-     * @param {string} versionId
-     * @return {?WebInspector.Target}
-     */
-    targetForVersionId: function(versionId)
-    {
-        for (var pair of this._workers) {
-            if (pair[1]._versionId === versionId)
-                return pair[1]._target;
-        }
-        return null;
-    },
-
-    /**
-     * @return {boolean}
-     */
-    hasWorkers: function()
-    {
-        return !!this._workers.size;
     },
 
     /**
@@ -193,14 +155,6 @@
     },
 
     /**
-     * @param {!ServiceWorkerAgent.TargetID} targetId
-     */
-    activateTarget: function(targetId)
-    {
-        this._agent.activateTarget(targetId);
-    },
-
-    /**
      * @param {string} scope
      */
     _unregister: function(scope)
@@ -241,68 +195,6 @@
     },
 
     /**
-     * @param {!ServiceWorkerAgent.TargetID} targetId
-     * @param {function(?WebInspector.TargetInfo)=} callback
-     */
-    getTargetInfo: function(targetId, callback)
-    {
-        /**
-         * @param {?Protocol.Error} error
-         * @param {?ServiceWorkerAgent.TargetInfo} targetInfo
-         */
-        function innerCallback(error, targetInfo)
-        {
-            if (error) {
-                console.error(error);
-                callback(null);
-                return;
-            }
-            if (targetInfo)
-                callback(new WebInspector.TargetInfo(targetInfo));
-            else
-                callback(null)
-        }
-        this._agent.getTargetInfo(targetId, innerCallback);
-    },
-
-    /**
-     * @param {string} workerId
-     * @param {string} url
-     * @param {string} versionId
-     */
-    _workerCreated: function(workerId, url, versionId)
-    {
-        new WebInspector.ServiceWorker(this, workerId, url, versionId);
-        this._updateWorkerStatuses();
-    },
-
-    /**
-     * @param {string} workerId
-     */
-    _workerTerminated: function(workerId)
-    {
-        var worker = this._workers.get(workerId);
-        if (!worker)
-            return;
-
-        worker._closeConnection();
-        this._workers.delete(workerId);
-
-        this.dispatchEventToListeners(WebInspector.ServiceWorkerManager.Events.WorkersUpdated);
-    },
-
-    /**
-     * @param {string} workerId
-     * @param {string} message
-     */
-    _dispatchMessage: function(workerId, message)
-    {
-        var worker = this._workers.get(workerId);
-        if (worker)
-            worker._connection.dispatch(message);
-    },
-
-    /**
      * @param {!Array.<!ServiceWorkerAgent.ServiceWorkerRegistration>} registrations
      */
     _workerRegistrationUpdated: function(registrations)
@@ -348,22 +240,6 @@
                 this.dispatchEventToListeners(WebInspector.ServiceWorkerManager.Events.RegistrationUpdated, registration);
             }
         }
-        this._updateWorkerStatuses();
-    },
-
-    _updateWorkerStatuses: function()
-    {
-        /** @type {!Map<string, string>} */
-        var versionById = new Map();
-        for (var registration of this._registrations.valuesArray()) {
-            for (var version of registration.versions.valuesArray())
-                versionById.set(version.id, version.status);
-        }
-        for (var worker of this._workers.valuesArray()) {
-            var status = versionById.get(worker.versionId());
-            if (status)
-                worker.setStatus(status);
-        }
     },
 
     /**
@@ -379,14 +255,6 @@
     },
 
     /**
-     * @param {!WebInspector.Event} event
-     */
-    _mainFrameNavigated: function(event)
-    {
-        // Attach to the new worker set.
-    },
-
-    /**
      * @return {!WebInspector.Setting}
      */
     forceUpdateOnReloadSetting: function()
@@ -399,131 +267,11 @@
         this._agent.setForceUpdateOnPageLoad(this._forceUpdateSetting.get());
     },
 
-    /**
-     * @param {!WebInspector.Event} event
-     */
-    _executionContextCreated: function(event)
-    {
-        var executionContext = /** @type {!WebInspector.ExecutionContext} */ (event.data);
-        var target = executionContext.target();
-        if (!target.parentTarget())
-            return;
-        var worker = target.parentTarget()[WebInspector.ServiceWorker.Symbol];
-        if (worker)
-            worker._setContextLabelFor(executionContext);
-    },
-
     __proto__: WebInspector.SDKObject.prototype
 }
 
 /**
  * @constructor
- * @param {!WebInspector.ServiceWorkerManager} manager
- * @param {string} workerId
- * @param {string} url
- * @param {string} versionId
- */
-WebInspector.ServiceWorker = function(manager, workerId, url, versionId)
-{
-    this._manager = manager;
-    this._agent = manager.target().serviceWorkerAgent();
-    this._workerId = workerId;
-    this._connection = new WebInspector.ServiceWorkerConnection(this._agent, workerId);
-    this._url = url;
-    this._versionId = versionId;
-    var parsedURL = url.asParsedURL();
-    this._name = parsedURL ? parsedURL.lastPathComponentWithFragment()  : "#" + (++WebInspector.ServiceWorker._lastAnonymousTargetId);
-    this._scope = parsedURL ? parsedURL.host + parsedURL.folderPathComponents : "";
-
-    this._manager._workers.set(workerId, this);
-    var capabilities =
-        WebInspector.Target.Capability.Log | WebInspector.Target.Capability.Network |
-        WebInspector.Target.Capability.Worker;
-    this._target = WebInspector.targetManager.createTarget(this._name, capabilities, this._connection, manager.target());
-    this._target[WebInspector.ServiceWorker.Symbol] = this;
-    this._manager.dispatchEventToListeners(WebInspector.ServiceWorkerManager.Events.WorkersUpdated);
-    this._target.runtimeAgent().runIfWaitingForDebugger();
-}
-
-WebInspector.ServiceWorker.Symbol = Symbol("serviceWorker");
-
-WebInspector.ServiceWorker._lastAnonymousTargetId = 0;
-
-WebInspector.ServiceWorker.prototype = {
-    /**
-     * @return {string}
-     */
-    name: function()
-    {
-        return this._name;
-    },
-
-    /**
-     * @return {string}
-     */
-    url: function()
-    {
-        return this._url;
-    },
-
-    /**
-     * @return {string}
-     */
-    versionId: function()
-    {
-        return this._versionId;
-    },
-
-    /**
-     * @return {string}
-     */
-    scope: function()
-    {
-        return this._scope;
-    },
-
-    stop: function()
-    {
-        this._agent.stop(this._workerId);
-    },
-
-    /** @param {string} status */
-    setStatus: function(status)
-    {
-        if (this._status === status)
-            return;
-        this._status = status;
-
-        for (var target of WebInspector.targetManager.targets()) {
-            if (target.parentTarget() !== this._target)
-                continue;
-            for (var context of target.runtimeModel.executionContexts())
-                this._setContextLabelFor(context);
-        }
-    },
-
-    /**
-     * @param {!WebInspector.ExecutionContext} context
-     */
-    _setContextLabelFor: function(context)
-    {
-        var parsedUrl = context.origin.asParsedURL();
-        var label = parsedUrl ? parsedUrl.lastPathComponentWithFragment() : context.name;
-        if (this._status)
-            context.setLabel(label + " #" + this._versionId + " (" + this._status + ")");
-        else
-            context.setLabel(label);
-    },
-
-    _closeConnection: function()
-    {
-        this._connection._close();
-        delete this._connection;
-    }
-}
-
-/**
- * @constructor
  * @implements {ServiceWorkerAgent.Dispatcher}
  * @param {!WebInspector.ServiceWorkerManager} manager
  */
@@ -535,36 +283,6 @@
 WebInspector.ServiceWorkerDispatcher.prototype = {
     /**
      * @override
-     * @param {string} workerId
-     * @param {string} url
-     * @param {string} versionId
-     */
-    workerCreated: function(workerId, url, versionId)
-    {
-        this._manager._workerCreated(workerId, url, versionId);
-    },
-
-    /**
-     * @override
-     * @param {string} workerId
-     */
-    workerTerminated: function(workerId)
-    {
-        this._manager._workerTerminated(workerId);
-    },
-
-    /**
-     * @override
-     * @param {string} workerId
-     * @param {string} message
-     */
-    dispatchMessage: function(workerId, message)
-    {
-        this._manager._dispatchMessage(workerId, message);
-    },
-
-    /**
-     * @override
      * @param {!Array.<!ServiceWorkerAgent.ServiceWorkerRegistration>} registrations
      */
     workerRegistrationUpdated: function(registrations)
@@ -593,68 +311,6 @@
 
 /**
  * @constructor
- * @extends {InspectorBackendClass.Connection}
- * @param {!Protocol.ServiceWorkerAgent} agent
- * @param {string} workerId
- */
-WebInspector.ServiceWorkerConnection = function(agent, workerId)
-{
-    InspectorBackendClass.Connection.call(this);
-    // FIXME: remove resourceTreeModel and others from worker targets
-    this.suppressErrorsForDomains(["Worker", "Page", "CSS", "DOM", "DOMStorage", "Database", "Network", "IndexedDB"]);
-    this._agent = agent;
-    this._workerId = workerId;
-}
-
-WebInspector.ServiceWorkerConnection.prototype = {
-    /**
-     * @override
-     * @param {!Object} messageObject
-     */
-    sendMessage: function(messageObject)
-    {
-        this._agent.sendMessage(this._workerId, JSON.stringify(messageObject));
-    },
-
-    _close: function()
-    {
-        this.connectionClosed("worker_terminated");
-    },
-
-    __proto__: InspectorBackendClass.Connection.prototype
-}
-
-/**
- * @constructor
- * @param {!ServiceWorkerAgent.TargetInfo} payload
- */
-WebInspector.TargetInfo = function(payload)
-{
-    this.id = payload.id;
-    this.type = payload.type;
-    this.title = payload.title;
-    this.url = payload.url;
-}
-
-WebInspector.TargetInfo.prototype = {
-    /**
-     * @return {boolean}
-     */
-    isWebContents: function()
-    {
-        return this.type === "page";
-    },
-    /**
-     * @return {boolean}
-     */
-    isFrame: function()
-    {
-        return this.type === "frame";
-    },
-}
-
-/**
- * @constructor
  * @param {!WebInspector.ServiceWorkerRegistration} registration
  * @param {!ServiceWorkerAgent.ServiceWorkerVersion} payload
  */
@@ -691,6 +347,7 @@
         this.controlledClients = [];
         for (var i = 0; i < payload.controlledClients.length; ++i)
             this.controlledClients.push(payload.controlledClients[i]);
+        this.targetId = payload.targetId || null;
     },
 
     /**
@@ -896,3 +553,92 @@
         this.errors = [];
     }
 }
+
+/**
+ * @constructor
+ * @param {!WebInspector.Target} target
+ * @param {!WebInspector.ServiceWorkerManager} serviceWorkerManager
+ * @param {!WebInspector.SubTargetsManager} subTargetsManager
+ */
+WebInspector.ServiceWorkerContextNamer = function(target, serviceWorkerManager, subTargetsManager)
+{
+    this._target = target;
+    this._serviceWorkerManager = serviceWorkerManager;
+    this._subTargetsManager = subTargetsManager;
+    /** @type {!Map<string, !WebInspector.ServiceWorkerVersion>} */
+    this._versionByTargetId = new Map();
+    serviceWorkerManager.addEventListener(WebInspector.ServiceWorkerManager.Events.RegistrationUpdated, this._registrationsUpdated, this);
+    serviceWorkerManager.addEventListener(WebInspector.ServiceWorkerManager.Events.RegistrationDeleted, this._registrationsUpdated, this);
+    WebInspector.targetManager.addModelListener(WebInspector.RuntimeModel, WebInspector.RuntimeModel.Events.ExecutionContextCreated, this._executionContextCreated, this);
+}
+
+WebInspector.ServiceWorkerContextNamer.prototype = {
+    /**
+     * @param {!WebInspector.Event} event
+     */
+    _registrationsUpdated: function(event)
+    {
+        this._versionByTargetId.clear();
+        var registrations = this._serviceWorkerManager.registrations().valuesArray();
+        for (var registration of registrations) {
+            var versions = registration.versions.valuesArray();
+            for (var version of versions) {
+                if (version.targetId)
+                    this._versionByTargetId.set(version.targetId, version);
+            }
+        }
+        this._updateAllContextLabels();
+    },
+
+    /**
+     * @param {!WebInspector.Event} event
+     */
+    _executionContextCreated: function(event)
+    {
+        var executionContext = /** @type {!WebInspector.ExecutionContext} */ (event.data);
+        var serviceWorkerTargetId = this._serviceWorkerTargetIdForWorker(executionContext.target());
+        if (!serviceWorkerTargetId)
+            return;
+        this._updateContextLabel(executionContext, this._versionByTargetId.get(serviceWorkerTargetId) || null);
+    },
+
+    /**
+     * @param {!WebInspector.Target} target
+     * @return {?string}
+     */
+    _serviceWorkerTargetIdForWorker: function(target)
+    {
+        var parent = target.parentTarget();
+        if (!parent || parent.parentTarget() !== this._target)
+            return null;
+        if (this._subTargetsManager.targetType(parent) !== "service_worker")
+            return null;
+        return this._subTargetsManager.targetId(parent);
+    },
+
+    _updateAllContextLabels: function()
+    {
+        for (var target of WebInspector.targetManager.targets()) {
+            var serviceWorkerTargetId = this._serviceWorkerTargetIdForWorker(target);
+            if (!serviceWorkerTargetId)
+                continue;
+            var version = this._versionByTargetId.get(serviceWorkerTargetId) || null;
+            for (var context of target.runtimeModel.executionContexts())
+                this._updateContextLabel(context, version);
+        }
+    },
+
+    /**
+     * @param {!WebInspector.ExecutionContext} context
+     * @param {?WebInspector.ServiceWorkerVersion} version
+     */
+    _updateContextLabel: function(context, version)
+    {
+        var parsedUrl = context.origin.asParsedURL();
+        var label = parsedUrl ? parsedUrl.lastPathComponentWithFragment() : context.name;
+        if (version)
+            context.setLabel(label + " #" + version.id + " (" + version.status + ")");
+        else
+            context.setLabel(label);
+    },
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js
new file mode 100644
index 0000000..c248eec
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js
@@ -0,0 +1,288 @@
+// 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.
+
+/**
+ * @constructor
+ * @extends {WebInspector.SDKModel}
+ * @param {!WebInspector.Target} target
+ */
+WebInspector.SubTargetsManager = function(target)
+{
+    WebInspector.SDKModel.call(this, WebInspector.SubTargetsManager, target);
+    target.registerTargetDispatcher(new WebInspector.SubTargetsDispatcher(this));
+    this._lastAnonymousTargetId = 0;
+    this._agent = target.targetAgent();
+
+    /** @type {!Map<string, !WebInspector.Target>} */
+    this._targets = new Map();
+    /** @type {!Map<string, !WebInspector.SubTargetConnection>} */
+    this._connections = new Map();
+
+    this._agent.setWaitForDebuggerOnStart(true);
+    this._agent.enable();
+}
+
+/** @enum {symbol} */
+WebInspector.SubTargetsManager.Events = {
+    SubTargetAdded: Symbol("SubTargetAdded"),
+    SubTargetRemoved: Symbol("SubTargetRemoved"),
+}
+
+WebInspector.SubTargetsManager._TypeSymbol = Symbol("SubTargetType");
+WebInspector.SubTargetsManager._IdSymbol = Symbol("SubTargetId");
+
+WebInspector.SubTargetsManager.prototype = {
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    suspendModel: function()
+    {
+        var fulfill;
+        var promise = new Promise(f => fulfill = f);
+        this._agent.setWaitForDebuggerOnStart(false, fulfill);
+        return promise;
+    },
+
+    /**
+     * @override
+     * @return {!Promise}
+     */
+    resumeModel: function()
+    {
+        var fulfill;
+        var promise = new Promise(f => fulfill = f);
+        this._agent.setWaitForDebuggerOnStart(true, fulfill);
+        return promise;
+    },
+
+    /**
+     * @override
+     */
+    dispose: function()
+    {
+        for (var connection of this._connections.values())
+            connection._close();
+        this._connections.clear();
+        this._targets.clear();
+    },
+
+    /**
+     * @param {!TargetAgent.TargetID} targetId
+     */
+    activateTarget: function(targetId)
+    {
+        this._agent.activateTarget(targetId);
+    },
+
+    /**
+     * @param {!TargetAgent.TargetID} targetId
+     * @param {function(?WebInspector.TargetInfo)=} callback
+     */
+    getTargetInfo: function(targetId, callback)
+    {
+        /**
+         * @param {?Protocol.Error} error
+         * @param {?TargetAgent.TargetInfo} targetInfo
+         */
+        function innerCallback(error, targetInfo)
+        {
+            if (error) {
+                console.error(error);
+                callback(null);
+                return;
+            }
+            if (targetInfo)
+                callback(new WebInspector.TargetInfo(targetInfo));
+            else
+                callback(null)
+        }
+        this._agent.getTargetInfo(targetId, innerCallback);
+    },
+
+    /**
+     * @param {string} targetId
+     * @return {?WebInspector.Target}
+     */
+    targetForId: function(targetId)
+    {
+        return this._targets.get(targetId) || null;
+    },
+
+    /**
+     * @param {!WebInspector.Target} target
+     * @return {?string}
+     */
+    targetId: function(target)
+    {
+        return target[WebInspector.SubTargetsManager._IdSymbol] || null;
+    },
+
+    /**
+     * @param {!WebInspector.Target} target
+     * @return {?string}
+     */
+    targetType: function(target)
+    {
+        return target[WebInspector.SubTargetsManager._TypeSymbol] || null;
+    },
+
+    /**
+     * @param {string} type
+     * @return {number}
+     */
+    _capabilitiesForType: function(type)
+    {
+        if (type === "worker")
+            return WebInspector.Target.Capability.JS | WebInspector.Target.Capability.Log;
+        if (type === "service_worker")
+            return WebInspector.Target.Capability.Log | WebInspector.Target.Capability.Network | WebInspector.Target.Capability.Worker;
+        return 0;
+    },
+
+    /**
+     * @param {string} targetId
+     * @param {string} type
+     * @param {string} url
+     * @param {boolean} waitingForDebugger
+     */
+    _targetCreated: function(targetId, type, url, waitingForDebugger)
+    {
+        var connection = new WebInspector.SubTargetConnection(this._agent, targetId);
+        this._connections.set(targetId, connection);
+
+        var parsedURL = url.asParsedURL();
+        var targetName = parsedURL ? parsedURL.lastPathComponentWithFragment() : "#" + (++this._lastAnonymousTargetId);
+        var target = WebInspector.targetManager.createTarget(targetName, this._capabilitiesForType(type), connection, this.target());
+        target[WebInspector.SubTargetsManager._TypeSymbol] = type;
+        target[WebInspector.SubTargetsManager._IdSymbol] = targetId;
+        this._targets.set(targetId, target);
+
+        // Only pause new worker if debugging SW - we are going through the pause on start checkbox.
+        var mainIsServiceWorker = !this.target().parentTarget() && this.target().hasWorkerCapability() && !this.target().hasBrowserCapability();
+        if (mainIsServiceWorker && waitingForDebugger)
+            target.debuggerAgent().pause();
+        target.runtimeAgent().runIfWaitingForDebugger();
+
+        this.dispatchEventToListeners(WebInspector.SubTargetsManager.Events.SubTargetAdded, target);
+    },
+
+    /**
+     * @param {string} targetId
+     */
+    _targetRemoved: function(targetId)
+    {
+        var connection = this._connections.get(targetId);
+        if (connection)
+            connection._close();
+        this._connections.delete(targetId);
+        var target = this._targets.get(targetId);
+        this._targets.delete(targetId);
+        this.dispatchEventToListeners(WebInspector.SubTargetsManager.Events.SubTargetRemoved, target);
+    },
+
+    /**
+     * @param {string} targetId
+     * @param {string} message
+     */
+    _receivedMessageFromTarget: function(targetId, message)
+    {
+        var connection = this._connections.get(targetId);
+        if (connection)
+            connection.dispatch(message);
+    },
+
+    __proto__: WebInspector.SDKModel.prototype
+}
+
+/**
+ * @constructor
+ * @implements {TargetAgent.Dispatcher}
+ * @param {!WebInspector.SubTargetsManager} manager
+ */
+WebInspector.SubTargetsDispatcher = function(manager)
+{
+    this._manager = manager;
+}
+
+WebInspector.SubTargetsDispatcher.prototype = {
+    /**
+     * @override
+     * @param {string} targetId
+     * @param {string} type
+     * @param {string} url
+     * @param {boolean} waitingForDebugger
+     */
+    targetCreated: function(targetId, type, url, waitingForDebugger)
+    {
+        this._manager._targetCreated(targetId, type, url, waitingForDebugger);
+    },
+
+    /**
+     * @override
+     * @param {string} targetId
+     */
+    targetRemoved: function(targetId)
+    {
+        this._manager._targetRemoved(targetId);
+    },
+
+    /**
+     * @override
+     * @param {string} targetId
+     * @param {string} message
+     */
+    receivedMessageFromTarget: function(targetId, message)
+    {
+        this._manager._receivedMessageFromTarget(targetId, message);
+    }
+}
+
+/**
+ * @constructor
+ * @extends {InspectorBackendClass.Connection}
+ * @param {!Protocol.TargetAgent} agent
+ * @param {string} targetId
+ */
+WebInspector.SubTargetConnection = function(agent, targetId)
+{
+    InspectorBackendClass.Connection.call(this);
+    this._agent = agent;
+    this._targetId = targetId;
+}
+
+WebInspector.SubTargetConnection.prototype = {
+    /**
+     * @override
+     * @param {!Object} messageObject
+     */
+    sendMessage: function(messageObject)
+    {
+        this._agent.sendMessageToTarget(this._targetId, JSON.stringify(messageObject));
+    },
+
+    _close: function()
+    {
+        this.connectionClosed("target_terminated");
+    },
+
+    __proto__: InspectorBackendClass.Connection.prototype
+}
+
+/**
+ * @constructor
+ * @param {!TargetAgent.TargetInfo} payload
+ */
+WebInspector.TargetInfo = function(payload)
+{
+    this.id = payload.targetId;
+    this.url = payload.url;
+    if (payload.type !== "page" && payload.type !== "frame") {
+        this.title = WebInspector.UIString("Worker: %s", this.url);
+        this.canActivate = false;
+    } else {
+        this.title = payload.title;
+        this.canActivate = true;
+    }
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
index ed81dfd..fd5b036a 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
@@ -224,8 +224,10 @@
 
         target.tracingManager = new WebInspector.TracingManager(target);
 
-        if (target.hasBrowserCapability())
-            target.serviceWorkerManager = new WebInspector.ServiceWorkerManager(target);
+        if (target.hasBrowserCapability()) {
+            target.subTargetsManager = new WebInspector.SubTargetsManager(target);
+            target.serviceWorkerManager = new WebInspector.ServiceWorkerManager(target, target.subTargetsManager);
+        }
 
         this.addTarget(target);
         return target;
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/module.json b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
index 1c4fd89e..b5ed413 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
@@ -98,6 +98,7 @@
         "HAREntry.js",
         "NetworkLog.js",
         "ServiceWorkerManager.js",
+        "SubTargetsManager.js",
         "TracingManager.js",
         "TracingModel.js",
         "WorkerManager.js",
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js
index eeb468e..bff0aa5 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineController.js
@@ -29,6 +29,8 @@
      */
     startRecording: function(captureCauses, enableJSSampling, captureMemory, capturePictures, captureFilmStrip)
     {
+        this._extensionTraceProviders = WebInspector.extensionServer.traceProviders().slice();
+
         function disabledByDefault(category)
         {
             return "disabled-by-default-" + category;
@@ -66,6 +68,9 @@
         if (captureFilmStrip)
             categoriesArray.push(disabledByDefault("devtools.screenshot"));
 
+        for (var traceProvider of this._extensionTraceProviders)
+            traceProvider.start();
+
         var categories = categoriesArray.join(",");
         this._startRecordingWithCategories(categories, enableJSSampling);
     },
@@ -80,6 +85,9 @@
         Promise.all(tracingStoppedPromises).then(() => this._allSourcesFinished());
 
         this._delegate.loadingStarted();
+
+        for (var traceProvider of this._extensionTraceProviders)
+            traceProvider.stop();
     },
 
     /**
diff --git a/third_party/WebKit/Source/modules/BUILD.gn b/third_party/WebKit/Source/modules/BUILD.gn
index e4fa4dd..1ebc245 100644
--- a/third_party/WebKit/Source/modules/BUILD.gn
+++ b/third_party/WebKit/Source/modules/BUILD.gn
@@ -233,13 +233,10 @@
     "fetch/BytesConsumerForDataConsumerHandleTest.cpp",
     "fetch/BytesConsumerTest.cpp",
     "fetch/BytesConsumerTestUtil.cpp",
-    "fetch/CompositeDataConsumerHandleTest.cpp",
     "fetch/DataConsumerHandleTestUtil.cpp",
     "fetch/DataConsumerHandleTestUtil.h",
     "fetch/DataConsumerHandleUtilTest.cpp",
-    "fetch/FetchBlobDataConsumerHandleTest.cpp",
     "fetch/FetchDataLoaderTest.cpp",
-    "fetch/FetchFormDataConsumerHandleTest.cpp",
     "fetch/FetchResponseDataTest.cpp",
     "fetch/FormDataBytesConsumerTest.cpp",
     "fetch/ReadableStreamDataConsumerHandleTest.cpp",
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp b/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
index 25f5e6a..84d704d4 100644
--- a/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
+++ b/third_party/WebKit/Source/modules/cachestorage/CacheTest.cpp
@@ -16,7 +16,7 @@
 #include "core/frame/Frame.h"
 #include "core/testing/DummyPageHolder.h"
 #include "modules/fetch/BodyStreamBuffer.h"
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
+#include "modules/fetch/FormDataBytesConsumer.h"
 #include "modules/fetch/GlobalFetch.h"
 #include "modules/fetch/Request.h"
 #include "modules/fetch/Response.h"
@@ -626,7 +626,7 @@
     fetcher->setExpectedFetchUrl(&url);
 
     Request* request = newRequestFromUrl(url);
-    Response* response = Response::create(getScriptState(), new BodyStreamBuffer(getScriptState(), FetchFormDataConsumerHandle::create(content)), contentType, ResponseInit(), exceptionState);
+    Response* response = Response::create(getScriptState(), new BodyStreamBuffer(getScriptState(), new FormDataBytesConsumer(content)), contentType, ResponseInit(), exceptionState);
     fetcher->setResponse(response);
 
     WebVector<WebServiceWorkerCache::BatchOperation> expectedPutOperations(size_t(1));
diff --git a/third_party/WebKit/Source/modules/fetch/BUILD.gn b/third_party/WebKit/Source/modules/fetch/BUILD.gn
index 156dfbb..ed634fe 100644
--- a/third_party/WebKit/Source/modules/fetch/BUILD.gn
+++ b/third_party/WebKit/Source/modules/fetch/BUILD.gn
@@ -16,19 +16,12 @@
     "BytesConsumer.h",
     "BytesConsumerForDataConsumerHandle.cpp",
     "BytesConsumerForDataConsumerHandle.h",
-    "CompositeDataConsumerHandle.cpp",
-    "CompositeDataConsumerHandle.h",
-    "CrossThreadHolder.h",
     "DataConsumerHandleUtil.cpp",
     "DataConsumerHandleUtil.h",
-    "FetchBlobDataConsumerHandle.cpp",
-    "FetchBlobDataConsumerHandle.h",
     "FetchDataConsumerHandle.cpp",
     "FetchDataConsumerHandle.h",
     "FetchDataLoader.cpp",
     "FetchDataLoader.h",
-    "FetchFormDataConsumerHandle.cpp",
-    "FetchFormDataConsumerHandle.h",
     "FetchHeaderList.cpp",
     "FetchHeaderList.h",
     "FetchManager.cpp",
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
index e7c4beb..67450d4 100644
--- a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
+++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
@@ -6,10 +6,10 @@
 
 #include "bindings/core/v8/V8BindingForTesting.h"
 #include "core/html/FormData.h"
+#include "modules/fetch/BlobBytesConsumer.h"
 #include "modules/fetch/BytesConsumerTestUtil.h"
 #include "modules/fetch/DataConsumerHandleTestUtil.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
+#include "modules/fetch/FormDataBytesConsumer.h"
 #include "platform/blob/BlobData.h"
 #include "platform/blob/BlobURL.h"
 #include "platform/network/EncodedFormData.h"
@@ -33,15 +33,6 @@
 using ReplayingHandle = DataConsumerHandleTestUtil::ReplayingHandle;
 using MockFetchDataLoaderClient = DataConsumerHandleTestUtil::MockFetchDataLoaderClient;
 
-class FakeLoaderFactory : public FetchBlobDataConsumerHandle::LoaderFactory {
-public:
-    ThreadableLoader* create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) override
-    {
-        ASSERT_NOT_REACHED();
-        return nullptr;
-    }
-};
-
 class BodyStreamBufferTest : public ::testing::Test {
 protected:
     ScriptValue eval(ScriptState* scriptState, const char* s)
@@ -174,7 +165,7 @@
     data->appendText("hello", false);
     auto size = data->length();
     RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(std::move(data), size);
-    BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), FetchBlobDataConsumerHandle::create(scope.getExecutionContext(), blobDataHandle, new FakeLoaderFactory));
+    BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), new BlobBytesConsumer(scope.getExecutionContext(), blobDataHandle));
 
     EXPECT_FALSE(buffer->isStreamLocked());
     EXPECT_FALSE(buffer->isStreamDisturbed());
@@ -232,7 +223,7 @@
     data->append("name2", "value2");
     RefPtr<EncodedFormData> inputFormData = data->encodeMultiPartFormData();
 
-    BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), FetchFormDataConsumerHandle::create(scope.getExecutionContext(), inputFormData));
+    BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), new FormDataBytesConsumer(scope.getExecutionContext(), inputFormData));
 
     EXPECT_FALSE(buffer->isStreamLocked());
     EXPECT_FALSE(buffer->isStreamDisturbed());
diff --git a/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp b/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp
index aa2f440..2a551390 100644
--- a/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp
+++ b/third_party/WebKit/Source/modules/fetch/BytesConsumer.cpp
@@ -7,7 +7,6 @@
 #include "core/dom/ExecutionContext.h"
 #include "core/dom/TaskRunnerHelper.h"
 #include "modules/fetch/BlobBytesConsumer.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
 #include "platform/blob/BlobData.h"
 #include "public/platform/WebTaskRunner.h"
 #include "wtf/Functional.h"
diff --git a/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.h b/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.h
index 8f11070..13b816c 100644
--- a/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.h
+++ b/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.h
@@ -7,7 +7,7 @@
 
 #include "modules/ModulesExport.h"
 #include "modules/fetch/BytesConsumer.h"
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
+#include "modules/fetch/FetchDataConsumerHandle.h"
 #include "platform/heap/Handle.h"
 #include "public/platform/WebDataConsumerHandle.h"
 #include "wtf/PassRefPtr.h"
diff --git a/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandle.cpp b/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandle.cpp
deleted file mode 100644
index 035c0b13..0000000
--- a/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandle.cpp
+++ /dev/null
@@ -1,219 +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.
-
-#include "modules/fetch/CompositeDataConsumerHandle.h"
-
-#include "platform/CrossThreadFunctional.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebTaskRunner.h"
-#include "public/platform/WebThread.h"
-#include "public/platform/WebTraceLocation.h"
-#include "wtf/Locker.h"
-#include "wtf/PtrUtil.h"
-#include "wtf/ThreadSafeRefCounted.h"
-#include "wtf/ThreadingPrimitives.h"
-#include <memory>
-
-namespace blink {
-
-using Result = WebDataConsumerHandle::Result;
-
-class CompositeDataConsumerHandle::ReaderImpl final : public WebDataConsumerHandle::Reader {
-public:
-    explicit ReaderImpl(PassRefPtr<Context>);
-    ~ReaderImpl() override;
-    Result read(void* data, size_t /* size */, Flags, size_t* readSize) override;
-    Result beginRead(const void** buffer, Flags, size_t* available) override;
-    Result endRead(size_t readSize) override;
-
-private:
-    RefPtr<Context> m_context;
-};
-
-class CompositeDataConsumerHandle::Context final : public ThreadSafeRefCounted<Context> {
-public:
-    using Token = unsigned;
-    static PassRefPtr<Context> create(std::unique_ptr<WebDataConsumerHandle> handle) { return adoptRef(new Context(std::move(handle))); }
-    ~Context()
-    {
-        DCHECK(!m_readerThread);
-        DCHECK(!m_reader);
-        DCHECK(!m_client);
-    }
-    std::unique_ptr<ReaderImpl> obtainReader(Client* client)
-    {
-        MutexLocker locker(m_mutex);
-        DCHECK(!m_readerThread);
-        DCHECK(!m_reader);
-        DCHECK(!m_client);
-        ++m_token;
-        m_client = client;
-        m_readerThread = Platform::current()->currentThread();
-        m_reader = m_handle->obtainReader(m_client);
-        return wrapUnique(new ReaderImpl(this));
-    }
-    void detachReader()
-    {
-        MutexLocker locker(m_mutex);
-        DCHECK(m_readerThread);
-        DCHECK(m_readerThread->isCurrentThread());
-        DCHECK(m_reader);
-        DCHECK(!m_isInTwoPhaseRead);
-        DCHECK(!m_isUpdateWaitingForEndRead);
-        ++m_token;
-        m_reader = nullptr;
-        m_readerThread = nullptr;
-        m_client = nullptr;
-    }
-    void update(std::unique_ptr<WebDataConsumerHandle> handle)
-    {
-        MutexLocker locker(m_mutex);
-        m_handle = std::move(handle);
-        if (!m_readerThread) {
-            // There is no reader.
-            return;
-        }
-        ++m_token;
-        updateReaderNoLock(m_token);
-    }
-
-    Result read(void* data, size_t size, Flags flags, size_t* readSize)
-    {
-        DCHECK(m_readerThread && m_readerThread->isCurrentThread());
-        return m_reader->read(data, size, flags, readSize);
-    }
-    Result beginRead(const void** buffer, Flags flags, size_t* available)
-    {
-        DCHECK(m_readerThread && m_readerThread->isCurrentThread());
-        DCHECK(!m_isInTwoPhaseRead);
-        Result r = m_reader->beginRead(buffer, flags, available);
-        m_isInTwoPhaseRead = (r == Ok);
-        return r;
-    }
-    Result endRead(size_t readSize)
-    {
-        DCHECK(m_readerThread && m_readerThread->isCurrentThread());
-        DCHECK(m_isInTwoPhaseRead);
-        Result r = m_reader->endRead(readSize);
-        m_isInTwoPhaseRead = false;
-        if (m_isUpdateWaitingForEndRead) {
-            // We need this lock to access |m_handle|.
-            MutexLocker locker(m_mutex);
-            m_reader = nullptr;
-            m_reader = m_handle->obtainReader(m_client);
-            m_isUpdateWaitingForEndRead = false;
-        }
-        return r;
-    }
-
-private:
-    explicit Context(std::unique_ptr<WebDataConsumerHandle> handle)
-        : m_handle(std::move(handle))
-        , m_readerThread(nullptr)
-        , m_client(nullptr)
-        , m_token(0)
-        , m_isUpdateWaitingForEndRead(false)
-        , m_isInTwoPhaseRead(false)
-    {
-    }
-    void updateReader(Token token)
-    {
-        MutexLocker locker(m_mutex);
-        updateReaderNoLock(token);
-    }
-    void updateReaderNoLock(Token token)
-    {
-        if (token != m_token) {
-            // This request is not fresh. Ignore it.
-            return;
-        }
-        DCHECK(m_readerThread);
-        DCHECK(m_reader);
-        if (m_readerThread->isCurrentThread()) {
-            if (m_isInTwoPhaseRead) {
-                // We are waiting for the two-phase read completion.
-                m_isUpdateWaitingForEndRead = true;
-                return;
-            }
-            // Unregister the old one, then register the new one.
-            m_reader = nullptr;
-            m_reader = m_handle->obtainReader(m_client);
-            return;
-        }
-        ++m_token;
-        m_readerThread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&Context::updateReader, wrapPassRefPtr(this), m_token));
-    }
-
-    std::unique_ptr<Reader> m_reader;
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-    // Note: Holding a WebThread raw pointer is not generally safe, but we can
-    // do that in this case because:
-    //  1. Destructing a ReaderImpl when the bound thread ends is a user's
-    //     responsibility.
-    //  2. |m_readerThread| will never be used after the associated reader is
-    //     detached.
-    WebThread* m_readerThread;
-    Client* m_client;
-    Token m_token;
-    // These boolean values are bound to the reader thread.
-    bool m_isUpdateWaitingForEndRead;
-    bool m_isInTwoPhaseRead;
-    Mutex m_mutex;
-};
-
-CompositeDataConsumerHandle::ReaderImpl::ReaderImpl(PassRefPtr<Context> context) : m_context(context) { }
-
-CompositeDataConsumerHandle::ReaderImpl::~ReaderImpl()
-{
-    m_context->detachReader();
-}
-
-Result CompositeDataConsumerHandle::ReaderImpl::read(void* data, size_t size, Flags flags, size_t* readSize)
-{
-    return m_context->read(data, size, flags, readSize);
-}
-
-Result CompositeDataConsumerHandle::ReaderImpl::beginRead(const void** buffer, Flags flags, size_t* available)
-{
-    return m_context->beginRead(buffer, flags, available);
-}
-
-Result CompositeDataConsumerHandle::ReaderImpl::endRead(size_t readSize)
-{
-    return m_context->endRead(readSize);
-}
-
-CompositeDataConsumerHandle::Updater::Updater(PassRefPtr<Context> context)
-    : m_context(context)
-#if DCHECK_IS_ON()
-    , m_thread(Platform::current()->currentThread())
-#endif
-{
-}
-
-CompositeDataConsumerHandle::Updater::~Updater() {}
-
-void CompositeDataConsumerHandle::Updater::update(std::unique_ptr<WebDataConsumerHandle> handle)
-{
-    DCHECK(handle);
-#if DCHECK_IS_ON()
-    DCHECK(m_thread->isCurrentThread());
-#endif
-    m_context->update(std::move(handle));
-}
-
-CompositeDataConsumerHandle::CompositeDataConsumerHandle(std::unique_ptr<WebDataConsumerHandle> handle, Updater** updater)
-    : m_context(Context::create(std::move(handle)))
-{
-    *updater = new Updater(m_context);
-}
-
-CompositeDataConsumerHandle::~CompositeDataConsumerHandle() { }
-
-std::unique_ptr<WebDataConsumerHandle::Reader> CompositeDataConsumerHandle::obtainReader(Client* client)
-{
-    return m_context->obtainReader(client);
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandle.h b/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandle.h
deleted file mode 100644
index fb0d9bb..0000000
--- a/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandle.h
+++ /dev/null
@@ -1,73 +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.
-
-#ifndef CompositeDataConsumerHandle_h
-#define CompositeDataConsumerHandle_h
-
-#include "modules/ModulesExport.h"
-#include "platform/heap/Handle.h"
-#include "public/platform/WebDataConsumerHandle.h"
-#include "wtf/Allocator.h"
-#include "wtf/PtrUtil.h"
-#include "wtf/RefPtr.h"
-#include <memory>
-
-namespace blink {
-
-class WebThread;
-
-// This is a utility class to construct a composite data consumer handle. It
-// owns a web data consumer handle and delegates methods. A user can update
-// the handle by using |update| method.
-class MODULES_EXPORT CompositeDataConsumerHandle final : public WebDataConsumerHandle {
-    WTF_MAKE_NONCOPYABLE(CompositeDataConsumerHandle);
-    USING_FAST_MALLOC(CompositeDataConsumerHandle);
-    class Context;
-public:
-    // An Updater is bound to the creator thread.
-    class MODULES_EXPORT Updater final : public GarbageCollectedFinalized<Updater> {
-    public:
-        explicit Updater(PassRefPtr<Context>);
-        ~Updater();
-
-        // |handle| must not be null and must not be locked.
-        void update(std::unique_ptr<WebDataConsumerHandle> /* handle */);
-        DEFINE_INLINE_TRACE() { }
-
-    private:
-        RefPtr<Context> m_context;
-#if DCHECK_IS_ON()
-        WebThread* const m_thread;
-#endif
-    };
-
-    // Returns a handle and stores the associated updater to |*updater|. The
-    // associated updater will be bound to the calling thread.
-    // |handle| must not be null and must not be locked.
-    template<typename T>
-    static std::unique_ptr<WebDataConsumerHandle> create(std::unique_ptr<WebDataConsumerHandle> handle, T* updater)
-    {
-        DCHECK(handle);
-        Updater* u = nullptr;
-        std::unique_ptr<CompositeDataConsumerHandle> p = wrapUnique(new CompositeDataConsumerHandle(std::move(handle), &u));
-        *updater = u;
-        return std::move(p);
-    }
-    ~CompositeDataConsumerHandle() override;
-
-    std::unique_ptr<Reader> obtainReader(Client*) override;
-
-private:
-    class ReaderImpl;
-
-    const char* debugName() const override { return "CompositeDataConsumerHandle"; }
-
-    CompositeDataConsumerHandle(std::unique_ptr<WebDataConsumerHandle>, Updater**);
-
-    RefPtr<Context> m_context;
-};
-
-} // namespace blink
-
-#endif // CompositeDataConsumerHandle_h
diff --git a/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandleTest.cpp b/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandleTest.cpp
deleted file mode 100644
index d1c172e6..0000000
--- a/third_party/WebKit/Source/modules/fetch/CompositeDataConsumerHandleTest.cpp
+++ /dev/null
@@ -1,493 +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.
-
-#include "modules/fetch/CompositeDataConsumerHandle.h"
-
-#include "modules/fetch/DataConsumerHandleTestUtil.h"
-#include "platform/CrossThreadFunctional.h"
-#include "platform/WaitableEvent.h"
-#include "platform/heap/Handle.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebThread.h"
-#include "public/platform/WebTraceLocation.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "wtf/Locker.h"
-#include "wtf/PtrUtil.h"
-#include <memory>
-
-namespace blink {
-
-namespace {
-
-using ::testing::ByMove;
-using ::testing::InSequence;
-using ::testing::Return;
-using ::testing::StrictMock;
-using Checkpoint = StrictMock<::testing::MockFunction<void(int)>>;
-
-const WebDataConsumerHandle::Result kShouldWait = WebDataConsumerHandle::ShouldWait;
-const WebDataConsumerHandle::Result kOk = WebDataConsumerHandle::Ok;
-const WebDataConsumerHandle::Flags kNone = WebDataConsumerHandle::FlagNone;
-
-class MockReader : public WebDataConsumerHandle::Reader {
-public:
-    static std::unique_ptr<StrictMock<MockReader>> create() { return wrapUnique(new StrictMock<MockReader>); }
-
-    using Result = WebDataConsumerHandle::Result;
-    using Flags = WebDataConsumerHandle::Flags;
-    MOCK_METHOD4(read, Result(void*, size_t, Flags, size_t*));
-    MOCK_METHOD3(beginRead, Result(const void**, Flags, size_t*));
-    MOCK_METHOD1(endRead, Result(size_t));
-};
-
-class MockHandle : public WebDataConsumerHandle {
-public:
-    static std::unique_ptr<StrictMock<MockHandle>> create() { return wrapUnique(new StrictMock<MockHandle>); }
-
-    MOCK_METHOD1(obtainReader, std::unique_ptr<Reader>(Client*));
-
-private:
-    const char* debugName() const override { return "MockHandle in CompositeDataConsumerHandleTest"; }
-};
-
-class ThreadingRegistrationTest : public DataConsumerHandleTestUtil::ThreadingTestBase {
-public:
-    using Self = ThreadingRegistrationTest;
-    static PassRefPtr<Self> create() { return adoptRef(new Self); }
-
-    void run()
-    {
-        ThreadHolder holder(this);
-        m_waitableEvent = wrapUnique(new WaitableEvent());
-
-        postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::createHandle, wrapPassRefPtr(this)));
-        postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::obtainReader, wrapPassRefPtr(this)));
-    }
-
-private:
-    ThreadingRegistrationTest() = default;
-
-    void createHandle()
-    {
-        m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::create("handle1", m_context), &m_updater);
-        m_waitableEvent->signal();
-    }
-    void obtainReader()
-    {
-        m_reader = m_handle->obtainReader(&m_client);
-        postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update, wrapPassRefPtr(this)));
-    }
-    void update()
-    {
-        m_updater->update(DataConsumerHandle::create("handle2", m_context));
-        m_updater.clear();
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetReader, wrapPassRefPtr(this)));
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDone, wrapPassRefPtr(this)));
-    }
-
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-    CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater;
-};
-
-class ThreadingRegistrationDeleteHandleTest : public DataConsumerHandleTestUtil::ThreadingTestBase {
-public:
-    using Self = ThreadingRegistrationDeleteHandleTest;
-    static PassRefPtr<Self> create() { return adoptRef(new Self); }
-
-    void run()
-    {
-        ThreadHolder holder(this);
-        m_waitableEvent = wrapUnique(new WaitableEvent());
-
-        postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::createHandle, wrapPassRefPtr(this)));
-        postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::obtainReader, wrapPassRefPtr(this)));
-    }
-
-private:
-    ThreadingRegistrationDeleteHandleTest() = default;
-
-    void createHandle()
-    {
-        m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::create("handle1", m_context), &m_updater);
-        m_waitableEvent->signal();
-    }
-
-    void obtainReader()
-    {
-        m_reader = m_handle->obtainReader(&m_client);
-        postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update, wrapPassRefPtr(this)));
-    }
-    void update()
-    {
-        m_updater->update(DataConsumerHandle::create("handle2", m_context));
-        m_updater.clear();
-        m_handle = nullptr;
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetReader, wrapPassRefPtr(this)));
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDone, wrapPassRefPtr(this)));
-    }
-
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-    CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater;
-};
-
-class ThreadingRegistrationDeleteReaderTest : public DataConsumerHandleTestUtil::ThreadingTestBase {
-public:
-    using Self = ThreadingRegistrationDeleteReaderTest;
-    static PassRefPtr<Self> create() { return adoptRef(new Self); }
-
-    void run()
-    {
-        ThreadHolder holder(this);
-        m_waitableEvent = wrapUnique(new WaitableEvent());
-
-        postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::createHandle, wrapPassRefPtr(this)));
-        postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::obtainReader, wrapPassRefPtr(this)));
-    }
-
-private:
-    ThreadingRegistrationDeleteReaderTest() = default;
-
-    void createHandle()
-    {
-        m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::create("handle1", m_context), &m_updater);
-        m_waitableEvent->signal();
-    }
-
-    void obtainReader()
-    {
-        m_reader = m_handle->obtainReader(&m_client);
-        postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update, wrapPassRefPtr(this)));
-    }
-    void update()
-    {
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetReader, wrapPassRefPtr(this)));
-        m_updater->update(DataConsumerHandle::create("handle2", m_context));
-        m_updater.clear();
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetReader, wrapPassRefPtr(this)));
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDone, wrapPassRefPtr(this)));
-    }
-
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-    CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater;
-};
-
-class ThreadingUpdatingReaderWhileUpdatingTest : public DataConsumerHandleTestUtil::ThreadingTestBase {
-public:
-    using Self = ThreadingUpdatingReaderWhileUpdatingTest;
-    static PassRefPtr<Self> create() { return adoptRef(new Self); }
-
-    void run()
-    {
-        ThreadHolder holder(this);
-        m_waitableEvent = wrapUnique(new WaitableEvent());
-        m_updateEvent = wrapUnique(new WaitableEvent());
-
-        postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::createHandle, wrapPassRefPtr(this)));
-        postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::obtainReader, wrapPassRefPtr(this)));
-    }
-
-private:
-    ThreadingUpdatingReaderWhileUpdatingTest() = default;
-
-    void createHandle()
-    {
-        m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::create("handle1", m_context), &m_updater);
-        m_waitableEvent->signal();
-    }
-
-    void obtainReader()
-    {
-        m_reader = m_handle->obtainReader(&m_client);
-        postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update, wrapPassRefPtr(this)));
-        m_updateEvent->wait();
-    }
-
-    void update()
-    {
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::reobtainReader, wrapPassRefPtr(this)));
-        m_updater->update(DataConsumerHandle::create("handle2", m_context));
-        m_updater.clear();
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetReader, wrapPassRefPtr(this)));
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDone, wrapPassRefPtr(this)));
-        m_updateEvent->signal();
-    }
-
-    void reobtainReader()
-    {
-        m_reader = nullptr;
-        m_reader = m_handle->obtainReader(&m_client);
-    }
-
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-    CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater;
-    std::unique_ptr<WaitableEvent> m_updateEvent;
-};
-
-class ThreadingRegistrationUpdateTwiceAtOneTimeTest : public DataConsumerHandleTestUtil::ThreadingTestBase {
-public:
-    using Self = ThreadingRegistrationUpdateTwiceAtOneTimeTest;
-    static PassRefPtr<Self> create() { return adoptRef(new Self); }
-
-    void run()
-    {
-        ThreadHolder holder(this);
-        m_waitableEvent = wrapUnique(new WaitableEvent());
-        m_updateEvent = wrapUnique(new WaitableEvent());
-
-        postTaskToUpdatingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::createHandle, wrapPassRefPtr(this)));
-        postTaskToReadingThreadAndWait(BLINK_FROM_HERE, crossThreadBind(&Self::obtainReader, wrapPassRefPtr(this)));
-    }
-
-private:
-    ThreadingRegistrationUpdateTwiceAtOneTimeTest() = default;
-
-    void createHandle()
-    {
-        m_handle = CompositeDataConsumerHandle::create(DataConsumerHandle::create("handle1", m_context), &m_updater);
-        m_waitableEvent->signal();
-    }
-
-    void obtainReader()
-    {
-        m_reader = m_handle->obtainReader(&m_client);
-        postTaskToUpdatingThread(BLINK_FROM_HERE, crossThreadBind(&Self::update, wrapPassRefPtr(this)));
-        // Stalls this thread while updating handles.
-        m_updateEvent->wait();
-    }
-    void update()
-    {
-        m_updater->update(DataConsumerHandle::create("handle2", m_context));
-        m_updater->update(DataConsumerHandle::create("handle3", m_context));
-        m_updateEvent->signal();
-        m_updater.clear();
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::resetReader, wrapPassRefPtr(this)));
-        postTaskToReadingThread(BLINK_FROM_HERE, crossThreadBind(&Self::signalDone, wrapPassRefPtr(this)));
-    }
-
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-    CrossThreadPersistent<CompositeDataConsumerHandle::Updater> m_updater;
-    std::unique_ptr<WaitableEvent> m_updateEvent;
-};
-
-TEST(CompositeDataConsumerHandleTest, Read)
-{
-    char buffer[20];
-    size_t size = 0;
-    DataConsumerHandleTestUtil::NoopClient client;
-    Checkpoint checkpoint;
-
-    std::unique_ptr<MockHandle> handle1 = MockHandle::create();
-    std::unique_ptr<MockHandle> handle2 = MockHandle::create();
-
-    // They will be adopted by |obtainReader|.
-    MockReader* reader1 = MockReader::create().release();
-    MockReader* reader2 = MockReader::create().release();
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(0));
-    EXPECT_CALL(*handle1, obtainReader(&client)).WillOnce(Return(ByMove(WTF::wrapUnique(reader1))));
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*reader1, read(buffer, sizeof(buffer), kNone, &size)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*handle2, obtainReader(&client)).WillOnce(Return(ByMove(WTF::wrapUnique(reader2))));
-    EXPECT_CALL(checkpoint, Call(3));
-    EXPECT_CALL(*reader2, read(buffer, sizeof(buffer), kNone, &size)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(4));
-
-    CompositeDataConsumerHandle::Updater* updater = nullptr;
-    std::unique_ptr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle::create(std::move(handle1), &updater);
-    checkpoint.Call(0);
-    std::unique_ptr<WebDataConsumerHandle::Reader> reader = handle->obtainReader(&client);
-    checkpoint.Call(1);
-    EXPECT_EQ(kOk, reader->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(2);
-    updater->update(std::move(handle2));
-    checkpoint.Call(3);
-    EXPECT_EQ(kOk, reader->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(4);
-}
-
-TEST(CompositeDataConsumerHandleTest, TwoPhaseRead)
-{
-    const void* p = nullptr;
-    size_t size = 0;
-    Checkpoint checkpoint;
-
-    std::unique_ptr<MockHandle> handle1 = MockHandle::create();
-    std::unique_ptr<MockHandle> handle2 = MockHandle::create();
-
-    // They are adopted by |obtainReader|.
-    MockReader* reader1 = MockReader::create().release();
-    MockReader* reader2 = MockReader::create().release();
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(0));
-    EXPECT_CALL(*handle1, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wrapUnique(reader1))));
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*reader1, beginRead(&p, kNone, &size)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*reader1, endRead(0)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(3));
-    EXPECT_CALL(*handle2, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wrapUnique(reader2))));
-    EXPECT_CALL(checkpoint, Call(4));
-    EXPECT_CALL(*reader2, beginRead(&p, kNone, &size)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(5));
-    EXPECT_CALL(*reader2, endRead(0)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(6));
-
-    CompositeDataConsumerHandle::Updater* updater = nullptr;
-    std::unique_ptr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle::create(std::move(handle1), &updater);
-    checkpoint.Call(0);
-    std::unique_ptr<WebDataConsumerHandle::Reader> reader = handle->obtainReader(nullptr);
-    checkpoint.Call(1);
-    EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size));
-    checkpoint.Call(2);
-    EXPECT_EQ(kOk, reader->endRead(0));
-    checkpoint.Call(3);
-    updater->update(std::move(handle2));
-    checkpoint.Call(4);
-    EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size));
-    checkpoint.Call(5);
-    EXPECT_EQ(kOk, reader->endRead(0));
-    checkpoint.Call(6);
-}
-
-TEST(CompositeDataConsumerHandleTest, HangingTwoPhaseRead)
-{
-    const void* p = nullptr;
-    size_t size = 0;
-    Checkpoint checkpoint;
-
-    std::unique_ptr<MockHandle> handle1 = MockHandle::create();
-    std::unique_ptr<MockHandle> handle2 = MockHandle::create();
-    std::unique_ptr<MockHandle> handle3 = MockHandle::create();
-
-    // They are adopted by |obtainReader|.
-    MockReader* reader1 = MockReader::create().release();
-    MockReader* reader2 = MockReader::create().release();
-    MockReader* reader3 = MockReader::create().release();
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(0));
-    EXPECT_CALL(*handle1, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wrapUnique(reader1))));
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*reader1, beginRead(&p, kNone, &size)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(checkpoint, Call(3));
-    EXPECT_CALL(*reader1, endRead(0)).WillOnce(Return(kOk));
-    EXPECT_CALL(*handle2, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wrapUnique(reader2))));
-    EXPECT_CALL(checkpoint, Call(4));
-    EXPECT_CALL(*reader2, beginRead(&p, kNone, &size)).WillOnce(Return(kShouldWait));
-    EXPECT_CALL(checkpoint, Call(5));
-    EXPECT_CALL(*handle3, obtainReader(nullptr)).WillOnce(Return(ByMove(WTF::wrapUnique(reader3))));
-    EXPECT_CALL(checkpoint, Call(6));
-    EXPECT_CALL(*reader3, beginRead(&p, kNone, &size)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(7));
-    EXPECT_CALL(*reader3, endRead(0)).WillOnce(Return(kOk));
-    EXPECT_CALL(checkpoint, Call(8));
-
-    CompositeDataConsumerHandle::Updater* updater = nullptr;
-    std::unique_ptr<WebDataConsumerHandle> handle = CompositeDataConsumerHandle::create(std::move(handle1), &updater);
-    checkpoint.Call(0);
-    std::unique_ptr<WebDataConsumerHandle::Reader> reader = handle->obtainReader(nullptr);
-    checkpoint.Call(1);
-    EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size));
-    checkpoint.Call(2);
-    updater->update(std::move(handle2));
-    checkpoint.Call(3);
-    EXPECT_EQ(kOk, reader->endRead(0));
-    checkpoint.Call(4);
-    EXPECT_EQ(kShouldWait, reader->beginRead(&p, kNone, &size));
-    checkpoint.Call(5);
-    updater->update(std::move(handle3));
-    checkpoint.Call(6);
-    EXPECT_EQ(kOk, reader->beginRead(&p, kNone, &size));
-    checkpoint.Call(7);
-    EXPECT_EQ(kOk, reader->endRead(0));
-    checkpoint.Call(8);
-}
-
-TEST(CompositeDataConsumerHandleTest, RegisterClientOnDifferentThreads)
-{
-    RefPtr<ThreadingRegistrationTest> test = ThreadingRegistrationTest::create();
-    test->run();
-
-    EXPECT_EQ(
-        "A reader is attached to handle1 on the reading thread.\n"
-        "A reader is detached from handle1 on the reading thread.\n"
-        "A reader is attached to handle2 on the reading thread.\n"
-        "A reader is detached from handle2 on the reading thread.\n",
-        test->result());
-}
-
-TEST(CompositeDataConsumerHandleTest, DeleteHandleWhileUpdating)
-{
-    RefPtr<ThreadingRegistrationDeleteHandleTest> test = ThreadingRegistrationDeleteHandleTest::create();
-    test->run();
-
-    EXPECT_EQ(
-        "A reader is attached to handle1 on the reading thread.\n"
-        "A reader is detached from handle1 on the reading thread.\n"
-        "A reader is attached to handle2 on the reading thread.\n"
-        "A reader is detached from handle2 on the reading thread.\n",
-        test->result());
-}
-
-TEST(CompositeDataConsumerHandleTest, DeleteReaderWhileUpdating)
-{
-    RefPtr<ThreadingRegistrationDeleteReaderTest> test = ThreadingRegistrationDeleteReaderTest::create();
-    test->run();
-
-    EXPECT_EQ(
-        "A reader is attached to handle1 on the reading thread.\n"
-        "A reader is detached from handle1 on the reading thread.\n",
-        test->result());
-}
-
-TEST(CompositeDataConsumerHandleTest, UpdateReaderWhileUpdating)
-{
-    RefPtr<ThreadingUpdatingReaderWhileUpdatingTest> test = ThreadingUpdatingReaderWhileUpdatingTest::create();
-    test->run();
-
-    EXPECT_EQ(
-        "A reader is attached to handle1 on the reading thread.\n"
-        "A reader is detached from handle1 on the reading thread.\n"
-        "A reader is attached to handle2 on the reading thread.\n"
-        "A reader is detached from handle2 on the reading thread.\n",
-        test->result());
-}
-
-TEST(CompositeDataConsumerHandleTest, UpdateTwiceAtOnce)
-{
-    RefPtr<ThreadingRegistrationUpdateTwiceAtOneTimeTest> test = ThreadingRegistrationUpdateTwiceAtOneTimeTest::create();
-    test->run();
-
-    EXPECT_EQ(
-        "A reader is attached to handle1 on the reading thread.\n"
-        "A reader is detached from handle1 on the reading thread.\n"
-        "A reader is attached to handle3 on the reading thread.\n"
-        "A reader is detached from handle3 on the reading thread.\n",
-        test->result());
-}
-
-TEST(CompositeDataConsumerHandleTest, DoneHandleNotification)
-{
-    RefPtr<DataConsumerHandleTestUtil::ThreadingHandleNotificationTest> test = DataConsumerHandleTestUtil::ThreadingHandleNotificationTest::create();
-    CompositeDataConsumerHandle::Updater* updater = nullptr;
-    // Test this function returns.
-    test->run(CompositeDataConsumerHandle::create(createDoneDataConsumerHandle(), &updater));
-}
-
-TEST(CompositeDataConsumerHandleTest, DoneHandleNoNotification)
-{
-    RefPtr<DataConsumerHandleTestUtil::ThreadingHandleNoNotificationTest> test = DataConsumerHandleTestUtil::ThreadingHandleNoNotificationTest::create();
-    CompositeDataConsumerHandle::Updater* updater = nullptr;
-    // Test this function doesn't crash.
-    test->run(CompositeDataConsumerHandle::create(createDoneDataConsumerHandle(), &updater));
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/modules/fetch/CrossThreadHolder.h b/third_party/WebKit/Source/modules/fetch/CrossThreadHolder.h
deleted file mode 100644
index 58dbb45..0000000
--- a/third_party/WebKit/Source/modules/fetch/CrossThreadHolder.h
+++ /dev/null
@@ -1,177 +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.
-
-#ifndef CrossThreadHolder_h
-#define CrossThreadHolder_h
-
-#include "core/dom/ActiveDOMObject.h"
-#include "core/dom/ExecutionContext.h"
-#include "core/dom/ExecutionContextTask.h"
-#include "public/platform/WebTraceLocation.h"
-#include "wtf/Locker.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/PtrUtil.h"
-#include "wtf/RefPtr.h"
-#include "wtf/ThreadingPrimitives.h"
-#include <memory>
-
-namespace blink {
-
-// CrossThreadHolder<T> provides cross-thread access to |obj| of class T
-// bound to the thread of |executionContext| where |obj| is created.
-// - CrossThreadHolder<T> can be passed across threads.
-// - |obj|'s methods are called on the thread of |executionContext|
-//   via CrossThreadHolder<T>::postTask().
-// - |obj| is destructed on the thread of |executionContext|
-//   when |executionContext| is stopped or
-//   CrossThreadHolder is destructed (earlier of them).
-//   Note: |obj|'s destruction can be slightly after CrossThreadHolder.
-template<typename T>
-class CrossThreadHolder final {
-public:
-    // Must be called on the thread where |obj| is created
-    // (== the thread of |executionContext|).
-    // The current thread must be attached to Oilpan.
-    static std::unique_ptr<CrossThreadHolder<T>> create(ExecutionContext* executionContext, std::unique_ptr<T> obj)
-    {
-        ASSERT(executionContext->isContextThread());
-        return wrapUnique(new CrossThreadHolder(executionContext, std::move(obj)));
-    }
-
-    // Can be called from any thread.
-    // Executes |task| with |obj| and |executionContext| on the thread of
-    // |executionContext|.
-    // NOTE: |task| might be silently ignored (i.e. not executed) and
-    // destructed (possibly on the calling thread or on the thread of
-    // |executionContext|) when |executionContext| is stopped or
-    // CrossThreadHolder is destructed.
-    void postTask(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF::CrossThreadAffinity>> task)
-    {
-        MutexLocker locker(m_mutex->mutex());
-        if (!m_bridge) {
-            // The bridge has already disappeared.
-            return;
-        }
-        m_bridge->getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossThreadTask(&Bridge::runTask, wrapCrossThreadPersistent(m_bridge.get()), passed(std::move(task))));
-    }
-
-    ~CrossThreadHolder()
-    {
-        MutexLocker locker(m_mutex->mutex());
-        clearInternal();
-    }
-
-private:
-    // Object graph:
-    //                     +------+                          +-----------------+
-    //     T <-unique_ptr- |Bridge| ---------*-------------> |CrossThreadHolder|
-    //                     |      | <-CrossThreadPersistent- |                 |
-    //                     +------+                          +-----------------+
-    //                        |                                    |
-    //                        +--RefPtr--> MutexWrapper <--RefPtr--+
-    // The CrossThreadPersistent<T>/T* between CrossThreadHolder and Bridge
-    // are protected by MutexWrapper
-    // and cleared when CrossThreadHolder::clearInternal() is called, i.e.:
-    // [1] when |executionContext| is stopped, or
-    // [2] when CrossThreadHolder is destructed.
-    // Then Bridge is shortly garbage collected and T is destructed.
-
-    class MutexWrapper : public ThreadSafeRefCounted<MutexWrapper> {
-    public:
-        static PassRefPtr<MutexWrapper> create() { return adoptRef(new MutexWrapper()); }
-        Mutex& mutex() { return m_mutex; }
-    private:
-        MutexWrapper() = default;
-        Mutex m_mutex;
-    };
-
-    // All methods except for clearInternal()
-    // must be called on |executionContext|'s thread.
-    class Bridge
-        : public GarbageCollectedFinalized<Bridge>
-        , public ActiveDOMObject {
-        USING_GARBAGE_COLLECTED_MIXIN(Bridge);
-    public:
-        Bridge(ExecutionContext* executionContext, std::unique_ptr<T> obj, PassRefPtr<MutexWrapper> mutex, CrossThreadHolder* holder)
-            : ActiveDOMObject(executionContext)
-            , m_obj(std::move(obj))
-            , m_mutex(mutex)
-            , m_holder(holder)
-        {
-            suspendIfNeeded();
-        }
-
-        DEFINE_INLINE_TRACE()
-        {
-            ActiveDOMObject::trace(visitor);
-        }
-
-        T* getObject() const { return m_obj.get(); }
-
-        // Must be protected by |m_mutex|.
-        // Is called from CrossThreadHolder::clearInternal() and
-        // can be called on any thread.
-        void clearInternal()
-        {
-            // We don't clear |m_obj| here to destruct |m_obj| on the thread
-            // of |executionContext|.
-            m_holder = nullptr;
-        }
-
-        void runTask(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF::CrossThreadAffinity>> task)
-        {
-            ASSERT(getExecutionContext()->isContextThread());
-            if (m_obj)
-                (*task)(m_obj.get(), getExecutionContext());
-        }
-
-    private:
-        // ActiveDOMObject
-        void stop() override
-        {
-            ASSERT(getExecutionContext()->isContextThread());
-            {
-                MutexLocker locker(m_mutex->mutex());
-                if (m_holder)
-                    m_holder->clearInternal();
-                ASSERT(!m_holder);
-            }
-
-            // We have to destruct |*m_obj| here because destructing |*m_obj|
-            // in ~Bridge() might be too late when |executionContext| is
-            // stopped.
-            m_obj.reset();
-        }
-
-
-        std::unique_ptr<T> m_obj;
-        // All accesses to |m_holder| must be protected by |m_mutex|.
-        RefPtr<MutexWrapper> m_mutex;
-        CrossThreadHolder* m_holder;
-    };
-
-    // Must be protected by |m_mutex|.
-    void clearInternal()
-    {
-        if (m_bridge)
-            m_bridge->clearInternal();
-        m_bridge.clear();
-    }
-
-    CrossThreadHolder(ExecutionContext* executionContext, std::unique_ptr<T> obj)
-        : m_mutex(MutexWrapper::create())
-        , m_bridge(new Bridge(executionContext, std::move(obj), m_mutex, this))
-    {
-    }
-
-    RefPtr<MutexWrapper> m_mutex;
-    // |m_bridge| is protected by |m_mutex|.
-    // |m_bridge| is cleared before the thread that allocated |*m_bridge|
-    // is stopped.
-    CrossThreadPersistent<Bridge> m_bridge;
-};
-
-} // namespace blink
-
-#endif // CrossThreadHolder_h
diff --git a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.cpp b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.cpp
deleted file mode 100644
index 59390959..0000000
--- a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.cpp
+++ /dev/null
@@ -1,319 +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.
-
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
-
-#include "core/dom/ExecutionContext.h"
-#include "core/fetch/FetchInitiatorTypeNames.h"
-#include "core/loader/ThreadableLoaderClient.h"
-#include "modules/fetch/CompositeDataConsumerHandle.h"
-#include "modules/fetch/CrossThreadHolder.h"
-#include "modules/fetch/DataConsumerHandleUtil.h"
-#include "platform/blob/BlobRegistry.h"
-#include "platform/blob/BlobURL.h"
-#include "platform/network/ResourceRequest.h"
-#include "wtf/PtrUtil.h"
-#include <memory>
-
-namespace blink {
-
-using Result = FetchBlobDataConsumerHandle::Result;
-
-namespace {
-
-// Object graph:
-//                                           +-------------+
-//                                           |ReaderContext|
-//   +-------------+  +-----------+   +---+  |             |
-//   |LoaderContext|<-|CTH::Bridge|<->|CTH|<-|             |
-//   +-------------+  +-----------+   +---+  +-------------+
-//               |
-//               +--> ThreadableLoader
-//
-// When the loader thread is stopped, CrossThreadHolder::Bridge and
-// LoaderContext (and thus ThreadableLoader) is destructed:
-//                                           +-------------+
-//                                           |ReaderContext|
-//                                    +---+  |             |
-//                                    |CTH|<-|             |
-//                                    +---+  +-------------+
-// and the rest will be destructed when ReaderContext is destructed.
-//
-// When ReaderContext is destructed, CrossThreadHolder is destructed:
-//
-//  +-------------+  +-----------+
-//  |LoaderContext|<-|CTH::Bridge|
-//  +-------------+  +-----------+
-//               |
-//               +--> ThreadableLoader
-// and the rest will be shortly destructed when CrossThreadHolder::Bridge
-// is garbage collected.
-
-// LoaderContext is created and destructed on the same thread
-// (call this thread loader thread).
-// All methods must be called on the loader thread.
-class LoaderContext {
-public:
-    virtual ~LoaderContext() { }
-    virtual void start(ExecutionContext*) = 0;
-};
-
-// All methods must be called on the loader thread.
-class BlobLoaderContext final
-    : public LoaderContext
-    , public ThreadableLoaderClient {
-public:
-    BlobLoaderContext(CompositeDataConsumerHandle::Updater* updater, PassRefPtr<BlobDataHandle> blobDataHandle, FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
-        : m_updater(updater)
-        , m_blobDataHandle(blobDataHandle)
-        , m_loaderFactory(loaderFactory)
-        , m_receivedResponse(false) { }
-
-    ~BlobLoaderContext() override
-    {
-        if (m_loader && !m_receivedResponse)
-            m_updater->update(createUnexpectedErrorDataConsumerHandle());
-        if (m_loader) {
-            m_loader->cancel();
-            m_loader = nullptr;
-        }
-        if (!m_registeredBlobURL.isEmpty())
-            BlobRegistry::revokePublicBlobURL(m_registeredBlobURL);
-    }
-
-    void start(ExecutionContext* executionContext) override
-    {
-        ASSERT(executionContext->isContextThread());
-        ASSERT(!m_loader);
-
-        m_registeredBlobURL = BlobURL::createPublicURL(executionContext->getSecurityOrigin());
-        if (m_registeredBlobURL.isEmpty()) {
-            m_updater->update(createUnexpectedErrorDataConsumerHandle());
-            return;
-        }
-        BlobRegistry::registerPublicBlobURL(executionContext->getSecurityOrigin(), m_registeredBlobURL, m_blobDataHandle);
-
-        m_loader = createLoader(executionContext, this);
-        ASSERT(m_loader);
-
-        ResourceRequest request(m_registeredBlobURL);
-        request.setRequestContext(WebURLRequest::RequestContextInternal);
-        request.setUseStreamOnResponse(true);
-        // We intentionally skip 'setExternalRequestStateFromRequestorAddressSpace', as 'data:' can never be external.
-        m_loader->start(request);
-    }
-
-private:
-    ThreadableLoader* createLoader(ExecutionContext* executionContext, ThreadableLoaderClient* client) const
-    {
-        ThreadableLoaderOptions options;
-        options.preflightPolicy = ConsiderPreflight;
-        options.crossOriginRequestPolicy = DenyCrossOriginRequests;
-        options.contentSecurityPolicyEnforcement = DoNotEnforceContentSecurityPolicy;
-        options.initiator = FetchInitiatorTypeNames::internal;
-
-        ResourceLoaderOptions resourceLoaderOptions;
-        resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
-
-        return m_loaderFactory->create(*executionContext, client, options, resourceLoaderOptions);
-    }
-
-    // ThreadableLoaderClient
-    void didReceiveResponse(unsigned long, const ResourceResponse&, std::unique_ptr<WebDataConsumerHandle> handle) override
-    {
-        ASSERT(!m_receivedResponse);
-        m_receivedResponse = true;
-        if (!handle) {
-            // Here we assume WebURLLoader must return the response body as
-            // |WebDataConsumerHandle| since we call
-            // request.setUseStreamOnResponse().
-            m_updater->update(createUnexpectedErrorDataConsumerHandle());
-            return;
-        }
-        m_updater->update(std::move(handle));
-    }
-
-    void didFinishLoading(unsigned long, double) override
-    {
-        m_loader = nullptr;
-    }
-
-    void didFail(const ResourceError&) override
-    {
-        if (!m_receivedResponse)
-            m_updater->update(createUnexpectedErrorDataConsumerHandle());
-        m_loader = nullptr;
-    }
-
-    void didFailRedirectCheck() override
-    {
-        // We don't expect redirects for Blob loading.
-        ASSERT_NOT_REACHED();
-    }
-
-    Persistent<CompositeDataConsumerHandle::Updater> m_updater;
-
-    RefPtr<BlobDataHandle> m_blobDataHandle;
-    Persistent<FetchBlobDataConsumerHandle::LoaderFactory> m_loaderFactory;
-    Persistent<ThreadableLoader> m_loader;
-    KURL m_registeredBlobURL;
-
-    bool m_receivedResponse;
-};
-
-class DefaultLoaderFactory final : public FetchBlobDataConsumerHandle::LoaderFactory {
-public:
-    ThreadableLoader* create(
-        ExecutionContext& executionContext,
-        ThreadableLoaderClient* client,
-        const ThreadableLoaderOptions& options,
-        const ResourceLoaderOptions& resourceLoaderOptions) override
-    {
-        return ThreadableLoader::create(executionContext, client, options, resourceLoaderOptions);
-    }
-};
-
-} // namespace
-
-// ReaderContext is referenced from FetchBlobDataConsumerHandle and
-// ReaderContext::ReaderImpl.
-// All functions/members must be called/accessed only on the reader thread,
-// except for constructor, destructor, and obtainReader().
-class FetchBlobDataConsumerHandle::ReaderContext final : public ThreadSafeRefCounted<ReaderContext> {
-public:
-    class ReaderImpl : public FetchDataConsumerHandle::Reader {
-    public:
-        ReaderImpl(Client* client, PassRefPtr<ReaderContext> readerContext, std::unique_ptr<WebDataConsumerHandle::Reader> reader)
-            : m_readerContext(readerContext)
-            , m_reader(std::move(reader))
-            , m_notifier(client) { }
-        ~ReaderImpl() override { }
-
-        Result read(void* data, size_t size, Flags flags, size_t* readSize) override
-        {
-            if (m_readerContext->drained())
-                return Done;
-            Result r = m_reader->read(data, size, flags, readSize);
-            if (!(size == 0 && (r == Ok || r == ShouldWait))) {
-                // We read non-empty data, so we cannot use the blob data
-                // handle which represents the whole data.
-                m_readerContext->clearBlobDataHandleForDrain();
-                m_readerContext->ensureStartLoader();
-            }
-            return r;
-        }
-
-        Result beginRead(const void** buffer, Flags flags, size_t* available) override
-        {
-            if (m_readerContext->drained())
-                return Done;
-            m_readerContext->ensureStartLoader();
-            m_readerContext->clearBlobDataHandleForDrain();
-            return m_reader->beginRead(buffer, flags, available);
-        }
-
-        Result endRead(size_t readSize) override
-        {
-            return m_reader->endRead(readSize);
-        }
-
-        PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy blobSizePolicy) override
-        {
-            if (!m_readerContext->m_blobDataHandleForDrain)
-                return nullptr;
-            if (blobSizePolicy == DisallowBlobWithInvalidSize && m_readerContext->m_blobDataHandleForDrain->size() == UINT64_MAX)
-                return nullptr;
-            RefPtr<BlobDataHandle> blobDataHandle = m_readerContext->m_blobDataHandleForDrain;
-            m_readerContext->setDrained();
-            m_readerContext->clearBlobDataHandleForDrain();
-            return blobDataHandle.release();
-        }
-
-        PassRefPtr<EncodedFormData> drainAsFormData() override
-        {
-            RefPtr<BlobDataHandle> handle = drainAsBlobDataHandle(AllowBlobWithInvalidSize);
-            if (!handle)
-                return nullptr;
-            RefPtr<EncodedFormData> formData = EncodedFormData::create();
-            formData->appendBlob(handle->uuid(), handle);
-            return formData.release();
-        }
-
-    private:
-        RefPtr<ReaderContext> m_readerContext;
-        std::unique_ptr<WebDataConsumerHandle::Reader> m_reader;
-        NotifyOnReaderCreationHelper m_notifier;
-    };
-
-    ReaderContext(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle, FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
-        : m_blobDataHandleForDrain(blobDataHandle)
-        , m_loaderStarted(false)
-        , m_drained(false)
-    {
-        CompositeDataConsumerHandle::Updater* updater = nullptr;
-        m_handle = CompositeDataConsumerHandle::create(createWaitingDataConsumerHandle(), &updater);
-        m_loaderContextHolder = CrossThreadHolder<LoaderContext>::create(executionContext, wrapUnique(new BlobLoaderContext(updater, m_blobDataHandleForDrain, loaderFactory)));
-    }
-
-    std::unique_ptr<FetchDataConsumerHandle::Reader> obtainReader(WebDataConsumerHandle::Client* client)
-    {
-        return wrapUnique(new ReaderImpl(client, this, m_handle->obtainReader(client)));
-    }
-
-private:
-    void ensureStartLoader()
-    {
-        if (m_loaderStarted)
-            return;
-        m_loaderStarted = true;
-        m_loaderContextHolder->postTask(crossThreadBind(&LoaderContext::start));
-    }
-
-    void clearBlobDataHandleForDrain()
-    {
-        m_blobDataHandleForDrain.clear();
-    }
-
-    bool drained() const { return m_drained; }
-    void setDrained() { m_drained = true; }
-
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-    RefPtr<BlobDataHandle> m_blobDataHandleForDrain;
-    std::unique_ptr<CrossThreadHolder<LoaderContext>> m_loaderContextHolder;
-
-    bool m_loaderStarted;
-    bool m_drained;
-};
-
-FetchBlobDataConsumerHandle::FetchBlobDataConsumerHandle(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle, LoaderFactory* loaderFactory)
-    : m_readerContext(adoptRef(new ReaderContext(executionContext, std::move(blobDataHandle), loaderFactory)))
-{
-}
-
-FetchBlobDataConsumerHandle::~FetchBlobDataConsumerHandle()
-{
-}
-
-std::unique_ptr<FetchDataConsumerHandle> FetchBlobDataConsumerHandle::create(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle, LoaderFactory* loaderFactory)
-{
-    if (!blobDataHandle)
-        return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle());
-
-    return wrapUnique(new FetchBlobDataConsumerHandle(executionContext, std::move(blobDataHandle), loaderFactory));
-}
-
-std::unique_ptr<FetchDataConsumerHandle> FetchBlobDataConsumerHandle::create(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle)
-{
-    if (!blobDataHandle)
-        return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle());
-
-    return wrapUnique(new FetchBlobDataConsumerHandle(executionContext, std::move(blobDataHandle), new DefaultLoaderFactory));
-}
-
-std::unique_ptr<FetchDataConsumerHandle::Reader> FetchBlobDataConsumerHandle::obtainFetchDataReader(Client* client)
-{
-    return m_readerContext->obtainReader(client);
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.h b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.h
deleted file mode 100644
index e7c867b7..0000000
--- a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandle.h
+++ /dev/null
@@ -1,52 +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.
-
-#ifndef FetchBlobDataConsumerHandle_h
-#define FetchBlobDataConsumerHandle_h
-
-#include "core/fetch/ResourceLoaderOptions.h"
-#include "core/loader/ThreadableLoader.h"
-#include "modules/ModulesExport.h"
-#include "modules/fetch/FetchDataConsumerHandle.h"
-#include "platform/blob/BlobData.h"
-#include "platform/heap/Handle.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefPtr.h"
-#include <memory>
-
-namespace blink {
-
-class ExecutionContext;
-// A FetchBlobDataConsumerHandle is created from a blob handle and it will
-// return a valid handle from drainAsBlobDataHandle as much as possible.
-class MODULES_EXPORT FetchBlobDataConsumerHandle final : public FetchDataConsumerHandle {
-    WTF_MAKE_NONCOPYABLE(FetchBlobDataConsumerHandle);
-public:
-    class MODULES_EXPORT LoaderFactory : public GarbageCollectedFinalized<LoaderFactory> {
-    public:
-        virtual ThreadableLoader* create(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) = 0;
-        virtual ~LoaderFactory() { }
-        DEFINE_INLINE_VIRTUAL_TRACE() { }
-    };
-
-    static std::unique_ptr<FetchDataConsumerHandle> create(ExecutionContext*, PassRefPtr<BlobDataHandle>);
-
-    // For testing.
-    static std::unique_ptr<FetchDataConsumerHandle> create(ExecutionContext*, PassRefPtr<BlobDataHandle>, LoaderFactory*);
-
-    ~FetchBlobDataConsumerHandle();
-
-private:
-    FetchBlobDataConsumerHandle(ExecutionContext*, PassRefPtr<BlobDataHandle>, LoaderFactory*);
-    std::unique_ptr<Reader> obtainFetchDataReader(Client*) override;
-
-    const char* debugName() const override { return "FetchBlobDataConsumerHandle"; }
-
-    class ReaderContext;
-    RefPtr<ReaderContext> m_readerContext;
-};
-
-} // namespace blink
-
-#endif // FetchBlobDataConsumerHandle_h
diff --git a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandleTest.cpp b/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandleTest.cpp
deleted file mode 100644
index 8bd1ea4..0000000
--- a/third_party/WebKit/Source/modules/fetch/FetchBlobDataConsumerHandleTest.cpp
+++ /dev/null
@@ -1,449 +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.
-
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
-
-#include "core/dom/ExecutionContext.h"
-#include "core/fetch/ResourceLoaderOptions.h"
-#include "core/loader/MockThreadableLoader.h"
-#include "core/loader/ThreadableLoaderClient.h"
-#include "core/testing/DummyPageHolder.h"
-#include "modules/fetch/DataConsumerHandleTestUtil.h"
-#include "platform/blob/BlobData.h"
-#include "platform/blob/BlobURL.h"
-#include "platform/network/ResourceError.h"
-#include "platform/network/ResourceRequest.h"
-#include "platform/network/ResourceResponse.h"
-#include "platform/testing/UnitTestHelpers.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/PtrUtil.h"
-#include "wtf/RefPtr.h"
-#include <memory>
-#include <string.h>
-
-namespace blink {
-namespace {
-
-using Result = WebDataConsumerHandle::Result;
-const Result kShouldWait = WebDataConsumerHandle::ShouldWait;
-const Result kUnexpectedError = WebDataConsumerHandle::UnexpectedError;
-const Result kDone = WebDataConsumerHandle::Done;
-using Flags = WebDataConsumerHandle::Flags;
-const Flags kNone = WebDataConsumerHandle::FlagNone;
-using Thread = DataConsumerHandleTestUtil::Thread;
-using HandleReader = DataConsumerHandleTestUtil::HandleReader;
-using HandleTwoPhaseReader = DataConsumerHandleTestUtil::HandleTwoPhaseReader;
-using HandleReadResult = DataConsumerHandleTestUtil::HandleReadResult;
-using ReplayingHandle = DataConsumerHandleTestUtil::ReplayingHandle;
-using Command = DataConsumerHandleTestUtil::Command;
-template <typename T>
-using HandleReaderRunner = DataConsumerHandleTestUtil::HandleReaderRunner<T>;
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::InSequence;
-using ::testing::Ref;
-using ::testing::Return;
-using ::testing::SaveArg;
-using ::testing::StrictMock;
-using Checkpoint = StrictMock<::testing::MockFunction<void(int)>>;
-
-class MockLoaderFactory : public FetchBlobDataConsumerHandle::LoaderFactory {
-public:
-    MOCK_METHOD4(create, ThreadableLoader*(ExecutionContext&, ThreadableLoaderClient*, const ThreadableLoaderOptions&, const ResourceLoaderOptions&));
-};
-
-PassRefPtr<BlobDataHandle> createBlobDataHandle(const char* s)
-{
-    std::unique_ptr<BlobData> data = BlobData::create();
-    data->appendText(s, false);
-    auto size = data->length();
-    return BlobDataHandle::create(std::move(data), size);
-}
-
-String toString(const Vector<char>& data)
-{
-    return String(data.data(), data.size());
-}
-
-class FetchBlobDataConsumerHandleTest : public ::testing::Test {
-public:
-    FetchBlobDataConsumerHandleTest()
-        : m_dummyPageHolder(DummyPageHolder::create(IntSize(1, 1))) {}
-    ~FetchBlobDataConsumerHandleTest() override
-    {
-        m_dummyPageHolder = nullptr;
-        // We need this to collect garbage-collected mocks.
-        ThreadState::current()-> collectAllGarbage();
-    }
-
-    Document& document() { return m_dummyPageHolder->document(); }
-
-private:
-    std::unique_ptr<DummyPageHolder> m_dummyPageHolder;
-};
-
-TEST_F(FetchBlobDataConsumerHandleTest, CreateLoader)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    ResourceRequest request;
-    ThreadableLoaderOptions options;
-    ResourceLoaderOptions resourceLoaderOptions;
-
-    Persistent<MockThreadableLoader> loader = MockThreadableLoader::create();
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(
-        SaveArg<2>(&options),
-        SaveArg<3>(&resourceLoaderOptions),
-        Return(loader.get())));
-    EXPECT_CALL(*loader, start(_)).WillOnce(SaveArg<0>(&request));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*loader, cancel());
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-    testing::runPendingTasks();
-
-    char buffer[1];
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-
-    EXPECT_TRUE(request.url().getString().startsWith("blob:"));
-    EXPECT_TRUE(request.useStreamOnResponse());
-
-    EXPECT_EQ(ConsiderPreflight, options.preflightPolicy);
-    EXPECT_EQ(DenyCrossOriginRequests, options.crossOriginRequestPolicy);
-    EXPECT_EQ(DoNotEnforceContentSecurityPolicy, options.contentSecurityPolicyEnforcement);
-
-    EXPECT_EQ(DoNotBufferData, resourceLoaderOptions.dataBufferingPolicy);
-    EXPECT_EQ(DoNotAllowStoredCredentials, resourceLoaderOptions.allowCredentials);
-    EXPECT_EQ(ClientDidNotRequestCredentials, resourceLoaderOptions.credentialsRequested);
-    EXPECT_EQ(CheckContentSecurityPolicy, resourceLoaderOptions.contentSecurityPolicyOption);
-    EXPECT_EQ(DocumentContext, resourceLoaderOptions.requestInitiatorContext);
-    EXPECT_EQ(RequestAsynchronously, resourceLoaderOptions.synchronousPolicy);
-    EXPECT_EQ(NotCORSEnabled, resourceLoaderOptions.corsEnabled);
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, ZeroByteReadDoesNotCreateLoader)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(checkpoint, Call(2));
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-    testing::runPendingTasks();
-
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(nullptr, 0, kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, CancelLoaderWhenStopped)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    Persistent<MockThreadableLoader> loader = MockThreadableLoader::create();
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(Return(loader.get()));
-    EXPECT_CALL(*loader, start(_));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*loader, cancel());
-    EXPECT_CALL(checkpoint, Call(3));
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-    testing::runPendingTasks();
-
-    char buffer[1];
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    document().stopActiveDOMObjects();
-    checkpoint.Call(3);
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, CancelLoaderWhenDestinationDetached)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    Persistent<MockThreadableLoader> loader = MockThreadableLoader::create();
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(Return(loader.get()));
-    EXPECT_CALL(*loader, start(_));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(checkpoint, Call(3));
-    EXPECT_CALL(*loader, cancel());
-    EXPECT_CALL(checkpoint, Call(4));
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-    std::unique_ptr<WebDataConsumerHandle::Reader> reader = handle->obtainReader(nullptr);
-    testing::runPendingTasks();
-
-    char buffer[1];
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, reader->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    handle = nullptr;
-    reader = nullptr;
-    checkpoint.Call(3);
-    ThreadState::current()-> collectAllGarbage();
-    checkpoint.Call(4);
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, ReadTest)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    Persistent<MockThreadableLoader> loader = MockThreadableLoader::create();
-    ThreadableLoaderClient* client = nullptr;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get())));
-    EXPECT_CALL(*loader, start(_));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*loader, cancel());
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Wait));
-    src->add(Command(Command::Data, "hello, "));
-    src->add(Command(Command::Data, "world"));
-    src->add(Command(Command::Wait));
-    src->add(Command(Command::Done));
-
-    char buffer[1];
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    client->didReceiveResponse(0, ResourceResponse(), std::move(src));
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("hello, world", toString(r->data()));
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, TwoPhaseReadTest)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    Persistent<MockThreadableLoader> loader = MockThreadableLoader::create();
-    ThreadableLoaderClient* client = nullptr;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get())));
-    EXPECT_CALL(*loader, start(_));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*loader, cancel());
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Wait));
-    src->add(Command(Command::Data, "hello, "));
-    src->add(Command(Command::Data, "world"));
-    src->add(Command(Command::Wait));
-    src->add(Command(Command::Done));
-
-    char buffer[1];
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    client->didReceiveResponse(0, ResourceResponse(), std::move(src));
-    HandleReaderRunner<HandleTwoPhaseReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("hello, world", toString(r->data()));
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, LoadErrorTest)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    Persistent<MockThreadableLoader> loader = MockThreadableLoader::create();
-    ThreadableLoaderClient* client = nullptr;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get())));
-    EXPECT_CALL(*loader, start(_));
-    EXPECT_CALL(checkpoint, Call(2));
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-
-    char buffer[1];
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    client->didFail(ResourceError());
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kUnexpectedError, r->result());
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, BodyLoadErrorTest)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-    Checkpoint checkpoint;
-
-    Persistent<MockThreadableLoader> loader = MockThreadableLoader::create();
-    ThreadableLoaderClient* client = nullptr;
-
-    InSequence s;
-    EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*factory, create(Ref(document()), _, _, _)).WillOnce(DoAll(SaveArg<1>(&client), Return(loader.get())));
-    EXPECT_CALL(*loader, start(_));
-    EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*loader, cancel());
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<WebDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Wait));
-    src->add(Command(Command::Data, "hello, "));
-    src->add(Command(Command::Error));
-
-    char buffer[1];
-    size_t size = 0;
-    ASSERT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(buffer, sizeof(buffer), kNone, &size));
-    checkpoint.Call(1);
-    testing::runPendingTasks();
-    checkpoint.Call(2);
-    client->didReceiveResponse(0, ResourceResponse(), std::move(src));
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kUnexpectedError, r->result());
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, DrainAsBlobDataHandle)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<FetchDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-
-    size_t size = 0;
-    EXPECT_EQ(blobDataHandle, handle->obtainFetchDataReader(nullptr)->drainAsBlobDataHandle());
-    EXPECT_FALSE(handle->obtainFetchDataReader(nullptr)->drainAsFormData());
-
-    EXPECT_EQ(kDone, handle->obtainReader(nullptr)->read(nullptr, 0, kNone, &size));
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, DrainAsFormData)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<FetchDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-
-    RefPtr<EncodedFormData> formData = handle->obtainFetchDataReader(nullptr)->drainAsFormData();
-    ASSERT_TRUE(formData);
-    EXPECT_TRUE(formData->isSafeToSendToAnotherThread());
-    ASSERT_EQ(1u, formData->elements().size());
-    EXPECT_EQ(FormDataElement::encodedBlob, formData->elements()[0].m_type);
-    EXPECT_EQ(blobDataHandle->uuid(), formData->elements()[0].m_blobUUID);
-    EXPECT_EQ(blobDataHandle, formData->elements()[0].m_optionalBlobDataHandle);
-
-    EXPECT_FALSE(handle->obtainFetchDataReader(nullptr)->drainAsBlobDataHandle());
-    size_t size;
-    EXPECT_EQ(kDone, handle->obtainFetchDataReader(nullptr)->read(nullptr, 0, kNone, &size));
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, ZeroByteReadDoesNotAffectDraining)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<FetchDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-
-    size_t readSize;
-    EXPECT_EQ(kShouldWait, reader->read(nullptr, 0, kNone, &readSize));
-    EXPECT_EQ(blobDataHandle, reader->drainAsBlobDataHandle());
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, OneByteReadAffectsDraining)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<FetchDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-
-    size_t readSize;
-    char c;
-    EXPECT_EQ(kShouldWait, reader->read(&c, 1, kNone, &readSize));
-    EXPECT_FALSE(reader->drainAsFormData());
-}
-
-TEST_F(FetchBlobDataConsumerHandleTest, BeginReadAffectsDraining)
-{
-    auto factory = new StrictMock<MockLoaderFactory>;
-
-    RefPtr<BlobDataHandle> blobDataHandle = createBlobDataHandle("Once upon a time");
-    std::unique_ptr<FetchDataConsumerHandle> handle
-        = FetchBlobDataConsumerHandle::create(&document(), blobDataHandle, factory);
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-
-    const void* buffer;
-    size_t available;
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    EXPECT_FALSE(reader->drainAsBlobDataHandle());
-}
-
-} // namespace
-} // namespace blink
diff --git a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandle.cpp b/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandle.cpp
deleted file mode 100644
index dba4a4a..0000000
--- a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandle.cpp
+++ /dev/null
@@ -1,338 +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.
-
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
-
-#include "modules/fetch/DataConsumerHandleUtil.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
-#include "wtf/PtrUtil.h"
-#include "wtf/ThreadingPrimitives.h"
-#include "wtf/Vector.h"
-#include "wtf/text/TextCodec.h"
-#include "wtf/text/TextEncoding.h"
-#include "wtf/text/WTFString.h"
-#include <memory>
-#include <utility>
-
-namespace blink {
-
-using Result = FetchDataConsumerHandle::Result;
-
-namespace {
-
-bool isSimple(const EncodedFormData* formData)
-{
-    for (const auto& element : formData->elements()) {
-        if (element.m_type != FormDataElement::data)
-            return false;
-    }
-    return true;
-}
-
-} // namespace
-
-class FetchFormDataConsumerHandle::Context : public ThreadSafeRefCounted<Context> {
-    WTF_MAKE_NONCOPYABLE(Context);
-public:
-    virtual ~Context() {}
-    virtual std::unique_ptr<FetchDataConsumerHandle::Reader> obtainReader(Client*) = 0;
-
-protected:
-    explicit Context() {}
-};
-
-class FetchFormDataConsumerHandle::SimpleContext final : public Context {
-    class ReaderImpl;
-public:
-    static PassRefPtr<SimpleContext> create(const String& body) { return adoptRef(new SimpleContext(body)); }
-    static PassRefPtr<SimpleContext> create(const void* data, size_t size) { return adoptRef(new SimpleContext(data, size)); }
-    static PassRefPtr<SimpleContext> create(PassRefPtr<EncodedFormData> body) { return adoptRef(new SimpleContext(std::move(body))); }
-
-    std::unique_ptr<Reader> obtainReader(Client* client) override
-    {
-        // For memory barrier.
-        Mutex m;
-        MutexLocker locker(m);
-        return ReaderImpl::create(this, client);
-    }
-
-    PassRefPtr<BlobDataHandle> drainAsBlobDataHandle()
-    {
-        if (!m_formData)
-            return nullptr;
-        flatten();
-        std::unique_ptr<BlobData> blobData = BlobData::create();
-        blobData->appendBytes(m_flattenFormData.data(), m_flattenFormData.size());
-        m_flattenFormData.clear();
-        auto length = blobData->length();
-        return BlobDataHandle::create(std::move(blobData), length);
-    }
-
-    PassRefPtr<EncodedFormData> drainFormData()
-    {
-        ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread());
-        return m_formData.release();
-    }
-
-    Result read(void* data, size_t size, Flags flags, size_t* readSize)
-    {
-        *readSize = 0;
-        if (size == 0 && m_formData)
-            return WebDataConsumerHandle::Ok;
-
-        flatten();
-        RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
-
-        *readSize = std::min(size, m_flattenFormData.size() - m_flattenFormDataOffset);
-        if (*readSize == 0)
-            return WebDataConsumerHandle::Done;
-        memcpy(data, &m_flattenFormData[m_flattenFormDataOffset], *readSize);
-        m_flattenFormDataOffset += *readSize;
-        RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
-
-        return WebDataConsumerHandle::Ok;
-    }
-
-    Result beginRead(const void** buffer, Flags flags, size_t* available)
-    {
-        *buffer = nullptr;
-        *available = 0;
-
-        flatten();
-        RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
-
-        if (m_flattenFormData.size() == m_flattenFormDataOffset)
-            return WebDataConsumerHandle::Done;
-        *buffer = &m_flattenFormData[m_flattenFormDataOffset];
-        *available = m_flattenFormData.size() - m_flattenFormDataOffset;
-        return WebDataConsumerHandle::Ok;
-    }
-
-    Result endRead(size_t read)
-    {
-        RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
-        RELEASE_ASSERT(read <= m_flattenFormData.size() - m_flattenFormDataOffset);
-        m_flattenFormDataOffset += read;
-
-        return WebDataConsumerHandle::Ok;
-    }
-
-private:
-    class ReaderImpl final : public FetchDataConsumerHandle::Reader {
-        WTF_MAKE_NONCOPYABLE(ReaderImpl);
-    public:
-        static std::unique_ptr<ReaderImpl> create(PassRefPtr<SimpleContext> context, Client* client) { return wrapUnique(new ReaderImpl(std::move(context), client)); }
-        Result read(void* data, size_t size, Flags flags, size_t* readSize) override
-        {
-            return m_context->read(data, size, flags, readSize);
-        }
-        Result beginRead(const void** buffer, Flags flags, size_t* available) override
-        {
-            return m_context->beginRead(buffer, flags, available);
-        }
-        Result endRead(size_t read) override
-        {
-            return m_context->endRead(read);
-        }
-        PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy) override
-        {
-            // A "simple" FormData always has a finite known size.
-            return m_context->drainAsBlobDataHandle();
-        }
-        PassRefPtr<EncodedFormData> drainAsFormData() override
-        {
-            return m_context->drainFormData();
-        }
-
-    private:
-        ReaderImpl(PassRefPtr<SimpleContext> context, Client* client) : m_context(context), m_notifier(client) {}
-
-        RefPtr<SimpleContext> m_context;
-        NotifyOnReaderCreationHelper m_notifier;
-    };
-
-    explicit SimpleContext(const String& body)
-        : m_formData(EncodedFormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables)))
-        , m_flattenFormDataOffset(0) {}
-    SimpleContext(const void* data, size_t size) : m_formData(EncodedFormData::create(data, size)) , m_flattenFormDataOffset(0) {}
-    explicit SimpleContext(PassRefPtr<EncodedFormData> body) : m_formData(body->deepCopy()) , m_flattenFormDataOffset(0) {}
-
-    void flatten()
-    {
-        if (!m_formData) {
-            // It is already drained or flatten.
-            return;
-        }
-        ASSERT(m_formData->isSafeToSendToAnotherThread());
-        m_formData->flatten(m_flattenFormData);
-        m_formData = nullptr;
-    }
-
-    // either one of |m_formData| and |m_flattenFormData| is usable at a time.
-    RefPtr<EncodedFormData> m_formData;
-    Vector<char> m_flattenFormData;
-    size_t m_flattenFormDataOffset;
-};
-
-class FetchFormDataConsumerHandle::ComplexContext final : public Context {
-    class ReaderImpl;
-public:
-    static PassRefPtr<ComplexContext> create(ExecutionContext* executionContext,
-        PassRefPtr<EncodedFormData> formData,
-        FetchBlobDataConsumerHandle::LoaderFactory* factory)
-    {
-        return adoptRef(new ComplexContext(executionContext, std::move(formData), factory));
-    }
-
-    std::unique_ptr<FetchFormDataConsumerHandle::Reader> obtainReader(Client* client) override
-    {
-        // For memory barrier.
-        Mutex m;
-        MutexLocker locker(m);
-        return ReaderImpl::create(this, client);
-    }
-
-private:
-    class ReaderImpl final : public FetchDataConsumerHandle::Reader {
-        WTF_MAKE_NONCOPYABLE(ReaderImpl);
-    public:
-        static std::unique_ptr<ReaderImpl> create(PassRefPtr<ComplexContext> context, Client* client) { return wrapUnique(new ReaderImpl(std::move(context), client)); }
-        Result read(void* data, size_t size, Flags flags, size_t* readSize) override
-        {
-            Result r = m_reader->read(data, size, flags, readSize);
-            if (!(size == 0 && (r == Ok || r == ShouldWait))) {
-                m_context->drainFormData();
-            }
-            return r;
-        }
-        Result beginRead(const void** buffer, Flags flags, size_t* available) override
-        {
-            m_context->drainFormData();
-            return m_reader->beginRead(buffer, flags, available);
-        }
-        Result endRead(size_t read) override
-        {
-            return m_reader->endRead(read);
-        }
-        PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy policy) override
-        {
-            RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle(policy);
-            if (handle) {
-                m_context->drainFormData();
-            }
-            return handle.release();
-        }
-        PassRefPtr<EncodedFormData> drainAsFormData() override
-        {
-            RefPtr<EncodedFormData> formData = m_context->drainFormData();
-            if (formData) {
-                // Drain blob from the underlying handle to mark data as read.
-                RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle(AllowBlobWithInvalidSize);
-                // Here we assume we can always get the valid handle. That is
-                // in fact not specified at FetchDataConsumerHandle level, but
-                // |m_context->m_handle| is a FetchBlobDataConsumerHandle.
-                ASSERT(handle);
-            }
-            return formData.release();
-        }
-    private:
-        ReaderImpl(PassRefPtr<ComplexContext> context, Client* client) : m_context(context), m_reader(m_context->m_handle->obtainFetchDataReader(client)) {}
-
-        RefPtr<ComplexContext> m_context;
-        std::unique_ptr<FetchDataConsumerHandle::Reader> m_reader;
-    };
-
-    ComplexContext(ExecutionContext* executionContext, PassRefPtr<EncodedFormData> body, FetchBlobDataConsumerHandle::LoaderFactory* factory)
-    {
-        std::unique_ptr<BlobData> blobData = BlobData::create();
-        for (const auto& element : body->elements()) {
-            switch (element.m_type) {
-            case FormDataElement::data:
-                blobData->appendBytes(element.m_data.data(), element.m_data.size());
-                break;
-            case FormDataElement::encodedFile:
-                blobData->appendFile(element.m_filename, element.m_fileStart, element.m_fileLength, element.m_expectedFileModificationTime);
-                break;
-            case FormDataElement::encodedBlob:
-                if (element.m_optionalBlobDataHandle)
-                    blobData->appendBlob(element.m_optionalBlobDataHandle, 0, element.m_optionalBlobDataHandle->size());
-                break;
-            case FormDataElement::encodedFileSystemURL:
-                blobData->appendFileSystemURL(element.m_fileSystemURL, element.m_fileStart, element.m_fileLength, element.m_expectedFileModificationTime);
-                break;
-            }
-        }
-        // Here we handle body->boundary() as a C-style string. See
-        // FormDataEncoder::generateUniqueBoundaryString.
-        blobData->setContentType(AtomicString("multipart/form-data; boundary=") + body->boundary().data());
-        auto size = blobData->length();
-        if (factory) {
-            // For testing
-            m_handle = FetchBlobDataConsumerHandle::create(executionContext, BlobDataHandle::create(std::move(blobData), size), factory);
-        } else {
-            m_handle = FetchBlobDataConsumerHandle::create(executionContext, BlobDataHandle::create(std::move(blobData), size));
-        }
-        // It is important to initialize |m_formData| here, because even
-        // read-only operations may make the form data unsharable with implicit
-        // ref-counting.
-        m_formData = body->deepCopy();
-    }
-    PassRefPtr<EncodedFormData> drainFormData()
-    {
-        ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread());
-        return m_formData.release();
-    }
-
-    RefPtr<EncodedFormData> m_formData;
-    std::unique_ptr<FetchDataConsumerHandle> m_handle;
-};
-
-std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(const String& body)
-{
-    return wrapUnique(new FetchFormDataConsumerHandle(body));
-}
-std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(DOMArrayBuffer* body)
-{
-    return wrapUnique(new FetchFormDataConsumerHandle(body->data(), body->byteLength()));
-}
-std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(DOMArrayBufferView* body)
-{
-    return wrapUnique(new FetchFormDataConsumerHandle(body->baseAddress(), body->byteLength()));
-}
-std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(const void* data, size_t size)
-{
-    return wrapUnique(new FetchFormDataConsumerHandle(data, size));
-}
-std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(ExecutionContext* executionContext, PassRefPtr<EncodedFormData> body)
-{
-    return wrapUnique(new FetchFormDataConsumerHandle(executionContext, std::move(body)));
-}
-std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::createForTest(
-    ExecutionContext* executionContext,
-    PassRefPtr<EncodedFormData> body,
-    FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
-{
-    return wrapUnique(new FetchFormDataConsumerHandle(executionContext, std::move(body), loaderFactory));
-}
-
-FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const String& body) : m_context(SimpleContext::create(body)) {}
-FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const void* data, size_t size) : m_context(SimpleContext::create(data, size)) {}
-FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(ExecutionContext* executionContext,
-    PassRefPtr<EncodedFormData> body,
-    FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
-{
-    if (isSimple(body.get())) {
-        m_context = SimpleContext::create(std::move(body));
-    } else {
-        m_context = ComplexContext::create(executionContext, std::move(body), loaderFactory);
-    }
-}
-FetchFormDataConsumerHandle::~FetchFormDataConsumerHandle() {}
-
-std::unique_ptr<FetchDataConsumerHandle::Reader> FetchFormDataConsumerHandle::obtainFetchDataReader(Client* client)
-{
-    return m_context->obtainReader(client);
-}
-
-} // namespace blink
diff --git a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandle.h b/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandle.h
deleted file mode 100644
index 90ee589..0000000
--- a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandle.h
+++ /dev/null
@@ -1,63 +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.
-
-#ifndef FetchFormDataConsumerHandle_h
-#define FetchFormDataConsumerHandle_h
-
-#include "core/dom/DOMArrayBuffer.h"
-#include "core/dom/DOMArrayBufferView.h"
-#include "modules/ModulesExport.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
-#include "modules/fetch/FetchDataConsumerHandle.h"
-#include "platform/blob/BlobData.h"
-#include "platform/network/EncodedFormData.h"
-#include "wtf/Forward.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefPtr.h"
-#include "wtf/ThreadSafeRefCounted.h"
-#include <memory>
-
-namespace blink {
-
-class ExecutionContext;
-
-// FetchFormDataConsumerHandle is a handle made from an EncodedFormData. It
-// provides drainAsFormData in the associated Reader.
-class MODULES_EXPORT FetchFormDataConsumerHandle final : public FetchDataConsumerHandle {
-    WTF_MAKE_NONCOPYABLE(FetchFormDataConsumerHandle);
-public:
-    static std::unique_ptr<FetchDataConsumerHandle> create(const String& body);
-    static std::unique_ptr<FetchDataConsumerHandle> create(DOMArrayBuffer* body);
-    static std::unique_ptr<FetchDataConsumerHandle> create(DOMArrayBufferView* body);
-    static std::unique_ptr<FetchDataConsumerHandle> create(const void* data, size_t);
-    static std::unique_ptr<FetchDataConsumerHandle> create(ExecutionContext*, PassRefPtr<EncodedFormData> body);
-    // Use FetchBlobDataConsumerHandle for blobs.
-
-    ~FetchFormDataConsumerHandle() override;
-
-    static std::unique_ptr<FetchDataConsumerHandle> createForTest(
-        ExecutionContext*,
-        PassRefPtr<EncodedFormData> body,
-        FetchBlobDataConsumerHandle::LoaderFactory*);
-
-private:
-    class Context;
-    class SimpleContext;
-    class ComplexContext;
-    class ReaderImpl;
-
-    explicit FetchFormDataConsumerHandle(const String& body);
-    FetchFormDataConsumerHandle(const void*, size_t);
-    FetchFormDataConsumerHandle(ExecutionContext*, PassRefPtr<EncodedFormData> body, FetchBlobDataConsumerHandle::LoaderFactory* = nullptr);
-
-    std::unique_ptr<Reader> obtainFetchDataReader(Client*) override;
-
-    const char* debugName() const override { return "FetchFormDataConsumerHandle"; }
-
-    RefPtr<Context> m_context;
-};
-
-} // namespace blink
-
-#endif // FetchFormDataConsumerHandle_h
diff --git a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandleTest.cpp b/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandleTest.cpp
deleted file mode 100644
index b92de7e..0000000
--- a/third_party/WebKit/Source/modules/fetch/FetchFormDataConsumerHandleTest.cpp
+++ /dev/null
@@ -1,445 +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.
-
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
-
-#include "core/dom/DOMTypedArray.h"
-#include "core/html/FormData.h"
-#include "core/loader/MockThreadableLoader.h"
-#include "core/loader/ThreadableLoaderClient.h"
-#include "core/testing/DummyPageHolder.h"
-#include "modules/fetch/DataConsumerHandleTestUtil.h"
-#include "platform/network/ResourceResponse.h"
-#include "platform/testing/UnitTestHelpers.h"
-#include "platform/weborigin/KURL.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "wtf/PassRefPtr.h"
-#include "wtf/RefPtr.h"
-#include "wtf/Vector.h"
-#include "wtf/text/TextEncoding.h"
-#include "wtf/text/WTFString.h"
-#include <memory>
-#include <string.h>
-
-namespace blink {
-namespace {
-
-using Result = WebDataConsumerHandle::Result;
-const Result kOk = WebDataConsumerHandle::Ok;
-const Result kDone = WebDataConsumerHandle::Done;
-const Result kShouldWait = WebDataConsumerHandle::ShouldWait;
-const WebDataConsumerHandle::Flags kNone = WebDataConsumerHandle::FlagNone;
-using HandleReader = DataConsumerHandleTestUtil::HandleReader;
-using HandleTwoPhaseReader = DataConsumerHandleTestUtil::HandleTwoPhaseReader;
-using HandleReadResult = DataConsumerHandleTestUtil::HandleReadResult;
-template <typename T>
-using HandleReaderRunner = DataConsumerHandleTestUtil::HandleReaderRunner<T>;
-using ReplayingHandle = DataConsumerHandleTestUtil::ReplayingHandle;
-using Command = DataConsumerHandleTestUtil::Command;
-
-using ::testing::_;
-using ::testing::InvokeWithoutArgs;
-
-String toString(const Vector<char>& data)
-{
-    return String(data.data(), data.size());
-}
-
-class LoaderFactory : public FetchBlobDataConsumerHandle::LoaderFactory {
-public:
-    explicit LoaderFactory(std::unique_ptr<WebDataConsumerHandle> handle)
-        : m_client(nullptr)
-        , m_handle(std::move(handle)) {}
-    ThreadableLoader* create(ExecutionContext&, ThreadableLoaderClient* client, const ThreadableLoaderOptions&, const ResourceLoaderOptions&) override
-    {
-        m_client = client;
-
-        MockThreadableLoader* loader = MockThreadableLoader::create();
-        EXPECT_CALL(*loader, start(_)).WillOnce(InvokeWithoutArgs(this, &LoaderFactory::handleDidReceiveResponse));
-        EXPECT_CALL(*loader, cancel()).Times(1);
-        return loader;
-    }
-
-private:
-    void handleDidReceiveResponse()
-    {
-        m_client->didReceiveResponse(0, ResourceResponse(), std::move(m_handle));
-    }
-
-    ThreadableLoaderClient* m_client;
-    std::unique_ptr<WebDataConsumerHandle> m_handle;
-};
-
-class FetchFormDataConsumerHandleTest : public ::testing::Test {
-public:
-    FetchFormDataConsumerHandleTest() : m_page(DummyPageHolder::create(IntSize(1, 1))) {}
-
-protected:
-    Document* getDocument() { return &m_page->document(); }
-
-    std::unique_ptr<DummyPageHolder> m_page;
-};
-
-PassRefPtr<EncodedFormData> complexFormData()
-{
-    RefPtr<EncodedFormData> data = EncodedFormData::create();
-
-    data->appendData("foo", 3);
-    data->appendFileRange("/foo/bar/baz", 3, 4, 5);
-    data->appendFileSystemURLRange(KURL(KURL(), "file:///foo/bar/baz"), 6, 7, 8);
-    std::unique_ptr<BlobData> blobData = BlobData::create();
-    blobData->appendText("hello", false);
-    auto size = blobData->length();
-    RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(std::move(blobData), size);
-    data->appendBlob(blobDataHandle->uuid(), blobDataHandle);
-    Vector<char> boundary;
-    boundary.append("\0", 1);
-    data->setBoundary(boundary);
-    return data.release();
-}
-
-void verifyComplexFormData(EncodedFormData* data)
-{
-    const auto& elements = data->elements();
-    if (4 != elements.size()) {
-        FAIL() << "data->elements().size() should be 4, but is " << data->elements().size() << ".";
-    }
-    EXPECT_EQ(FormDataElement::data, elements[0].m_type);
-    EXPECT_EQ("foo", String(elements[0].m_data.data(), elements[0].m_data.size()));
-
-    EXPECT_EQ(FormDataElement::encodedFile, elements[1].m_type);
-    EXPECT_EQ("/foo/bar/baz", elements[1].m_filename);
-    EXPECT_EQ(3, elements[1].m_fileStart);
-    EXPECT_EQ(4, elements[1].m_fileLength);
-    EXPECT_EQ(5, elements[1].m_expectedFileModificationTime);
-
-    EXPECT_EQ(FormDataElement::encodedFileSystemURL, elements[2].m_type);
-    EXPECT_EQ(KURL(KURL(), "file:///foo/bar/baz"), elements[2].m_fileSystemURL);
-    EXPECT_EQ(6, elements[2].m_fileStart);
-    EXPECT_EQ(7, elements[2].m_fileLength);
-    EXPECT_EQ(8, elements[2].m_expectedFileModificationTime);
-
-    EXPECT_EQ(FormDataElement::encodedBlob, elements[3].m_type);
-    if (!elements[3].m_optionalBlobDataHandle) {
-        FAIL() << "optional BlobDataHandle must be set.";
-    }
-    EXPECT_EQ(elements[3].m_blobUUID, elements[3].m_optionalBlobDataHandle->uuid());
-    EXPECT_EQ(5u, elements[3].m_optionalBlobDataHandle->size());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ReadFromString)
-{
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String("hello, world"));
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("hello, world", toString(r->data()));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, TwoPhaseReadFromString)
-{
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String("hello, world"));
-    HandleReaderRunner<HandleTwoPhaseReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("hello, world", toString(r->data()));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ReadFromStringNonLatin)
-{
-    UChar cs[] = {0x3042, 0};
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String(cs));
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("\xe3\x81\x82", toString(r->data()));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ReadFromArrayBuffer)
-{
-    const unsigned char data[] = { 0x21, 0xfe, 0x00, 0x00, 0xff, 0xa3, 0x42, 0x30, 0x42, 0x99, 0x88 };
-    DOMArrayBuffer* buffer = DOMArrayBuffer::create(data, WTF_ARRAY_LENGTH(data));
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(buffer);
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    Vector<char> expected;
-    expected.append(data, WTF_ARRAY_LENGTH(data));
-    EXPECT_EQ(expected, r->data());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ReadFromArrayBufferView)
-{
-    const unsigned char data[] = { 0x21, 0xfe, 0x00, 0x00, 0xff, 0xa3, 0x42, 0x30, 0x42, 0x99, 0x88 };
-    const size_t offset = 1, size = 4;
-    DOMArrayBuffer* buffer = DOMArrayBuffer::create(data, WTF_ARRAY_LENGTH(data));
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(DOMUint8Array::create(buffer, offset, size));
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    Vector<char> expected;
-    expected.append(data + offset, size);
-    EXPECT_EQ(expected, r->data());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ReadFromSimplFormData)
-{
-    RefPtr<EncodedFormData> data = EncodedFormData::create();
-    data->appendData("foo", 3);
-    data->appendData("hoge", 4);
-
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(getDocument(), data);
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    testing::runPendingTasks();
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("foohoge", toString(r->data()));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ReadFromComplexFormData)
-{
-    RefPtr<EncodedFormData> data = complexFormData();
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Data, "bar"));
-    src->add(Command(Command::Done));
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::createForTest(getDocument(), data, new LoaderFactory(std::move(src)));
-    char c;
-    size_t readSize;
-    EXPECT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(&c, 1, kNone, &readSize));
-
-    HandleReaderRunner<HandleReader> runner(std::move(handle));
-    testing::runPendingTasks();
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("bar", toString(r->data()));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, TwoPhaseReadFromComplexFormData)
-{
-    RefPtr<EncodedFormData> data = complexFormData();
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Data, "bar"));
-    src->add(Command(Command::Done));
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::createForTest(getDocument(), data, new LoaderFactory(std::move(src)));
-    char c;
-    size_t readSize;
-    EXPECT_EQ(kShouldWait, handle->obtainReader(nullptr)->read(&c, 1, kNone, &readSize));
-
-    HandleReaderRunner<HandleTwoPhaseReader> runner(std::move(handle));
-    testing::runPendingTasks();
-    std::unique_ptr<HandleReadResult> r = runner.wait();
-    EXPECT_EQ(kDone, r->result());
-    EXPECT_EQ("bar", toString(r->data()));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsBlobDataHandleFromString)
-{
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String("hello, world"));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<BlobDataHandle> blobDataHandle = reader->drainAsBlobDataHandle();
-    ASSERT_TRUE(blobDataHandle);
-
-    EXPECT_EQ(String(), blobDataHandle->type());
-    EXPECT_EQ(12u, blobDataHandle->size());
-    EXPECT_EQ(nullptr, reader->drainAsFormData());
-    char c;
-    size_t readSize;
-    EXPECT_EQ(kDone, reader->read(&c, 1, kNone, &readSize));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsBlobDataHandleFromArrayBuffer)
-{
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(DOMArrayBuffer::create("foo", 3));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<BlobDataHandle> blobDataHandle = reader->drainAsBlobDataHandle();
-    ASSERT_TRUE(blobDataHandle);
-
-    EXPECT_EQ(String(), blobDataHandle->type());
-    EXPECT_EQ(3u, blobDataHandle->size());
-    EXPECT_EQ(nullptr, reader->drainAsFormData());
-    char c;
-    size_t readSize;
-    EXPECT_EQ(kDone, reader->read(&c, 1, kNone, &readSize));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsBlobDataHandleFromSimpleFormData)
-{
-    FormData* data = FormData::create(UTF8Encoding());
-    data->append("name1", "value1");
-    data->append("name2", "value2");
-    RefPtr<EncodedFormData> inputFormData = data->encodeMultiPartFormData();
-
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(getDocument(), inputFormData);
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<BlobDataHandle> blobDataHandle = reader->drainAsBlobDataHandle();
-    ASSERT_TRUE(blobDataHandle);
-
-    EXPECT_EQ(String(), blobDataHandle->type());
-    EXPECT_EQ(inputFormData->flattenToString().utf8().length(), blobDataHandle->size());
-    EXPECT_EQ(nullptr, reader->drainAsFormData());
-    char c;
-    size_t readSize;
-    EXPECT_EQ(kDone, reader->read(&c, 1, kNone, &readSize));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsBlobDataHandleFromComplexFormData)
-{
-    RefPtr<EncodedFormData> inputFormData = complexFormData();
-
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(getDocument(), inputFormData);
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<BlobDataHandle> blobDataHandle = reader->drainAsBlobDataHandle();
-    ASSERT_TRUE(blobDataHandle);
-
-    EXPECT_EQ(nullptr, reader->drainAsFormData());
-    char c;
-    size_t readSize;
-    EXPECT_EQ(kDone, reader->read(&c, 1, kNone, &readSize));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromString)
-{
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String("hello, world"));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<EncodedFormData> formData = reader->drainAsFormData();
-    ASSERT_TRUE(formData);
-    EXPECT_TRUE(formData->isSafeToSendToAnotherThread());
-    EXPECT_EQ("hello, world", formData->flattenToString());
-
-    const void* buffer = nullptr;
-    size_t size;
-    EXPECT_EQ(kDone, reader->read(nullptr, 0, kNone, &size));
-    EXPECT_EQ(kDone, reader->beginRead(&buffer, kNone, &size));
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromArrayBuffer)
-{
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(DOMArrayBuffer::create("foo", 3));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<EncodedFormData> formData = reader->drainAsFormData();
-    ASSERT_TRUE(formData);
-    EXPECT_TRUE(formData->isSafeToSendToAnotherThread());
-    EXPECT_EQ("foo", formData->flattenToString());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromSimpleFormData)
-{
-    FormData* data = FormData::create(UTF8Encoding());
-    data->append("name1", "value1");
-    data->append("name2", "value2");
-    RefPtr<EncodedFormData> inputFormData = data->encodeMultiPartFormData();
-
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(getDocument(), inputFormData);
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<EncodedFormData> outputFormData = reader->drainAsFormData();
-    ASSERT_TRUE(outputFormData);
-    EXPECT_TRUE(outputFormData->isSafeToSendToAnotherThread());
-    EXPECT_NE(outputFormData.get(), inputFormData.get());
-    EXPECT_EQ(inputFormData->flattenToString(), outputFormData->flattenToString());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, DrainAsFormDataFromComplexFormData)
-{
-    RefPtr<EncodedFormData> inputFormData = complexFormData();
-
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(getDocument(), inputFormData);
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    RefPtr<EncodedFormData> outputFormData = reader->drainAsFormData();
-    ASSERT_TRUE(outputFormData);
-    EXPECT_TRUE(outputFormData->isSafeToSendToAnotherThread());
-    EXPECT_NE(outputFormData.get(), inputFormData.get());
-    verifyComplexFormData(outputFormData.get());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ZeroByteReadDoesNotAffectDraining)
-{
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String("hello, world"));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    size_t readSize;
-    EXPECT_EQ(kOk, reader->read(nullptr, 0, kNone, &readSize));
-    RefPtr<EncodedFormData> formData = reader->drainAsFormData();
-    ASSERT_TRUE(formData);
-    EXPECT_TRUE(formData->isSafeToSendToAnotherThread());
-    EXPECT_EQ("hello, world", formData->flattenToString());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, OneByteReadAffectsDraining)
-{
-    char c;
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String("hello, world"));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    size_t readSize;
-    EXPECT_EQ(kOk, reader->read(&c, 1, kNone, &readSize));
-    EXPECT_EQ(1u, readSize);
-    EXPECT_EQ('h', c);
-    EXPECT_FALSE(reader->drainAsFormData());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, BeginReadAffectsDraining)
-{
-    const void* buffer = nullptr;
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::create(String("hello, world"));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    size_t available;
-    EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available));
-    ASSERT_TRUE(buffer);
-    EXPECT_EQ("hello, world", String(static_cast<const char*>(buffer), available));
-    EXPECT_FALSE(reader->drainAsFormData());
-    reader->endRead(0);
-    EXPECT_FALSE(reader->drainAsFormData());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, ZeroByteReadDoesNotAffectDrainingForComplexFormData)
-{
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Data, "bar"));
-    src->add(Command(Command::Done));
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::createForTest(getDocument(), complexFormData(), new LoaderFactory(std::move(src)));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    size_t readSize;
-    EXPECT_EQ(kShouldWait, reader->read(nullptr, 0, kNone, &readSize));
-    testing::runPendingTasks();
-    RefPtr<EncodedFormData> formData = reader->drainAsFormData();
-    ASSERT_TRUE(formData);
-    EXPECT_TRUE(formData->isSafeToSendToAnotherThread());
-    verifyComplexFormData(formData.get());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, OneByteReadAffectsDrainingForComplexFormData)
-{
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Data, "bar"));
-    src->add(Command(Command::Done));
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::createForTest(getDocument(), complexFormData(), new LoaderFactory(std::move(src)));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    char c;
-    size_t readSize;
-    EXPECT_EQ(kShouldWait, reader->read(&c, 1, kNone, &readSize));
-    testing::runPendingTasks();
-    EXPECT_EQ(kOk, reader->read(&c, 1, kNone, &readSize));
-    EXPECT_EQ(1u, readSize);
-    EXPECT_EQ('b', c);
-    EXPECT_FALSE(reader->drainAsFormData());
-}
-
-TEST_F(FetchFormDataConsumerHandleTest, BeginReadAffectsDrainingForComplexFormData)
-{
-    std::unique_ptr<ReplayingHandle> src = ReplayingHandle::create();
-    src->add(Command(Command::Data, "bar"));
-    src->add(Command(Command::Done));
-    const void* buffer = nullptr;
-    std::unique_ptr<FetchDataConsumerHandle> handle = FetchFormDataConsumerHandle::createForTest(getDocument(), complexFormData(), new LoaderFactory(std::move(src)));
-    std::unique_ptr<FetchDataConsumerHandle::Reader> reader = handle->obtainFetchDataReader(nullptr);
-    size_t available;
-    EXPECT_EQ(kShouldWait, reader->beginRead(&buffer, kNone, &available));
-    testing::runPendingTasks();
-    EXPECT_EQ(kOk, reader->beginRead(&buffer, kNone, &available));
-    EXPECT_FALSE(reader->drainAsFormData());
-    reader->endRead(0);
-    EXPECT_FALSE(reader->drainAsFormData());
-}
-
-} // namespace
-} // namespace blink
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
index d229085..dae30e4 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
@@ -23,10 +23,11 @@
 #include "core/page/Page.h"
 #include "modules/fetch/Body.h"
 #include "modules/fetch/BodyStreamBuffer.h"
-#include "modules/fetch/CompositeDataConsumerHandle.h"
+#include "modules/fetch/BytesConsumer.h"
+#include "modules/fetch/BytesConsumerForDataConsumerHandle.h"
 #include "modules/fetch/DataConsumerHandleUtil.h"
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
 #include "modules/fetch/FetchRequestData.h"
+#include "modules/fetch/FormDataBytesConsumer.h"
 #include "modules/fetch/Response.h"
 #include "modules/fetch/ResponseInit.h"
 #include "platform/HTTPNames.h"
@@ -51,6 +52,104 @@
     return (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307 || statusCode == 308);
 }
 
+class SRIBytesConsumer final : public BytesConsumer {
+public:
+    // BytesConsumer implementation
+    Result beginRead(const char** buffer, size_t* available) override
+    {
+        if (!m_underlying) {
+            *buffer = nullptr;
+            *available = 0;
+            return m_isCancelled ? Result::Done : Result::ShouldWait;
+        }
+        return m_underlying->beginRead(buffer, available);
+    }
+    Result endRead(size_t readSize) override
+    {
+        DCHECK(m_underlying);
+        return m_underlying->endRead(readSize);
+    }
+    PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy policy) override
+    {
+        return m_underlying ? m_underlying->drainAsBlobDataHandle(policy) : nullptr;
+    }
+    PassRefPtr<EncodedFormData> drainAsFormData() override
+    {
+        return m_underlying ? m_underlying->drainAsFormData() : nullptr;
+    }
+    void setClient(BytesConsumer::Client* client) override
+    {
+        DCHECK(!m_client);
+        DCHECK(client);
+        if (m_underlying)
+            m_underlying->setClient(client);
+        else
+            m_client = client;
+    }
+    void clearClient() override
+    {
+        if (m_underlying)
+            m_underlying->clearClient();
+        else
+            m_client = nullptr;
+    }
+    void cancel() override
+    {
+        if (m_underlying) {
+            m_underlying->cancel();
+        } else {
+            m_isCancelled = true;
+            m_client = nullptr;
+        }
+    }
+    PublicState getPublicState() const override
+    {
+        return m_underlying ? m_underlying->getPublicState() : m_isCancelled ? PublicState::Closed : PublicState::ReadableOrWaiting;
+    }
+    Error getError() const override
+    {
+        DCHECK(m_underlying);
+        // We must not be in the errored state until we get updated.
+        return m_underlying->getError();
+    }
+    String debugName() const override
+    {
+        return "SRIBytesConsumer";
+    }
+
+    // This function can be called at most once.
+    void update(BytesConsumer* consumer)
+    {
+        DCHECK(!m_underlying);
+        if (m_isCancelled) {
+            // This consumer has already been closed.
+            return;
+        }
+
+        m_underlying = consumer;
+        if (m_client) {
+            Client* client = m_client;
+            m_client = nullptr;
+            m_underlying->setClient(client);
+            if (getPublicState() != PublicState::ReadableOrWaiting)
+                client->onStateChange();
+        }
+    }
+
+    DEFINE_INLINE_TRACE()
+    {
+        visitor->trace(m_underlying);
+        visitor->trace(m_client);
+        BytesConsumer::trace(visitor);
+    }
+
+private:
+    Member<BytesConsumer> m_underlying;
+    Member<Client> m_client;
+    bool m_isCancelled = false;
+};
+
+
 } // namespace
 
 class FetchManager::Loader final : public GarbageCollectedFinalized<FetchManager::Loader>, public ThreadableLoaderClient {
@@ -80,7 +179,7 @@
         // SRIVerifier takes ownership of |handle| and |response|.
         // |updater| must be garbage collected. The other arguments
         // all must have the lifetime of the give loader.
-        SRIVerifier(std::unique_ptr<WebDataConsumerHandle> handle, CompositeDataConsumerHandle::Updater* updater, Response* response, FetchManager::Loader* loader, String integrityMetadata, const KURL& url)
+        SRIVerifier(std::unique_ptr<WebDataConsumerHandle> handle, SRIBytesConsumer* updater, Response* response, FetchManager::Loader* loader, String integrityMetadata, const KURL& url)
             : m_handle(std::move(handle))
             , m_updater(updater)
             , m_response(response)
@@ -114,7 +213,7 @@
             m_finished = true;
             if (r == WebDataConsumerHandle::Done) {
                 if (SubresourceIntegrity::CheckSubresourceIntegrity(m_integrityMetadata, m_buffer.data(), m_buffer.size(), m_url, *m_loader->document(), errorMessage)) {
-                    m_updater->update(FetchFormDataConsumerHandle::create(m_buffer.data(), m_buffer.size()));
+                    m_updater->update(new FormDataBytesConsumer(m_buffer.data(), m_buffer.size()));
                     m_loader->m_resolver->resolve(m_response);
                     m_loader->m_resolver.clear();
                     // FetchManager::Loader::didFinishLoading() can
@@ -128,7 +227,7 @@
                     return;
                 }
             }
-            m_updater->update(createUnexpectedErrorDataConsumerHandle());
+            m_updater->update(new BytesConsumerForDataConsumerHandle(m_response->getExecutionContext(), createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle())));
             m_loader->performNetworkError(errorMessage);
         }
 
@@ -142,7 +241,7 @@
         }
     private:
         std::unique_ptr<WebDataConsumerHandle> m_handle;
-        Member<CompositeDataConsumerHandle::Updater> m_updater;
+        Member<SRIBytesConsumer> m_updater;
         // We cannot store a Response because its JS wrapper can be collected.
         // TODO(yhirano): Fix this.
         Member<Response> m_response;
@@ -296,11 +395,13 @@
     }
 
     FetchResponseData* responseData = nullptr;
-    CompositeDataConsumerHandle::Updater* updater = nullptr;
-    if (m_request->integrity().isEmpty())
+    SRIBytesConsumer* sriConsumer = nullptr;
+    if (m_request->integrity().isEmpty()) {
         responseData = FetchResponseData::createWithBuffer(new BodyStreamBuffer(scriptState, createFetchDataConsumerHandleFromWebHandle(std::move(handle))));
-    else
-        responseData = FetchResponseData::createWithBuffer(new BodyStreamBuffer(scriptState, createFetchDataConsumerHandleFromWebHandle(CompositeDataConsumerHandle::create(createWaitingDataConsumerHandle(), &updater))));
+    } else {
+        sriConsumer = new SRIBytesConsumer();
+        responseData = FetchResponseData::createWithBuffer(new BodyStreamBuffer(scriptState, sriConsumer));
+    }
     responseData->setStatus(response.httpStatusCode());
     responseData->setStatusMessage(response.httpStatusText());
     for (auto& it : response.httpHeaderFields())
@@ -365,7 +466,7 @@
         m_resolver.clear();
     } else {
         ASSERT(!m_integrityVerifier);
-        m_integrityVerifier = new SRIVerifier(std::move(handle), updater, r, this, m_request->integrity(), response.url());
+        m_integrityVerifier = new SRIVerifier(std::move(handle), sriConsumer, r, this, m_request->integrity(), response.url());
     }
 }
 
diff --git a/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp b/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp
index 811ef0d..aefa1e0 100644
--- a/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp
+++ b/third_party/WebKit/Source/modules/fetch/FetchRequestData.cpp
@@ -9,9 +9,9 @@
 #include "core/fetch/ResourceLoaderOptions.h"
 #include "core/loader/ThreadableLoader.h"
 #include "modules/credentialmanager/PasswordCredential.h"
+#include "modules/fetch/BlobBytesConsumer.h"
 #include "modules/fetch/BodyStreamBuffer.h"
 #include "modules/fetch/DataConsumerHandleUtil.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
 #include "modules/fetch/FetchHeaderList.h"
 #include "platform/HTTPNames.h"
 #include "platform/network/ResourceRequest.h"
@@ -33,7 +33,7 @@
     for (HTTPHeaderMap::const_iterator it = webRequest.headers().begin(); it != webRequest.headers().end(); ++it)
         request->m_headerList->append(it->key, it->value);
     if (webRequest.blobDataHandle())
-        request->setBuffer(new BodyStreamBuffer(scriptState, FetchBlobDataConsumerHandle::create(scriptState->getExecutionContext(), webRequest.blobDataHandle())));
+        request->setBuffer(new BodyStreamBuffer(scriptState, new BlobBytesConsumer(scriptState->getExecutionContext(), webRequest.blobDataHandle())));
     request->setContext(webRequest.requestContext());
     request->setReferrer(Referrer(webRequest.referrerUrl().string(), static_cast<ReferrerPolicy>(webRequest.referrerPolicy())));
     request->setMode(webRequest.mode());
diff --git a/third_party/WebKit/Source/modules/fetch/Request.cpp b/third_party/WebKit/Source/modules/fetch/Request.cpp
index 08aff7d0..62ca634 100644
--- a/third_party/WebKit/Source/modules/fetch/Request.cpp
+++ b/third_party/WebKit/Source/modules/fetch/Request.cpp
@@ -12,7 +12,6 @@
 #include "core/loader/ThreadableLoader.h"
 #include "modules/fetch/BodyStreamBuffer.h"
 #include "modules/fetch/DataConsumerHandleUtil.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
 #include "modules/fetch/FetchManager.h"
 #include "modules/fetch/RequestInit.h"
 #include "platform/HTTPNames.h"
diff --git a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
index 6b2d3c5..faad8ce 100644
--- a/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
+++ b/third_party/WebKit/Source/modules/fetch/RequestInit.cpp
@@ -15,8 +15,8 @@
 #include "core/dom/URLSearchParams.h"
 #include "core/fileapi/Blob.h"
 #include "core/html/FormData.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
+#include "modules/fetch/BlobBytesConsumer.h"
+#include "modules/fetch/FormDataBytesConsumer.h"
 #include "modules/fetch/Headers.h"
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/blob/BlobData.h"
@@ -110,26 +110,26 @@
         return;
 
     if (v8Body->IsArrayBuffer()) {
-        body = FetchFormDataConsumerHandle::create(V8ArrayBuffer::toImpl(v8Body.As<v8::Object>()));
+        body = new FormDataBytesConsumer(V8ArrayBuffer::toImpl(v8Body.As<v8::Object>()));
     } else if (v8Body->IsArrayBufferView()) {
-        body = FetchFormDataConsumerHandle::create(V8ArrayBufferView::toImpl(v8Body.As<v8::Object>()));
+        body = new FormDataBytesConsumer(V8ArrayBufferView::toImpl(v8Body.As<v8::Object>()));
     } else if (V8Blob::hasInstance(v8Body, isolate)) {
         RefPtr<BlobDataHandle> blobDataHandle = V8Blob::toImpl(v8Body.As<v8::Object>())->blobDataHandle();
         contentType = blobDataHandle->type();
-        body = FetchBlobDataConsumerHandle::create(context, blobDataHandle.release());
+        body = new BlobBytesConsumer(context, blobDataHandle.release());
     } else if (V8FormData::hasInstance(v8Body, isolate)) {
         RefPtr<EncodedFormData> formData = V8FormData::toImpl(v8Body.As<v8::Object>())->encodeMultiPartFormData();
         // Here we handle formData->boundary() as a C-style string. See
         // FormDataEncoder::generateUniqueBoundaryString.
         contentType = AtomicString("multipart/form-data; boundary=") + formData->boundary().data();
-        body = FetchFormDataConsumerHandle::create(context, formData.release());
+        body = new FormDataBytesConsumer(context, formData.release());
     } else if (V8URLSearchParams::hasInstance(v8Body, isolate)) {
         RefPtr<EncodedFormData> formData = V8URLSearchParams::toImpl(v8Body.As<v8::Object>())->toEncodedFormData();
         contentType = AtomicString("application/x-www-form-urlencoded;charset=UTF-8");
-        body = FetchFormDataConsumerHandle::create(context, formData.release());
+        body = new FormDataBytesConsumer(context, formData.release());
     } else if (v8Body->IsString()) {
         contentType = "text/plain;charset=UTF-8";
-        body = FetchFormDataConsumerHandle::create(toUSVString(isolate, v8Body, exceptionState));
+        body = new FormDataBytesConsumer(toUSVString(isolate, v8Body, exceptionState));
     }
 }
 
diff --git a/third_party/WebKit/Source/modules/fetch/RequestInit.h b/third_party/WebKit/Source/modules/fetch/RequestInit.h
index 593f713..99094215 100644
--- a/third_party/WebKit/Source/modules/fetch/RequestInit.h
+++ b/third_party/WebKit/Source/modules/fetch/RequestInit.h
@@ -15,8 +15,8 @@
 
 namespace blink {
 
+class BytesConsumer;
 class ExceptionState;
-class FetchDataConsumerHandle;
 class Headers;
 
 // FIXME: Use IDL dictionary instead of this class.
@@ -29,7 +29,7 @@
     Member<Headers> headers;
     Dictionary headersDictionary;
     String contentType;
-    std::unique_ptr<FetchDataConsumerHandle> body;
+    Member<BytesConsumer> body;
     Referrer referrer;
     String mode;
     String credentials;
diff --git a/third_party/WebKit/Source/modules/fetch/Response.cpp b/third_party/WebKit/Source/modules/fetch/Response.cpp
index 356e6b6b..ff894600a 100644
--- a/third_party/WebKit/Source/modules/fetch/Response.cpp
+++ b/third_party/WebKit/Source/modules/fetch/Response.cpp
@@ -20,10 +20,10 @@
 #include "core/fileapi/Blob.h"
 #include "core/html/FormData.h"
 #include "core/streams/ReadableStreamOperations.h"
+#include "modules/fetch/BlobBytesConsumer.h"
 #include "modules/fetch/BodyStreamBuffer.h"
 #include "modules/fetch/DataConsumerHandleUtil.h"
-#include "modules/fetch/FetchBlobDataConsumerHandle.h"
-#include "modules/fetch/FetchFormDataConsumerHandle.h"
+#include "modules/fetch/FormDataBytesConsumer.h"
 #include "modules/fetch/ReadableStreamDataConsumerHandle.h"
 #include "modules/fetch/ResponseInit.h"
 #include "platform/network/EncodedFormData.h"
@@ -54,7 +54,7 @@
         response->headerList()->append(i->key, i->value);
     }
 
-    response->replaceBodyStreamBuffer(new BodyStreamBuffer(scriptState, FetchBlobDataConsumerHandle::create(scriptState->getExecutionContext(), webResponse.blobDataHandle())));
+    response->replaceBodyStreamBuffer(new BodyStreamBuffer(scriptState, new BlobBytesConsumer(scriptState->getExecutionContext(), webResponse.blobDataHandle())));
 
     // Filter the response according to |webResponse|'s ResponseType.
     switch (webResponse.responseType()) {
@@ -132,21 +132,21 @@
         // https://crbug.com/335871.
     } else if (V8Blob::hasInstance(body, isolate)) {
         Blob* blob = V8Blob::toImpl(body.As<v8::Object>());
-        bodyBuffer = new BodyStreamBuffer(scriptState, FetchBlobDataConsumerHandle::create(executionContext, blob->blobDataHandle()));
+        bodyBuffer = new BodyStreamBuffer(scriptState, new BlobBytesConsumer(executionContext, blob->blobDataHandle()));
         contentType = blob->type();
     } else if (body->IsArrayBuffer()) {
-        bodyBuffer = new BodyStreamBuffer(scriptState, FetchFormDataConsumerHandle::create(V8ArrayBuffer::toImpl(body.As<v8::Object>())));
+        bodyBuffer = new BodyStreamBuffer(scriptState, new FormDataBytesConsumer(V8ArrayBuffer::toImpl(body.As<v8::Object>())));
     } else if (body->IsArrayBufferView()) {
-        bodyBuffer = new BodyStreamBuffer(scriptState, FetchFormDataConsumerHandle::create(V8ArrayBufferView::toImpl(body.As<v8::Object>())));
+        bodyBuffer = new BodyStreamBuffer(scriptState, new FormDataBytesConsumer(V8ArrayBufferView::toImpl(body.As<v8::Object>())));
     } else if (V8FormData::hasInstance(body, isolate)) {
         RefPtr<EncodedFormData> formData = V8FormData::toImpl(body.As<v8::Object>())->encodeMultiPartFormData();
         // Here we handle formData->boundary() as a C-style string. See
         // FormDataEncoder::generateUniqueBoundaryString.
         contentType = AtomicString("multipart/form-data; boundary=") + formData->boundary().data();
-        bodyBuffer = new BodyStreamBuffer(scriptState, FetchFormDataConsumerHandle::create(executionContext, formData.release()));
+        bodyBuffer = new BodyStreamBuffer(scriptState, new FormDataBytesConsumer(executionContext, formData.release()));
     } else if (V8URLSearchParams::hasInstance(body, isolate)) {
         RefPtr<EncodedFormData> formData = V8URLSearchParams::toImpl(body.As<v8::Object>())->toEncodedFormData();
-        bodyBuffer = new BodyStreamBuffer(scriptState, FetchFormDataConsumerHandle::create(executionContext, formData.release()));
+        bodyBuffer = new BodyStreamBuffer(scriptState, new FormDataBytesConsumer(executionContext, formData.release()));
         contentType = "application/x-www-form-urlencoded;charset=UTF-8";
     } else if (ReadableStreamOperations::isReadableStream(scriptState, bodyValue)) {
         bodyBuffer = new BodyStreamBuffer(scriptState, bodyValue);
@@ -154,7 +154,7 @@
         String string = toUSVString(isolate, body, exceptionState);
         if (exceptionState.hadException())
             return nullptr;
-        bodyBuffer = new BodyStreamBuffer(scriptState, FetchFormDataConsumerHandle::create(string));
+        bodyBuffer = new BodyStreamBuffer(scriptState, new FormDataBytesConsumer(string));
         contentType = "text/plain;charset=UTF-8";
     }
     Response* response = create(scriptState, bodyBuffer, contentType, ResponseInit(init, exceptionState), exceptionState);
diff --git a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
index a79e321..063d01b 100644
--- a/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
+++ b/third_party/WebKit/Source/modules/remoteplayback/RemotePlayback.cpp
@@ -5,6 +5,7 @@
 #include "modules/remoteplayback/RemotePlayback.h"
 
 #include "bindings/core/v8/ScriptPromiseResolver.h"
+#include "core/HTMLNames.h"
 #include "core/dom/DOMException.h"
 #include "core/dom/Document.h"
 #include "core/events/Event.h"
@@ -82,11 +83,16 @@
 
 ScriptPromise RemotePlayback::prompt(ScriptState* scriptState)
 {
-    // TODO(avayvod): implement steps 3, 4, 5, 8, 9 of the algorithm.
+    // TODO(avayvod): implement steps 4, 5, 8, 9 of the algorithm.
     // https://crbug.com/647441
     ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
     ScriptPromise promise = resolver->promise();
 
+    if (m_mediaElement->fastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
+        resolver->reject(DOMException::create(InvalidStateError, "disableRemotePlayback attribute is present."));
+        return promise;
+    }
+
     // TODO(avayvod): should we have a separate flag to disable the user gesture
     // requirement (for tests) or reuse the one for the PresentationRequest::start()?
     if (!UserGestureIndicator::utilizeUserGesture()) {
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py
index 33feda9..29620fb 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/git.py
@@ -288,8 +288,8 @@
     # These methods are git specific and are meant to provide support for the Git oriented workflow
     # that Blink is moving towards, hence there are no equivalent methods in the SVN class.
 
-    def pull(self):
-        self._run_git(['pull'])
+    def pull(self, timeout_seconds=None):
+        self._run_git(['pull'], timeout_seconds=timeout_seconds)
 
     def latest_git_commit(self):
         return self._run_git(['log', '-1', '--format=%H']).strip()
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
index 4778916..d4bba36 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/checkout/scm/scm.py
@@ -50,11 +50,22 @@
         self.checkout_root = self.find_checkout_root(self.cwd)
 
     # A wrapper used by subclasses to create processes.
-    def _run(self, args, cwd=None, input=None, error_handler=None, return_exit_code=False, return_stderr=True, decode_output=True):
+    def _run(self,
+             args,
+             cwd=None,
+             # pylint: disable=W0622
+             # redefining built-in
+             input=None,
+             timeout_seconds=None,
+             error_handler=None,
+             return_exit_code=False,
+             return_stderr=True,
+             decode_output=True):
         # FIXME: We should set cwd appropriately.
         return self._executive.run_command(args,
                                            cwd=cwd,
                                            input=input,
+                                           timeout_seconds=timeout_seconds,
                                            error_handler=error_handler,
                                            return_exit_code=return_exit_code,
                                            return_stderr=return_stderr,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py
index cfe05da..fa1fcec4 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive.py
@@ -36,6 +36,7 @@
 import subprocess
 import sys
 import time
+import threading
 
 from webkitpy.common.system.outputtee import Tee
 from webkitpy.common.system.filesystem import FileSystem
@@ -350,6 +351,7 @@
                     cwd=None,
                     env=None,
                     input=None,
+                    timeout_seconds=None,
                     error_handler=None,
                     return_exit_code=False,
                     return_stderr=True,
@@ -368,6 +370,11 @@
                              cwd=cwd,
                              env=env,
                              close_fds=self._should_close_fds())
+
+        if timeout_seconds:
+            timer = threading.Timer(timeout_seconds, process.kill)
+            timer.start()
+
         output = process.communicate(string_to_communicate)[0]
 
         # run_command automatically decodes to unicode() unless explicitly told not to.
@@ -378,6 +385,9 @@
         # http://bugs.python.org/issue1731717
         exit_code = process.wait()
 
+        if timeout_seconds:
+            timer.cancel()
+
         if debug_logging:
             _log.debug('"%s" took %.2fs', self.command_for_printing(args), time.time() - start_time)
 
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py
index ea83b92..24afeac 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_mock.py
@@ -95,6 +95,9 @@
                     args,
                     cwd=None,
                     input=None,
+                    # pylint: disable=W0613
+                    # unused argument
+                    timeout_seconds=None,
                     error_handler=None,
                     return_exit_code=False,
                     return_stderr=True,
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_unittest.py
index 9d54ac7..5b8ecc0 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_unittest.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/common/system/executive_unittest.py
@@ -167,6 +167,22 @@
         # Killing again should fail silently.
         executive.kill_process(process.pid)
 
+    def test_timeout_exceeded(self):
+        executive = Executive()
+
+        def timeout():
+            executive.run_command(command_line('sleep', 'infinity'), timeout_seconds=0.01)
+        self.assertRaises(ScriptError, timeout)
+
+    def test_timeout_exceeded_exit_code(self):
+        executive = Executive()
+        exit_code = executive.run_command(command_line('sleep', 'infinity'), timeout_seconds=0.01, return_exit_code=True)
+        self.assertNotEqual(exit_code, 0)
+
+    def test_timeout_satisfied(self):
+        executive = Executive()
+        executive.run_command(command_line('sleep', '0'), timeout_seconds=1000)
+
     def _assert_windows_image_name(self, name, expected_windows_name):
         executive = Executive()
         windows_name = executive._windows_image_name(name)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py
index 8177691..f73d641 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/bot/commit_announcer.py
@@ -39,6 +39,7 @@
 CHANNEL = "#blink"
 NICKNAME = "commit-bot"
 
+PULL_TIMEOUT_SECONDS = 60 * 5
 UPDATE_WAIT_SECONDS = 10
 RETRY_ATTEMPTS = 8
 
@@ -136,7 +137,7 @@
                 time.sleep(wait)
                 _log.info('Pull attempt %s out of %s', attempts, RETRY_ATTEMPTS)
             try:
-                self.git.pull()
+                self.git.pull(timeout_seconds=PULL_TIMEOUT_SECONDS)
                 return True
             except ScriptError as e:
                 _log.error('Error pulling from server: %s', e)
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index bc4e34f6..9f445125 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -803,7 +803,6 @@
 }
 
 #search-box input {
-  cursor: default;
   display: inline-block;
   transition: width 0.2s ease;
   width: 0;