diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc
index c873dc4f..369ff26 100644
--- a/ash/ash_switches.cc
+++ b/ash/ash_switches.cc
@@ -30,14 +30,6 @@
 // Enable keyboard shortcuts used by developers only.
 const char kAshDeveloperShortcuts[] = "ash-dev-shortcuts";
 
-// Disables the window backdrops normally used in maximize mode (TouchView).
-const char kAshDisableMaximizeModeWindowBackdrop[] =
-    "ash-disable-maximize-mode-window-backdrop";
-
-// Disable the support for WebContents to lock the screen orientation.
-const char kAshDisableScreenOrientationLock[] =
-    "ash-disable-screen-orientation-lock";
-
 // Disable the Touch Exploration Mode. Touch Exploration Mode will no longer be
 // turned on automatically when spoken feedback is enabled when this flag is
 // set.
diff --git a/ash/ash_switches.h b/ash/ash_switches.h
index f26d1310..4fc51f54 100644
--- a/ash/ash_switches.h
+++ b/ash/ash_switches.h
@@ -20,8 +20,6 @@
 ASH_EXPORT extern const char kAshCopyHostBackgroundAtBoot[];
 ASH_EXPORT extern const char kAshDebugShortcuts[];
 ASH_EXPORT extern const char kAshDeveloperShortcuts[];
-ASH_EXPORT extern const char kAshDisableMaximizeModeWindowBackdrop[];
-ASH_EXPORT extern const char kAshDisableScreenOrientationLock[];
 ASH_EXPORT extern const char kAshDisableSmoothScreenRotation[];
 ASH_EXPORT extern const char kAshDisableTouchExplorationMode[];
 ASH_EXPORT extern const char kAshEnableMagnifierKeyScroller[];
diff --git a/ash/display/screen_orientation_controller_chromeos.cc b/ash/display/screen_orientation_controller_chromeos.cc
index 0040a53..0428d03a 100644
--- a/ash/display/screen_orientation_controller_chromeos.cc
+++ b/ash/display/screen_orientation_controller_chromeos.cc
@@ -215,10 +215,8 @@
 
 bool ScreenOrientationController::ScreenOrientationProviderSupported() const {
   return Shell::Get()
-             ->maximize_mode_controller()
-             ->IsMaximizeModeWindowManagerEnabled() &&
-         !base::CommandLine::ForCurrentProcess()->HasSwitch(
-             switches::kAshDisableScreenOrientationLock);
+      ->maximize_mode_controller()
+      ->IsMaximizeModeWindowManagerEnabled();
 }
 
 void ScreenOrientationController::ToggleUserRotationLock() {
diff --git a/ash/wm/maximize_mode/maximize_mode_window_manager.cc b/ash/wm/maximize_mode/maximize_mode_window_manager.cc
index 4a053c8..05b9c74 100644
--- a/ash/wm/maximize_mode/maximize_mode_window_manager.cc
+++ b/ash/wm/maximize_mode/maximize_mode_window_manager.cc
@@ -310,12 +310,6 @@
 
 void MaximizeModeWindowManager::EnableBackdropBehindTopWindowOnEachDisplay(
     bool enable) {
-  // This function should be a no-op if backdrops have been disabled.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAshDisableMaximizeModeWindowBackdrop)) {
-    return;
-  }
-
   if (backdrops_hidden_)
     return;
 
diff --git a/ash/wm/workspace/workspace_layout_manager_keyboard_unittest.cc b/ash/wm/workspace/workspace_layout_manager_keyboard_unittest.cc
index 478425f..db3ba59 100644
--- a/ash/wm/workspace/workspace_layout_manager_keyboard_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_keyboard_unittest.cc
@@ -18,7 +18,6 @@
 #include "ash/shell_port.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/fullscreen_window_finder.h"
-#include "ash/wm/maximize_mode/workspace_backdrop_delegate.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
diff --git a/chrome/VERSION b/chrome/VERSION
index 12c2345..0445841b 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=60
 MINOR=0
-BUILD=3100
+BUILD=3101
 PATCH=0
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 15b70802..08f0858 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1333,13 +1333,6 @@
         flag_descriptions::kDisplayColorCalibrationDescription, kOsCrOS,
         SINGLE_DISABLE_VALUE_TYPE(::switches::kDisableDisplayColorCalibration),
     },
-    {
-        "ash-disable-screen-orientation-lock",
-        flag_descriptions::kAshScreenOrientationLockName,
-        flag_descriptions::kAshScreenOrientationLockDescription, kOsCrOS,
-        SINGLE_DISABLE_VALUE_TYPE(
-            ash::switches::kAshDisableScreenOrientationLock),
-    },
     {"enable-tether", flag_descriptions::kTetherName,
      flag_descriptions::kTetherDescription, kOsCrOS,
      SINGLE_VALUE_TYPE(chromeos::switches::kEnableTether)},
@@ -1365,13 +1358,6 @@
         SINGLE_VALUE_TYPE(ash::switches::kAshDebugShortcuts),
     },
     {
-        "ash-disable-maximize-mode-window-backdrop",
-        flag_descriptions::kAshMaximizeModeWindowBackdropName,
-        flag_descriptions::kAshMaximizeModeWindowBackdropDescription, kOsCrOS,
-        SINGLE_DISABLE_VALUE_TYPE(
-            ash::switches::kAshDisableMaximizeModeWindowBackdrop),
-    },
-    {
         "ash-enable-mirrored-screen",
         flag_descriptions::kAshEnableMirroredScreenName,
         flag_descriptions::kAshEnableMirroredScreenDescription, kOsCrOS,
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index cbd1887..635a4c3 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -700,18 +700,6 @@
 
 const char kAshShelfColorSchemeDarkMuted[] = "Dark & Muted";
 
-const char kAshMaximizeModeWindowBackdropName[] =
-    "Window backdrops in TouchView";
-
-const char kAshMaximizeModeWindowBackdropDescription[] =
-    "Show grey window backdrops used in TouchView (maximize mode) behind "
-    "windows which cannot be maximized.";
-
-const char kAshScreenOrientationLockName[] = "Screen Orientation locking";
-
-const char kAshScreenOrientationLockDescription[] =
-    "Allows javascript to lock the screen orienation.";
-
 const char kAshEnableMirroredScreenName[] = "Enable mirrored screen mode.";
 
 const char kAshEnableMirroredScreenDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 32dfac8..bff4570 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -369,12 +369,6 @@
 extern const char kAshShelfColorSchemeNormalMuted[];
 extern const char kAshShelfColorSchemeDarkMuted[];
 
-extern const char kAshMaximizeModeWindowBackdropName[];
-extern const char kAshMaximizeModeWindowBackdropDescription[];
-
-extern const char kAshScreenOrientationLockName[];
-extern const char kAshScreenOrientationLockDescription[];
-
 extern const char kAshEnableMirroredScreenName[];
 extern const char kAshEnableMirroredScreenDescription[];
 
diff --git a/chrome/browser/resources/md_bookmarks/command_manager.html b/chrome/browser/resources/md_bookmarks/command_manager.html
index 2ec008d..c2391bba 100644
--- a/chrome/browser/resources/md_bookmarks/command_manager.html
+++ b/chrome/browser/resources/md_bookmarks/command_manager.html
@@ -3,29 +3,23 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
 <link rel="import" href="chrome://bookmarks/edit_dialog.html">
+<link rel="import" href="chrome://bookmarks/shared_style.html">
 <link rel="import" href="chrome://bookmarks/store_client.html">
 
 <dom-module id="bookmarks-command-manager">
   <template>
+    <style include="shared-style"></style>
     <dialog is="cr-action-menu" id="dropdown" on-mousedown="onMenuMousedown_">
-      <button class="dropdown-item"
-          command="edit"
-          hidden$="[[!canExecute('edit', menuIds_)]]"
-          on-tap="onCommandClick_">
-        [[getEditActionLabel_(menuIds_)]]
-      </button>
-      <button class="dropdown-item"
-          command="copy"
-          hidden$="[[!canExecute('copy', menuIds_)]]"
-          on-tap="onCommandClick_">
-        $i18n{menuCopyURL}
-      </button>
-      <button class="dropdown-item"
-          command="delete"
-          hidden$="[[!canExecute('delete', menuIds_)]]"
-          on-tap="onCommandClick_">
-        $i18n{menuDelete}
-      </button>
+      <template is="dom-repeat" items="[[menuCommands_]]" as="command">
+        <button class="dropdown-item"
+            command$="[[command]]"
+            hidden$="[[!isCommandVisible_(command, menuIds_)]]"
+            disabled$="[[!isCommandEnabled_(command, menuIds_)]]"
+            on-tap="onCommandClick_">
+          [[getCommandLabel_(command, menuIds_)]]
+        </button>
+        <hr hidden$="[[!showDividerAfter_(command)]]"></hr>
+      </template>
     </dialog>
     <template is="cr-lazy-render" id="editDialog">
       <bookmarks-edit-dialog></bookmarks-edit-dialog>
diff --git a/chrome/browser/resources/md_bookmarks/command_manager.js b/chrome/browser/resources/md_bookmarks/command_manager.js
index a21c9c4..9cf612e 100644
--- a/chrome/browser/resources/md_bookmarks/command_manager.js
+++ b/chrome/browser/resources/md_bookmarks/command_manager.js
@@ -2,219 +2,394 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-Polymer({
-  is: 'bookmarks-command-manager',
+/**
+ * @fileoverview Element which shows context menus and handles keyboard
+ * shortcuts.
+ */
+cr.define('bookmarks', function() {
 
-  behaviors: [
-    bookmarks.StoreClient,
-  ],
+  var CommandManager = Polymer({
+    is: 'bookmarks-command-manager',
 
-  properties: {
-    /** @type {Set<string>} */
-    menuIds_: Object,
-  },
+    behaviors: [
+      bookmarks.StoreClient,
+    ],
 
-  attached: function() {
-    /** @private {function(!Event)} */
-    this.boundOnOpenItemMenu_ = this.onOpenItemMenu_.bind(this);
-    document.addEventListener('open-item-menu', this.boundOnOpenItemMenu_);
+    properties: {
+      /** @private {!Array<Command>} */
+      menuCommands_: {
+        type: Array,
+        value: function() {
+          return [
+            Command.EDIT,
+            Command.COPY,
+            Command.DELETE,
+            // <hr>
+            Command.OPEN_NEW_TAB,
+            Command.OPEN_NEW_WINDOW,
+            Command.OPEN_INCOGNITO,
+          ];
+        },
+      },
 
-    /** @private {function(!Event)} */
-    this.boundOnKeydown_ = this.onKeydown_.bind(this);
-    document.addEventListener('keydown', this.boundOnKeydown_);
+      /** @type {Set<string>} */
+      menuIds_: Object,
+    },
 
-    /** @private {Object<Command, string>} */
-    this.shortcuts_ = {};
-    this.shortcuts_[Command.EDIT] = cr.isMac ? 'enter' : 'f2';
-    this.shortcuts_[Command.COPY] = cr.isMac ? 'meta+c' : 'ctrl+c';
-    this.shortcuts_[Command.DELETE] = cr.isMac ? 'delete backspace' : 'delete';
-  },
+    attached: function() {
+      assert(CommandManager.instance_ == null);
+      CommandManager.instance_ = this;
 
-  detached: function() {
-    document.removeEventListener('open-item-menu', this.boundOnOpenItemMenu_);
-    document.removeEventListener('keydown', this.boundOnKeydown_);
-  },
+      /** @private {function(!Event)} */
+      this.boundOnOpenItemMenu_ = this.onOpenItemMenu_.bind(this);
+      document.addEventListener('open-item-menu', this.boundOnOpenItemMenu_);
 
-  /**
-   * Display the command context menu at (|x|, |y|) in window co-ordinates.
-   * Commands will execute on the currently selected items.
-   * @param {number} x
-   * @param {number} y
-   */
-  openCommandMenuAtPosition: function(x, y) {
-    this.menuIds_ = this.getState().selection.items;
-    /** @type {!CrActionMenuElement} */ (this.$.dropdown)
-        .showAtPosition({top: y, left: x});
-  },
+      /** @private {function(!Event)} */
+      this.boundOnKeydown_ = this.onKeydown_.bind(this);
+      document.addEventListener('keydown', this.boundOnKeydown_);
 
-  /**
-   * Display the command context menu positioned to cover the |target|
-   * element. Commands will execute on the currently selected items.
-   * @param {!Element} target
-   */
-  openCommandMenuAtElement: function(target) {
-    this.menuIds_ = this.getState().selection.items;
-    /** @type {!CrActionMenuElement} */ (this.$.dropdown).showAt(target);
-  },
+      /** @private {Object<Command, string>} */
+      this.shortcuts_ = {};
+      this.shortcuts_[Command.EDIT] = cr.isMac ? 'enter' : 'f2';
+      this.shortcuts_[Command.COPY] = cr.isMac ? 'meta+c' : 'ctrl+c';
+      this.shortcuts_[Command.DELETE] =
+          cr.isMac ? 'delete backspace' : 'delete';
+      this.shortcuts_[Command.OPEN_NEW_TAB] =
+          cr.isMac ? 'meta+enter' : 'ctrl+enter';
+      this.shortcuts_[Command.OPEN_NEW_WINDOW] = 'shift+enter';
+    },
 
-  closeCommandMenu: function() {
-    /** @type {!CrActionMenuElement} */ (this.$.dropdown).close();
-  },
+    detached: function() {
+      CommandManager.instance_ = null;
+      document.removeEventListener('open-item-menu', this.boundOnOpenItemMenu_);
+      document.removeEventListener('keydown', this.boundOnKeydown_);
+    },
 
-  ////////////////////////////////////////////////////////////////////////////
-  // Command handlers:
+    /**
+     * Display the command context menu at (|x|, |y|) in window co-ordinates.
+     * Commands will execute on the currently selected items.
+     * @param {number} x
+     * @param {number} y
+     */
+    openCommandMenuAtPosition: function(x, y) {
+      this.menuIds_ = this.getState().selection.items;
+      /** @type {!CrActionMenuElement} */ (this.$.dropdown)
+          .showAtPosition({top: y, left: x});
+    },
 
-  /**
-   * @param {Command} command
-   * @param {!Set<string>} itemIds
-   * @return {boolean}
-   */
-  canExecute: function(command, itemIds) {
-    switch (command) {
-      case Command.EDIT:
-        return itemIds.size == 1;
-      case Command.COPY:
-        return itemIds.size == 1 &&
-            this.containsMatchingNode_(itemIds, function(node) {
-              return !!node.url;
-            });
-      case Command.DELETE:
-        return itemIds.size > 0;
-      default:
-        return false;
-    }
-  },
+    /**
+     * Display the command context menu positioned to cover the |target|
+     * element. Commands will execute on the currently selected items.
+     * @param {!Element} target
+     */
+    openCommandMenuAtElement: function(target) {
+      this.menuIds_ = this.getState().selection.items;
+      /** @type {!CrActionMenuElement} */ (this.$.dropdown).showAt(target);
+    },
 
-  /**
-   * @param {Command} command
-   * @param {!Set<string>} itemIds
-   */
-  handle: function(command, itemIds) {
-    switch (command) {
-      case Command.EDIT:
-        var id = Array.from(itemIds)[0];
-        /** @type {!BookmarksEditDialogElement} */ (this.$.editDialog.get())
-            .showEditDialog(this.getState().nodes[id]);
-        break;
-      case Command.COPY:
-        var idList = Array.from(itemIds);
-        chrome.bookmarkManagerPrivate.copy(idList, function() {
-          // TODO(jiaxi): Add toast later.
-        });
-        break;
-      case Command.DELETE:
-        chrome.bookmarkManagerPrivate.removeTrees(
-            Array.from(this.minimizeDeletionSet_(itemIds)), function() {
-              // TODO(jiaxi): Add toast later.
-            });
-        break;
-    }
-  },
+    closeCommandMenu: function() {
+      /** @type {!CrActionMenuElement} */ (this.$.dropdown).close();
+    },
 
-  ////////////////////////////////////////////////////////////////////////////
-  // Private functions:
+    ////////////////////////////////////////////////////////////////////////////
+    // Command handlers:
 
-  /**
-   * Minimize the set of |itemIds| by removing any node which has an ancestor
-   * node already in the set. This ensures that instead of trying to delete both
-   * a node and its descendant, we will only try to delete the topmost node,
-   * preventing an error in the bookmarkManagerPrivate.removeTrees API call.
-   * @param {!Set<string>} itemIds
-   * @return {!Set<string>}
-   */
-  minimizeDeletionSet_: function(itemIds) {
-    var minimizedSet = new Set();
-    var nodes = this.getState().nodes;
-    itemIds.forEach(function(itemId) {
-      var currentId = itemId;
-      while (currentId != ROOT_NODE_ID) {
-        currentId = assert(nodes[currentId].parentId);
-        if (itemIds.has(currentId))
-          return;
+    /**
+     * Determine if the |command| can be executed with the given |itemIds|.
+     * Commands which appear in the context menu should be implemented
+     * separately using `isCommandVisible_` and `isCommandEnabled_`.
+     * @param {Command} command
+     * @param {!Set<string>} itemIds
+     * @return {boolean}
+     */
+    canExecute: function(command, itemIds) {
+      return this.isCommandVisible_(command, itemIds) &&
+          this.isCommandEnabled_(command, itemIds);
+    },
+
+    /**
+     * @param {Command} command
+     * @param {!Set<string>} itemIds
+     * @return {boolean} True if the command should be visible in the context
+     *     menu.
+     */
+    isCommandVisible_: function(command, itemIds) {
+      switch (command) {
+        case Command.EDIT:
+          return itemIds.size == 1;
+        case Command.COPY:
+          return itemIds.size == 1 &&
+              this.containsMatchingNode_(itemIds, function(node) {
+                return !!node.url;
+              });
+        case Command.DELETE:
+        case Command.OPEN_NEW_TAB:
+        case Command.OPEN_NEW_WINDOW:
+        case Command.OPEN_INCOGNITO:
+          return itemIds.size > 0;
+        default:
+          return false;
       }
-      minimizedSet.add(itemId);
-    });
-    return minimizedSet;
-  },
+    },
 
-  /**
-   * @param {!Set<string>} itemIds
-   * @param {function(BookmarkNode):boolean} predicate
-   * @return {boolean} True if any node in |itemIds| returns true for
-   *     |predicate|.
-   */
-  containsMatchingNode_: function(itemIds, predicate) {
-    var nodes = this.getState().nodes;
+    /**
+     * @param {Command} command
+     * @param {!Set<string>} itemIds
+     * @return {boolean} True if the command should be clickable in the context
+     *     menu.
+     */
+    isCommandEnabled_: function(command, itemIds) {
+      switch (command) {
+        case Command.OPEN_NEW_TAB:
+        case Command.OPEN_NEW_WINDOW:
+        case Command.OPEN_INCOGNITO:
+          return this.expandUrls_(itemIds).length > 0;
+        default:
+          return true;
+      }
+    },
 
-    return Array.from(itemIds).some(function(id) {
-      return predicate(nodes[id]);
-    });
-  },
+    /**
+     * @param {Command} command
+     * @param {!Set<string>} itemIds
+     */
+    handle: function(command, itemIds) {
+      switch (command) {
+        case Command.EDIT:
+          var id = Array.from(itemIds)[0];
+          /** @type {!BookmarksEditDialogElement} */ (this.$.editDialog.get())
+              .showEditDialog(this.getState().nodes[id]);
+          break;
+        case Command.COPY:
+          var idList = Array.from(itemIds);
+          chrome.bookmarkManagerPrivate.copy(idList, function() {
+            // TODO(jiaxi): Add toast later.
+          });
+          break;
+        case Command.DELETE:
+          chrome.bookmarkManagerPrivate.removeTrees(
+              Array.from(this.minimizeDeletionSet_(itemIds)), function() {
+                // TODO(jiaxi): Add toast later.
+              });
+          break;
+        case Command.OPEN_NEW_TAB:
+        case Command.OPEN_NEW_WINDOW:
+        case Command.OPEN_INCOGNITO:
+          this.openUrls_(this.expandUrls_(itemIds), command);
+          break;
+      }
+    },
 
-  /**
-   * @param {Event} e
-   * @private
-   */
-  onOpenItemMenu_: function(e) {
-    if (e.detail.targetElement) {
-      this.openCommandMenuAtElement(e.detail.targetElement);
-    } else {
-      this.openCommandMenuAtPosition(e.detail.x, e.detail.y);
-    }
-  },
+    ////////////////////////////////////////////////////////////////////////////
+    // Private functions:
 
-  /**
-   * @param {Event} e
-   * @private
-   */
-  onCommandClick_: function(e) {
-    this.closeCommandMenu();
-    this.handle(e.target.getAttribute('command'), assert(this.menuIds_));
-  },
+    /**
+     * Minimize the set of |itemIds| by removing any node which has an ancestor
+     * node already in the set. This ensures that instead of trying to delete
+     * both a node and its descendant, we will only try to delete the topmost
+     * node, preventing an error in the bookmarkManagerPrivate.removeTrees API
+     * call.
+     * @param {!Set<string>} itemIds
+     * @return {!Set<string>}
+     */
+    minimizeDeletionSet_: function(itemIds) {
+      var minimizedSet = new Set();
+      var nodes = this.getState().nodes;
+      itemIds.forEach(function(itemId) {
+        var currentId = itemId;
+        while (currentId != ROOT_NODE_ID) {
+          currentId = assert(nodes[currentId].parentId);
+          if (itemIds.has(currentId))
+            return;
+        }
+        minimizedSet.add(itemId);
+      });
+      return minimizedSet;
+    },
 
-  /**
-   * @param {!Event} e
-   * @private
-   */
-  onKeydown_: function(e) {
-    var selection = this.getState().selection.items;
-    // TODO(tsergeant): Prevent keyboard shortcuts when a dialog is open or text
-    // field is focused.
-    for (var commandName in this.shortcuts_) {
-      var shortcut = this.shortcuts_[commandName];
-      if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(e, shortcut) &&
-          this.canExecute(commandName, selection)) {
-        this.handle(commandName, selection);
+    /**
+     * @param {!Array<string>} urls
+     * @param {Command} command
+     * @private
+     */
+    openUrls_: function(urls, command) {
+      assert(
+          command == Command.OPEN_NEW_TAB ||
+          command == Command.OPEN_NEW_WINDOW ||
+          command == Command.OPEN_INCOGNITO);
 
-        e.stopPropagation();
-        e.preventDefault();
+      if (urls.length == 0)
         return;
+
+      var incognito = command == Command.OPEN_INCOGNITO;
+      if (command == Command.OPEN_NEW_WINDOW || incognito) {
+        chrome.windows.create({url: urls, incognito: incognito});
+      } else {
+        urls.forEach(function(url) {
+          chrome.tabs.create({url: url, active: false});
+        });
       }
-    }
-  },
+    },
 
-  /**
-   * Close the menu on mousedown so clicks can propagate to the underlying UI.
-   * This allows the user to right click the list while a context menu is
-   * showing and get another context menu.
-   * @param {Event} e
-   * @private
-   */
-  onMenuMousedown_: function(e) {
-    if (e.path[0] != this.$.dropdown)
-      return;
+    /**
+     * Returns all URLs in the given set of nodes and their immediate children.
+     * Note that these will be ordered by insertion order into the |itemIds|
+     * set, and that it is possible to duplicate a URL by passing in both the
+     * parent ID and child ID.
+     * @param {!Set<string>} itemIds
+     * @return {!Array<string>}
+     * @private
+     */
+    expandUrls_: function(itemIds) {
+      var urls = [];
+      var nodes = this.getState().nodes;
 
-    this.$.dropdown.close();
-  },
+      itemIds.forEach(function(id) {
+        var node = nodes[id];
+        if (node.url) {
+          urls.push(node.url);
+        } else {
+          node.children.forEach(function(childId) {
+            var childNode = nodes[childId];
+            if (childNode.url)
+              urls.push(childNode.url);
+          });
+        }
+      });
 
-  /** @private */
-  getEditActionLabel_: function() {
-    if (this.menuIds_.size > 1)
-      return;
+      return urls;
+    },
 
-    var id = Array.from(this.menuIds_)[0];
-    var itemUrl = this.getState().nodes[id].url;
-    var label = itemUrl ? 'menuEdit' : 'menuRename';
-    return loadTimeData.getString(label);
-  },
+    /**
+     * @param {!Set<string>} itemIds
+     * @param {function(BookmarkNode):boolean} predicate
+     * @return {boolean} True if any node in |itemIds| returns true for
+     *     |predicate|.
+     */
+    containsMatchingNode_: function(itemIds, predicate) {
+      var nodes = this.getState().nodes;
+
+      return Array.from(itemIds).some(function(id) {
+        return predicate(nodes[id]);
+      });
+    },
+
+    /**
+     * @param {Event} e
+     * @private
+     */
+    onOpenItemMenu_: function(e) {
+      if (e.detail.targetElement) {
+        this.openCommandMenuAtElement(e.detail.targetElement);
+      } else {
+        this.openCommandMenuAtPosition(e.detail.x, e.detail.y);
+      }
+    },
+
+    /**
+     * @param {Event} e
+     * @private
+     */
+    onCommandClick_: function(e) {
+      this.closeCommandMenu();
+      this.handle(e.target.getAttribute('command'), assert(this.menuIds_));
+    },
+
+    /**
+     * @param {!Event} e
+     * @private
+     */
+    onKeydown_: function(e) {
+      var selection = this.getState().selection.items;
+      // TODO(tsergeant): Prevent keyboard shortcuts when a dialog is open or
+      // text field is focused.
+      for (var commandName in this.shortcuts_) {
+        var shortcut = this.shortcuts_[commandName];
+        if (Polymer.IronA11yKeysBehavior.keyboardEventMatchesKeys(
+                e, shortcut) &&
+            this.canExecute(commandName, selection)) {
+          this.handle(commandName, selection);
+
+          e.stopPropagation();
+          e.preventDefault();
+          return;
+        }
+      }
+    },
+
+    /**
+     * Close the menu on mousedown so clicks can propagate to the underlying UI.
+     * This allows the user to right click the list while a context menu is
+     * showing and get another context menu.
+     * @param {Event} e
+     * @private
+     */
+    onMenuMousedown_: function(e) {
+      if (e.path[0] != this.$.dropdown)
+        return;
+
+      this.$.dropdown.close();
+    },
+
+    /**
+     * @param {Command} command
+     * @return {string}
+     * @private
+     */
+    getCommandLabel_: function(command) {
+      var multipleNodes = this.menuIds_.size > 1 ||
+          this.containsMatchingNode_(this.menuIds_, function(node) {
+            return !node.url;
+          });
+      var label;
+      switch (command) {
+        case Command.EDIT:
+          if (this.menuIds_.size > 1)
+            return '';
+
+          var id = Array.from(this.menuIds_)[0];
+          var itemUrl = this.getState().nodes[id].url;
+          label = itemUrl ? 'menuEdit' : 'menuRename';
+          break;
+        case Command.COPY:
+          label = 'menuCopyURL';
+          break;
+        case Command.DELETE:
+          label = 'menuDelete';
+          break;
+        case Command.OPEN_NEW_TAB:
+          label = multipleNodes ? 'menuOpenAllNewTab' : 'menuOpenNewTab';
+          break;
+        case Command.OPEN_NEW_WINDOW:
+          label = multipleNodes ? 'menuOpenAllNewWindow' : 'menuOpenNewWindow';
+          break;
+        case Command.OPEN_INCOGNITO:
+          label = multipleNodes ? 'menuOpenAllIncognito' : 'menuOpenIncognito';
+          break;
+      }
+
+      return loadTimeData.getString(assert(label));
+    },
+
+    /**
+     * @param {Command} command
+     * @return {boolean}
+     * @private
+     */
+    showDividerAfter_: function(command) {
+      return command == Command.DELETE;
+    },
+  });
+
+  /** @private {bookmarks.CommandManager} */
+  CommandManager.instance_ = null;
+
+  /** @return {!bookmarks.CommandManager} */
+  CommandManager.getInstance = function() {
+    return assert(CommandManager.instance_);
+  };
+
+  return {
+    CommandManager: CommandManager,
+  };
 });
diff --git a/chrome/browser/resources/md_bookmarks/constants.js b/chrome/browser/resources/md_bookmarks/constants.js
index 692cd352..6879377 100644
--- a/chrome/browser/resources/md_bookmarks/constants.js
+++ b/chrome/browser/resources/md_bookmarks/constants.js
@@ -23,6 +23,9 @@
   EDIT: 'edit',
   COPY: 'copy',
   DELETE: 'delete',
+  OPEN_NEW_TAB: 'open-new-tab',
+  OPEN_NEW_WINDOW: 'open-new-window',
+  OPEN_INCOGNITO: 'open-incognito',
 };
 
 /** @const */
diff --git a/chrome/browser/resources/md_bookmarks/folder_node.js b/chrome/browser/resources/md_bookmarks/folder_node.js
index 12654b4..09dd809 100644
--- a/chrome/browser/resources/md_bookmarks/folder_node.js
+++ b/chrome/browser/resources/md_bookmarks/folder_node.js
@@ -61,6 +61,12 @@
     });
 
     this.updateFromStore();
+
+    if (this.isSelectedFolder_) {
+      this.async(function() {
+        this.scrollIntoViewIfNeeded();
+      });
+    }
   },
 
   /** @return {HTMLElement} */
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
index 6dc90f2e..521277b8b 100644
--- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
+++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -61,6 +61,19 @@
   AddLocalizedString(source, "menuEdit", IDS_EDIT);
   AddLocalizedString(source, "menuExport", IDS_MD_BOOKMARK_MANAGER_MENU_EXPORT);
   AddLocalizedString(source, "menuImport", IDS_MD_BOOKMARK_MANAGER_MENU_IMPORT);
+  // TODO(tsergeant): These are not the exact strings specified by UI. Reconcile
+  // the differences between these strings and the work in crbug.com/708815.
+  AddLocalizedString(source, "menuOpenAllNewTab", IDS_BOOKMARK_BAR_OPEN_ALL);
+  AddLocalizedString(source, "menuOpenAllNewWindow",
+                     IDS_BOOKMARK_BAR_OPEN_ALL_NEW_WINDOW);
+  AddLocalizedString(source, "menuOpenAllIncognito",
+                     IDS_BOOKMARK_BAR_OPEN_ALL_INCOGNITO);
+  AddLocalizedString(source, "menuOpenNewTab",
+                     IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB);
+  AddLocalizedString(source, "menuOpenNewWindow",
+                     IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW);
+  AddLocalizedString(source, "menuOpenIncognito",
+                     IDS_BOOKMARK_BAR_OPEN_INCOGNITO);
   AddLocalizedString(source, "menuRename", IDS_MD_BOOKMARK_MANAGER_MENU_RENAME);
   AddLocalizedString(source, "menuSort", IDS_MD_BOOKMARK_MANAGER_MENU_SORT);
   AddLocalizedString(source, "noSearchResults",
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index ddbfe97..d5c5f57 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -807,8 +807,14 @@
     "dependencies": ["permission:webview"],
     "contexts": ["blessed_extension"]
   },
-  "windows": {
+  "windows": [{
     "dependencies": ["api:tabs"],
     "contexts": ["blessed_extension"]
-  }
+  }, {
+    "channel": "stable",
+    "contexts": ["webui"],
+    "matches": [
+      "chrome://bookmarks/*"
+    ]
+  }]
 }
diff --git a/chrome/test/data/webui/md_bookmarks/command_manager_test.js b/chrome/test/data/webui/md_bookmarks/command_manager_test.js
index c0b993b..14b6d282 100644
--- a/chrome/test/data/webui/md_bookmarks/command_manager_test.js
+++ b/chrome/test/data/webui/md_bookmarks/command_manager_test.js
@@ -32,12 +32,20 @@
                 createFolder(
                     '11',
                     [
-                      createItem('111'),
+                      createItem('111', {url: 'http://111/'}),
                     ]),
-                createFolder('12', []),
-                createItem('13'),
+                createFolder(
+                    '12',
+                    [
+                      createItem('121', {url: 'http://121/'}),
+                    ]),
+                createItem('13', {url: 'http://13/'}),
               ]),
-          createFolder('2', [])),
+          createFolder(
+              '2',
+              [
+                createFolder('21', []),
+              ]))
     });
     bookmarks.Store.instance_ = store;
 
@@ -50,6 +58,8 @@
       realHandle(command, itemIds);
     };
     replaceBody(commandManager);
+
+    Polymer.dom.flush();
   });
 
   test('can only copy single URL items', function() {
@@ -130,4 +140,49 @@
 
     assertDeepEquals(['1', '2'], lastDelete);
   });
+
+  test('expandUrls_ expands one level of URLs', function() {
+    var urls = commandManager.expandUrls_(new Set(['1']));
+    assertDeepEquals(['http://13/'], urls);
+
+    urls = commandManager.expandUrls_(new Set(['11', '12', '13']));
+    assertDeepEquals(['http://111/', 'http://121/', 'http://13/'], urls);
+  });
+
+  test('shift-enter opens URLs in new window', function() {
+    store.data.selection.items = new Set(['12', '13']);
+    store.notifyObservers();
+
+    var lastCreate;
+    chrome.windows.create = function(createConfig) {
+      lastCreate = createConfig;
+    };
+
+    MockInteractions.pressAndReleaseKeyOn(document, 13, 'shift', 'Enter');
+    assertLastCommand(Command.OPEN_NEW_WINDOW, ['12', '13']);
+    assertDeepEquals(['http://121/', 'http://13/'], lastCreate.url);
+    assertFalse(lastCreate.incognito);
+  });
+
+  test('cannot execute "Open in New Tab" on folders with no items', function() {
+    var items = new Set(['2']);
+    assertFalse(commandManager.canExecute(Command.OPEN_NEW_TAB, items));
+
+    store.data.selection.items = items;
+
+    commandManager.openCommandMenuAtPosition(0, 0);
+    var commandItem = {};
+    commandManager.root.querySelectorAll('.dropdown-item').forEach(element => {
+      commandItem[element.getAttribute('command')] = element;
+    });
+
+    assertTrue(commandItem[Command.OPEN_NEW_TAB].disabled);
+    assertFalse(commandItem[Command.OPEN_NEW_TAB].hidden);
+
+    assertTrue(commandItem[Command.OPEN_NEW_WINDOW].disabled);
+    assertFalse(commandItem[Command.OPEN_NEW_WINDOW].hidden);
+
+    assertTrue(commandItem[Command.OPEN_INCOGNITO].disabled);
+    assertFalse(commandItem[Command.OPEN_INCOGNITO].hidden);
+  });
 });
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index 429b4f5..4c4d3422 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -119,6 +119,16 @@
     "args": ["--disable-slimming-paint-invalidation"]
   },
   {
+    "prefix": "off-main-thread-fetch",
+    "base": "http/tests/fetch/workers",
+    "args": ["--enable-features=OffMainThreadFetch"]
+  },
+  {
+    "prefix": "off-main-thread-fetch",
+    "base": "http/tests/xmlhttprequest/workers",
+    "args": ["--enable-features=OffMainThreadFetch"]
+  },
+  {
     "prefix": "origin-trials-runtimeflags-disabled",
     "base": "http/tests/origin_trials/webexposed",
     "args": ["--disable-blink-features=ForeignFetch,InstalledApp,LinkServiceWorker,LongTaskObserver,SetRootScroller,WebUSB,WebVR,WebShare"]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-characteristic-is-removed.html
index a933867a..1c5df21f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-characteristic-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-characteristic-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.html
index 78c6b835..5e775e3 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.html
index 370aa9d1..2b7a188 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.html
index 3dd6bb8..f8ad4e9 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.html
index 49fbe6ab..13d714e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.html
index 47b74dc..59ab7ef 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.html
index a1f3c8c6..eb722199 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.html
index b19e359..4a3a2fc3 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.html
index 3ed0e2e..345b104 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.html
index 849e4b0..7c2b585 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-get-same-object.html
index 2006c95c..19533894 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-get-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-get-same-object.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.html
index 6a1eefd9..7eec2c2 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.html
index 4ee0fc0..b8cf4823 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-service-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-service-is-removed.html
index 940b90d6..b07fbc4 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-service-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptor/gen-service-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed-with-uuid.html
index 90021cc..02b53ba3 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed.html
index 54c9982..b900e3a6 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-characteristic-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.html
index f01fdde..e86d3ba 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.html
index 3fe240d..82d7d31 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.html
index 1452d0e..6554c33e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.html
index 6c3dd143..4077589 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.html
index 36d922f..e5bb627c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.html
index bec4f24..c38c309 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.html
index 95e36b48..5deed54 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.html
index b0250d0..d2a57489 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.html
index c3b37a2..83e5d36 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.html
index e58a85e9..92aad9f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.html
index 27858f2c..6b12d65 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.html
index a26d8d6e..f9d1411b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.html
index 1ee3ba3..f830182 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.html
index 66689ec..accbc406 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.html
index c31ea77..1dfee88 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.html
index 8c39dfe..0beee57 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.html
index 42c1860..e836870 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.html
index 358d8ad..29e16ef0 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.html
index e40aaea8..def99fb 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.html
index d11ab3c..d35adf4 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed-with-uuid.html
index 664c7429..e426af9 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed.html
index 664c7429..e426af9 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/getDescriptors/gen-service-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-characteristic-is-removed.html
index 5c7529c9..7782152af 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-characteristic-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-characteristic-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.html
index b0fc0993..2494e258 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.html
index 74aafad7..384488b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.html
index f3e9157..7d687e2 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.html
index 6d8b24a9..3130160 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.html
index b38046b7..59d9cc5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.html
index 74480cb..32d61ba 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.html
index 9cf7a71..0c9e648 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.html
index e3ce3bb..b16fe18 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.html
index cfa1c63..5376d4a4 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.html
index 0e43b22..8252acd 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.html
index d7b988a..bdbb069 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.html
index 447d4e9..146e8e9 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-characteristic-is-removed.html
index 1d2bba91..7e6003e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-characteristic-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-characteristic-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.html
index fa1541c07..a8559011 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.html
index 81af665f..83581d3 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.html
index 5d40c68..2685881 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.html
index 1c57102..286601e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.html
index 68a6b7b..92b3525 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.html
index 2ad7864..b920f94 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.html
index 1138fcc..c0a7326 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.html
index 8653a22..8592e38 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.html
index 401e84aa6..32e5d9e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
index 734d1b56..56623b5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.html
index b6b06ce7..c4f8fc5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.html
index b77bab0..5584dcf7 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html
index ab99cee..f37122a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html
index 7c2d2a7..f45d216 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html
index 027e96c..8f5e94c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html
index 84ec35e..3afc0e1 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
index 76607f8..0bed95de 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-characteristic-is-removed.html
index 0078a8ef..1881364 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-characteristic-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-characteristic-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.html
index fb12ba4af..f7eea07 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.html
index 203c9c9..d588061 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.html
index dee8248..c4f6fb8 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.html
index 2ffac61..0199364 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.html
index 6be55d9..aae2709f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.html
index f05c89ee..316cf2d 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.html
index 862f0df..9f224833 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.html
index 7bdf7e3..f56a6b1 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.html
index a72ae34..6271337 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.html
index 5b03c25..d79b3ee 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.html
index 10bbbeb..d29214bf 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.html
index 726043f4..0a56b383 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
index a6060802..624273901 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html
index c9f76c2..a84de5bcd 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html
index 4c852d4..bc75923 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html
index d2b38f0..39d7c26 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html
index 3f47ac9..1b26a8a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html
index ac1fa11..bf0b4e4 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html
index e4a977e6..f512790 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html
index 1808b9e..6aa9e89c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html
index 9851482..6b861674 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html
index 6933150..d1db6ba 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html
index a3bc1f11..505702b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-fails.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html
index 996c8d6..42fdb3e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html
index 3202d43c..831fbc9 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html
index ba65197..2ecbfe54 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html
index 0442811..30f5afb8 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html
index eb7f24e..1b88b4c5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/readValue/gen-service-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
index ed710b7..b76c53f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html
index 5325c84..7ab7345 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html
index de767f5..ccb9b93 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html
index 9bc8f5fb..df10b36 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html
index 80eeef4..8ffced0 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html
index b5a95a0..5780d862 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html
index e428fa5..d9e1fed 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html
index 94ff73a..4a11cbe 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html
index 39bbe89..5f882fe 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-fails.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-fails.html
index 317a6d0..d2ff1e91 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-fails.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-fails.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html
index e8830f37..7b9e4c4 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html
index 95c93e2..cecb93ad 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html
index 3e24c35..72f48679 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html
index 957ef5e..be7e5e5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 promise_test(
     () => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-service-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-service-is-removed.html
index 6cd2690e..242912e 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-service-is-removed.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/descriptor/writeValue/gen-service-is-removed.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/base_test_template.html b/third_party/WebKit/LayoutTests/bluetooth/script-tests/base_test_template.html
index e4a3ad2..4f52e63c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/base_test_template.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/base_test_template.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 TEST
 </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-for-any-service.html
index 3e586879..47ede4ed 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-for-any-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-for-any-service.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html
index 6a3cf5b4..2267c42 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(t => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.html
index c55cbc69..394681d 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html
index 6bdd14cb..0acff90 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
index 42d9af2..7e1ddde7 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
index 09ca3a028..f03e923 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html
index f54b4c1..37c33542 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html
index 03a8ad8..f046b52 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-get-same-object.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
index d806f36..c04a98f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service-with-uuid.html
index 24d961602..5a1828c9 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service.html
index cfff721..84d7b55 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-for-any-service.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html
index 6cecf4e..814105f 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(t => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html
index 885c693..1494385 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(t => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.html
index f1426b1..fdc9876 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.html
index fbe41394..63dd666 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html
index eeb4815..19ccb5a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html
index 4e9f3c9..1506c3d 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
index e3f632b..9e38a0d 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
index 4bc900a..a3677d6b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
index 89e6565..ff3978c 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
index 5185205..66813e4 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html
index 71865c18..e903a517 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html
index 41226bc5c4..1afe652 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html
index 5595f477..e6231c3 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html
index 10b26f7..00f859b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-get-same-object.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
index b382af76..12b0ef9 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
index f82e0af..0b19a37 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html
index 0f19f49..7f3c6181 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html
index e05d356..6658708 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-error.html
index e46582a..26fd3421 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.html
index 053cafb9..55ba1c5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-get-same-object.html
index 9e61bcc6..95551ad 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-get-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristic/gen-get-same-object.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html
index 3fb1fc9..14feb007 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html
index 15fce456..556ee5ff 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html
index fea309f..aaec32b5 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html
index 995d2894..a644971a 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error-with-uuid.html
index 65532abf1..d489e30 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error.html
index 2c4b349..c8503f0 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-error.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.html
index eebfa73..7501579 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.html
index bbe0183..33ac184 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object-with-uuid.html
index 4d822ac..6cee86b 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object-with-uuid.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object-with-uuid.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object.html
index 3ab308c..8f97af7 100644
--- a/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object.html
+++ b/third_party/WebKit/LayoutTests/bluetooth/service/getCharacteristics/gen-get-same-object.html
@@ -3,6 +3,8 @@
 <script src="../../../resources/testharness.js"></script>
 <script src="../../../resources/testharnessreport.js"></script>
 <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script>
+<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script>
+<script src="../../../resources/mojo-helpers.js"></script>
 <script>
 'use strict';
 promise_test(() => {
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/README.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/README.txt
new file mode 100644
index 0000000..333a41222
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/README.txt
@@ -0,0 +1 @@
+This directory is for testing the off-main-thread fetch optimization.
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/block-mixed-content-base-https-expected.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/block-mixed-content-base-https-expected.txt
new file mode 100644
index 0000000..cce97ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/block-mixed-content-base-https-expected.txt
@@ -0,0 +1,18 @@
+CONSOLE ERROR: line 157: Fetch API cannot load http://example.test:8000/serviceworker/resources/fetch-access-control.php?ACAOrigin=*&label=test1-same-origin. Request mode is "same-origin" but the URL's origin is not same as the request origin https://127.0.0.1:8443.
+CONSOLE ERROR: Fetch API cannot load https://127.0.0.1:8443/serviceworker/resources/redirect.php?ACAOrigin=*&Redirect=http%3A%2F%2Fexample.test%3A8000%2Fserviceworker%2Fresources%2Ffetch-access-control.php%3FACAOrigin%3D*%26label%3Dtest2-same-origin. Redirect failed.
+CONSOLE ERROR: line 170: Fetch API cannot load http://example.test:8000/serviceworker/resources/redirect.php?ACAOrigin=*&Redirect=https%3A%2F%2F127.0.0.1%3A8443%2Fserviceworker%2Fresources%2Ffetch-access-control.php%3FACAOrigin%3D*%26label%3Dtest3-same-origin. Request mode is "same-origin" but the URL's origin is not same as the request origin https://127.0.0.1:8443.
+CONSOLE ERROR: line 188: Fetch API cannot load https://localhost:8443/serviceworker/resources/redirect.php?ACAOrigin=*&Redirect=https%3A%2F%2F127.0.0.1%3A8443%2Fserviceworker%2Fresources%2Ffetch-access-control.php%3FACAOrigin%3D*%26label%3Dtest5-same-origin. Request mode is "same-origin" but the URL's origin is not same as the request origin https://127.0.0.1:8443.
+This is a testharness.js-based test.
+PASS Startup 
+PASS Mixed content fetch (same-origin, HTTPS->HTTP) 
+PASS Mixed content redirect (same-origin, HTTPS->HTTPS->HTTP) 
+PASS Mixed content redirect same-origin, HTTPS->HTTP->HTTPS) 
+PASS Same origin redirect (same-origin, HTTPS->HTTPS->HTTPS) 
+PASS Cross origin redirect (same-origin, HTTPS->HTTPS->HTTPS 
+FAIL Mixed content fetch (cors, HTTPS->HTTP) assert_unreached: unexpected fulfillment: [object Response] Reached unreachable code
+FAIL Mixed content redirect (cors, HTTPS->HTTPS->HTTP) assert_unreached: unexpected fulfillment: [object Response] Reached unreachable code
+FAIL Mixed content redirect cors, HTTPS->HTTP->HTTPS) assert_unreached: unexpected fulfillment: [object Response] Reached unreachable code
+PASS Same origin redirect (cors, HTTPS->HTTPS->HTTPS) 
+PASS Cross origin redirect (cors, HTTPS->HTTPS->HTTPS 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/block-mixed-content-nocors-base-https-expected.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/block-mixed-content-nocors-base-https-expected.txt
new file mode 100644
index 0000000..bb3c186
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/fetch/workers/block-mixed-content-nocors-base-https-expected.txt
@@ -0,0 +1,9 @@
+This is a testharness.js-based test.
+PASS Startup 
+FAIL Mixed content fetch (no-cors, HTTPS->HTTP) assert_unreached: unexpected fulfillment: [object Response] Reached unreachable code
+FAIL Mixed content redirect (no-cors, HTTPS->HTTPS->HTTP) assert_unreached: unexpected fulfillment: [object Response] Reached unreachable code
+FAIL Mixed content redirect no-cors, HTTPS->HTTP->HTTPS) assert_unreached: unexpected fulfillment: [object Response] Reached unreachable code
+PASS Same origin redirect (no-cors, HTTPS->HTTPS->HTTPS) 
+PASS Cross origin redirect (no-cors, HTTPS->HTTPS->HTTPS 
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/xmlhttprequest/workers/README.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/xmlhttprequest/workers/README.txt
new file mode 100644
index 0000000..333a41222
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/xmlhttprequest/workers/README.txt
@@ -0,0 +1 @@
+This directory is for testing the off-main-thread fetch optimization.
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
new file mode 100644
index 0000000..de5a621
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/off-main-thread-fetch/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
@@ -0,0 +1,40 @@
+CONSOLE ERROR: line 20: XMLHttpRequest cannot load ftp://127.0.0.1/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 1: XMLHttpRequest cannot load ftp://127.0.0.1/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: XMLHttpRequest cannot load ftp://127.0.0.1/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 1: XMLHttpRequest cannot load ftp://127.0.0.1/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: XMLHttpRequest cannot load localhost:8080/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 1: XMLHttpRequest cannot load localhost:8080/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: XMLHttpRequest cannot load localhost:8080/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 1: XMLHttpRequest cannot load localhost:8080/. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: XMLHttpRequest cannot load tel:1234. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 1: XMLHttpRequest cannot load tel:1234. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 20: XMLHttpRequest cannot load tel:1234. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 1: XMLHttpRequest cannot load tel:1234. Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+[Worker] Test cross-origin XHRs to CORS-unsupported protocol schemes in the URL.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Starting worker: ../resources/cross-origin-unsupported-url.js
+PASS [Worker] errorEvent.name is "NetworkError"
+PASS [Worker] errorEvent.type is "error"
+PASS [Worker] xhr.send() did not throw exception.
+PASS [Worker] errorEvent.name is "NetworkError"
+PASS [Worker] errorEvent.type is "error"
+PASS [Worker] xhr.send() did not throw exception.
+PASS [Worker] errorEvent.name is "NetworkError"
+PASS [Worker] errorEvent.type is "error"
+PASS [Worker] xhr.send() did not throw exception.
+PASS [Worker] errorEvent.name is "NetworkError"
+PASS [Worker] errorEvent.type is "error"
+PASS [Worker] xhr.send() did not throw exception.
+PASS [Worker] errorEvent.name is "NetworkError"
+PASS [Worker] errorEvent.type is "error"
+PASS [Worker] xhr.send() did not throw exception.
+PASS [Worker] errorEvent.name is "NetworkError"
+PASS [Worker] errorEvent.type is "error"
+PASS [Worker] xhr.send() did not throw exception.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
index e4c3925..7031a194 100644
--- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -393,7 +393,10 @@
     bool should_force_preflight = request.IsExternalRequest();
     if (!should_force_preflight)
       probe::shouldForceCORSPreflight(GetDocument(), &should_force_preflight);
+    // TODO(horo): Currently we don't support the CORS preflight cache on worker
+    // thread when off-main-thread-fetch is enabled. https://crbug.com/443374
     bool can_skip_preflight =
+        IsMainThread() &&
         CrossOriginPreflightResultCache::Shared().CanSkipPreflight(
             GetSecurityOrigin()->ToString(), cross_origin_request.Url(),
             EffectiveAllowCredentials(), cross_origin_request.HttpMethod(),
@@ -769,9 +772,13 @@
     return;
   }
 
-  CrossOriginPreflightResultCache::Shared().AppendEntry(
-      GetSecurityOrigin()->ToString(), actual_request_.Url(),
-      std::move(preflight_result));
+  if (IsMainThread()) {
+    // TODO(horo): Currently we don't support the CORS preflight cache on worker
+    // thread when off-main-thread-fetch is enabled. https://crbug.com/443374
+    CrossOriginPreflightResultCache::Shared().AppendEntry(
+        GetSecurityOrigin()->ToString(), actual_request_.Url(),
+        std::move(preflight_result));
+  }
 }
 
 void DocumentThreadableLoader::ReportResponseReceived(
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp
index bf836d3..cb4ce9a 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoader.cpp
@@ -34,8 +34,10 @@
 #include "core/dom/ExecutionContext.h"
 #include "core/loader/DocumentThreadableLoader.h"
 #include "core/loader/ThreadableLoadingContext.h"
+#include "core/loader/WorkerFetchContext.h"
 #include "core/loader/WorkerThreadableLoader.h"
 #include "core/workers/WorkerGlobalScope.h"
+#include "platform/RuntimeEnabledFeatures.h"
 
 namespace blink {
 
@@ -47,6 +49,14 @@
   DCHECK(client);
 
   if (context.IsWorkerGlobalScope()) {
+    if (RuntimeEnabledFeatures::offMainThreadFetchEnabled()) {
+      DCHECK(ToWorkerGlobalScope(&context)->GetFetchContext());
+      // TODO(horo): Rename DocumentThreadableLoader. We will use it on the
+      // worker thread when off-main-thread-fetch is enabled.
+      return DocumentThreadableLoader::Create(
+          *ThreadableLoadingContext::Create(*ToWorkerGlobalScope(&context)),
+          client, options, resource_loader_options);
+    }
     return WorkerThreadableLoader::Create(ToWorkerGlobalScope(context), client,
                                           options, resource_loader_options);
   }
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp
index 0df2ad47..551dd18c 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.cpp
@@ -6,6 +6,8 @@
 
 #include "core/dom/Document.h"
 #include "core/dom/TaskRunnerHelper.h"
+#include "core/loader/WorkerFetchContext.h"
+#include "core/workers/WorkerGlobalScope.h"
 #include "platform/loader/fetch/ResourceFetcher.h"
 
 namespace blink {
@@ -66,9 +68,77 @@
   Member<Document> document_;
 };
 
+class WorkerThreadableLoadingContext : public ThreadableLoadingContext {
+ public:
+  explicit WorkerThreadableLoadingContext(
+      WorkerGlobalScope& worker_global_scope)
+      : worker_global_scope_(&worker_global_scope),
+        fetch_context_(worker_global_scope.GetFetchContext()) {}
+
+  ~WorkerThreadableLoadingContext() override = default;
+
+  bool IsContextThread() const override {
+    DCHECK(fetch_context_);
+    DCHECK(worker_global_scope_);
+    return worker_global_scope_->IsContextThread();
+  }
+
+  ResourceFetcher* GetResourceFetcher() override {
+    DCHECK(IsContextThread());
+    return fetch_context_->GetResourceFetcher();
+  }
+
+  SecurityOrigin* GetSecurityOrigin() override {
+    DCHECK(IsContextThread());
+    return worker_global_scope_->GetSecurityOrigin();
+  }
+
+  bool IsSecureContext() const override {
+    DCHECK(IsContextThread());
+    String error_message;
+    return worker_global_scope_->IsSecureContext(error_message);
+  }
+
+  KURL FirstPartyForCookies() const override {
+    DCHECK(IsContextThread());
+    // TODO(horo): Returns the FirstPartyForCookies of the parent frame for
+    // dedicated workers.
+    return worker_global_scope_->Url();
+  }
+
+  String UserAgent() const override {
+    DCHECK(IsContextThread());
+    return worker_global_scope_->UserAgent();
+  }
+
+  Document* GetLoadingDocument() override { return nullptr; }
+
+  RefPtr<WebTaskRunner> GetTaskRunner(TaskType type) override {
+    return fetch_context_->LoadingTaskRunner();
+  }
+
+  void RecordUseCount(UseCounter::Feature feature) override {
+    UseCounter::Count(worker_global_scope_, feature);
+  }
+
+  DEFINE_INLINE_VIRTUAL_TRACE() {
+    visitor->Trace(fetch_context_);
+    visitor->Trace(worker_global_scope_);
+    ThreadableLoadingContext::Trace(visitor);
+  }
+
+ private:
+  Member<WorkerGlobalScope> worker_global_scope_;
+  Member<WorkerFetchContext> fetch_context_;
+};
+
 ThreadableLoadingContext* ThreadableLoadingContext::Create(Document& document) {
-  // For now this is the only default implementation.
   return new DocumentThreadableLoadingContext(document);
 }
 
+ThreadableLoadingContext* ThreadableLoadingContext::Create(
+    WorkerGlobalScope& worker_global_scope) {
+  return new WorkerThreadableLoadingContext(worker_global_scope);
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.h b/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.h
index 3447835..35549a9 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.h
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoadingContext.h
@@ -19,6 +19,7 @@
 class ResourceFetcher;
 class SecurityOrigin;
 class WebTaskRunner;
+class WorkerGlobalScope;
 
 // An abstract interface for top-level loading context.
 // This should be accessed only from the thread where the loading
@@ -29,6 +30,7 @@
 
  public:
   static ThreadableLoadingContext* Create(Document&);
+  static ThreadableLoadingContext* Create(WorkerGlobalScope&);
 
   ThreadableLoadingContext() = default;
   virtual ~ThreadableLoadingContext() = default;
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
index a1ca5f3..767f6dc 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -4,14 +4,18 @@
 
 #include "core/loader/WorkerFetchContext.h"
 
+#include "core/frame/Deprecation.h"
+#include "core/frame/UseCounter.h"
 #include "core/workers/WorkerClients.h"
 #include "core/workers/WorkerGlobalScope.h"
 #include "platform/Supplementable.h"
 #include "platform/WebTaskRunner.h"
 #include "platform/exported/WrappedResourceRequest.h"
+#include "platform/loader/fetch/ResourceFetcher.h"
 #include "platform/scheduler/child/web_scheduler.h"
 #include "public/platform/Platform.h"
 #include "public/platform/WebThread.h"
+#include "public/platform/WebURLRequest.h"
 #include "public/platform/WebWorkerFetchContext.h"
 
 namespace blink {
@@ -64,17 +68,90 @@
     return nullptr;
   std::unique_ptr<WebWorkerFetchContext> web_context = holder->TakeContext();
   DCHECK(web_context);
-  return new WorkerFetchContext(std::move(web_context));
+  return new WorkerFetchContext(worker_global_scope, std::move(web_context));
 }
 
 WorkerFetchContext::WorkerFetchContext(
+    WorkerGlobalScope& worker_global_scope,
     std::unique_ptr<WebWorkerFetchContext> web_context)
-    : web_context_(std::move(web_context)) {
-  web_context_->InitializeOnWorkerThread(Platform::Current()
-                                             ->CurrentThread()
-                                             ->Scheduler()
-                                             ->LoadingTaskRunner()
-                                             ->ToSingleThreadTaskRunner());
+    : BaseFetchContext(&worker_global_scope),
+      worker_global_scope_(worker_global_scope),
+      web_context_(std::move(web_context)),
+      loading_task_runner_(Platform::Current()
+                               ->CurrentThread()
+                               ->Scheduler()
+                               ->LoadingTaskRunner()) {
+  web_context_->InitializeOnWorkerThread(
+      loading_task_runner_->ToSingleThreadTaskRunner());
+}
+
+ResourceFetcher* WorkerFetchContext::GetResourceFetcher() {
+  if (resource_fetcher_)
+    return resource_fetcher_;
+  resource_fetcher_ = ResourceFetcher::Create(this);
+  return resource_fetcher_;
+}
+
+ContentSettingsClient* WorkerFetchContext::GetContentSettingsClient() const {
+  // TODO(horo): Implement this.
+  return nullptr;
+}
+
+Settings* WorkerFetchContext::GetSettings() const {
+  // TODO(horo): Implement this.
+  return nullptr;
+}
+
+SubresourceFilter* WorkerFetchContext::GetSubresourceFilter() const {
+  // TODO(horo): Implement this.
+  return nullptr;
+}
+
+SecurityContext* WorkerFetchContext::GetParentSecurityContext() const {
+  // TODO(horo): Implement this.
+  return nullptr;
+}
+
+bool WorkerFetchContext::ShouldBlockRequestByInspector(
+    const ResourceRequest& resource_request) const {
+  // TODO(horo): Implement this.
+  return false;
+}
+
+void WorkerFetchContext::DispatchDidBlockRequest(
+    const ResourceRequest& resource_request,
+    const FetchInitiatorInfo& fetch_initiator_info,
+    ResourceRequestBlockedReason blocked_reason) const {
+  // TODO(horo): Implement this.
+}
+
+void WorkerFetchContext::ReportLocalLoadFailed(const KURL&) const {
+  // TODO(horo): Implement this.
+}
+
+bool WorkerFetchContext::ShouldBypassMainWorldCSP() const {
+  // TODO(horo): Implement this.
+  return false;
+}
+
+bool WorkerFetchContext::IsSVGImageChromeClient() const {
+  return false;
+}
+
+void WorkerFetchContext::CountUsage(UseCounter::Feature feature) const {
+  UseCounter::Count(worker_global_scope_, feature);
+}
+
+void WorkerFetchContext::CountDeprecation(UseCounter::Feature feature) const {
+  Deprecation::CountDeprecation(worker_global_scope_, feature);
+}
+
+bool WorkerFetchContext::ShouldBlockFetchByMixedContentCheck(
+    const ResourceRequest& resource_request,
+    const KURL& url,
+    SecurityViolationReportingPolicy reporting_policy) const {
+  // TODO(horo): Implement this.
+  return false;
 }
 
 std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader() {
@@ -87,10 +164,21 @@
 
 void WorkerFetchContext::PrepareRequest(ResourceRequest& request,
                                         RedirectType) {
+  request.OverrideLoadingIPCType(WebURLRequest::LoadingIPCType::kMojo);
   WrappedResourceRequest webreq(request);
   web_context_->WillSendRequest(webreq);
 }
 
+RefPtr<WebTaskRunner> WorkerFetchContext::LoadingTaskRunner() const {
+  return loading_task_runner_;
+}
+
+DEFINE_TRACE(WorkerFetchContext) {
+  visitor->Trace(worker_global_scope_);
+  visitor->Trace(resource_fetcher_);
+  BaseFetchContext::Trace(visitor);
+}
+
 void ProvideWorkerFetchContextToWorker(
     WorkerClients* clients,
     std::unique_ptr<WebWorkerFetchContext> web_context) {
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
index 4a98706..4797358 100644
--- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
+++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.h
@@ -7,15 +7,17 @@
 
 #include <memory>
 #include "core/CoreExport.h"
-#include "platform/loader/fetch/FetchContext.h"
+#include "core/loader/BaseFetchContext.h"
 #include "platform/wtf/Forward.h"
 
 namespace blink {
 
-class WorkerClients;
+class ResourceFetcher;
+class WebTaskRunner;
 class WebURLLoader;
 class WebWorkerFetchContext;
 class WorkerGlobalScope;
+class WorkerClients;
 
 CORE_EXPORT void ProvideWorkerFetchContextToWorker(
     WorkerClients*,
@@ -25,21 +27,49 @@
 // service workers). This class is used only when off-main-thread-fetch is
 // enabled, and is still under development.
 // TODO(horo): Implement all methods of FetchContext. crbug.com/443374
-class WorkerFetchContext final : public FetchContext {
+class WorkerFetchContext final : public BaseFetchContext {
  public:
   static WorkerFetchContext* Create(WorkerGlobalScope&);
   virtual ~WorkerFetchContext();
 
+  ResourceFetcher* GetResourceFetcher();
+
+  // BaseFetchContext implementation:
+  ContentSettingsClient* GetContentSettingsClient() const override;
+  Settings* GetSettings() const override;
+  SubresourceFilter* GetSubresourceFilter() const override;
+  SecurityContext* GetParentSecurityContext() const override;
+  bool ShouldBlockRequestByInspector(const ResourceRequest&) const override;
+  void DispatchDidBlockRequest(const ResourceRequest&,
+                               const FetchInitiatorInfo&,
+                               ResourceRequestBlockedReason) const override;
+  void ReportLocalLoadFailed(const KURL&) const override;
+  bool ShouldBypassMainWorldCSP() const override;
+  bool IsSVGImageChromeClient() const override;
+  void CountUsage(UseCounter::Feature) const override;
+  void CountDeprecation(UseCounter::Feature) const override;
+  bool ShouldBlockFetchByMixedContentCheck(
+      const ResourceRequest&,
+      const KURL&,
+      SecurityViolationReportingPolicy) const override;
+
   // FetchContext implementation:
   // TODO(horo): Implement more methods.
   std::unique_ptr<WebURLLoader> CreateURLLoader() override;
   void PrepareRequest(ResourceRequest&, RedirectType) override;
   bool IsControlledByServiceWorker() const override;
+  RefPtr<WebTaskRunner> LoadingTaskRunner() const override;
+
+  DECLARE_VIRTUAL_TRACE();
 
  private:
-  explicit WorkerFetchContext(std::unique_ptr<WebWorkerFetchContext>);
+  WorkerFetchContext(WorkerGlobalScope&,
+                     std::unique_ptr<WebWorkerFetchContext>);
 
+  Member<WorkerGlobalScope> worker_global_scope_;
   std::unique_ptr<WebWorkerFetchContext> web_context_;
+  Member<ResourceFetcher> resource_fetcher_;
+  RefPtr<WebTaskRunner> loading_task_runner_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/modules/exported/BUILD.gn b/third_party/WebKit/Source/modules/exported/BUILD.gn
index b23096d..00f32b54 100644
--- a/third_party/WebKit/Source/modules/exported/BUILD.gn
+++ b/third_party/WebKit/Source/modules/exported/BUILD.gn
@@ -9,6 +9,9 @@
     "WebDOMFileSystem.cpp",
     "WebDOMMediaStreamTrack.cpp",
     "WebDatabase.cpp",
+    "WebSpeechGrammar.cpp",
+    "WebSpeechRecognitionHandle.cpp",
+    "WebSpeechRecognitionResult.cpp",
   ]
 
   defines = [ "BLINK_MODULES_IMPLEMENTATION=1" ]
diff --git a/third_party/WebKit/Source/web/WebSpeechGrammar.cpp b/third_party/WebKit/Source/modules/exported/WebSpeechGrammar.cpp
similarity index 100%
rename from third_party/WebKit/Source/web/WebSpeechGrammar.cpp
rename to third_party/WebKit/Source/modules/exported/WebSpeechGrammar.cpp
diff --git a/third_party/WebKit/Source/web/WebSpeechRecognitionHandle.cpp b/third_party/WebKit/Source/modules/exported/WebSpeechRecognitionHandle.cpp
similarity index 100%
rename from third_party/WebKit/Source/web/WebSpeechRecognitionHandle.cpp
rename to third_party/WebKit/Source/modules/exported/WebSpeechRecognitionHandle.cpp
diff --git a/third_party/WebKit/Source/web/WebSpeechRecognitionResult.cpp b/third_party/WebKit/Source/modules/exported/WebSpeechRecognitionResult.cpp
similarity index 97%
rename from third_party/WebKit/Source/web/WebSpeechRecognitionResult.cpp
rename to third_party/WebKit/Source/modules/exported/WebSpeechRecognitionResult.cpp
index e5ddb10..8f51335 100644
--- a/third_party/WebKit/Source/web/WebSpeechRecognitionResult.cpp
+++ b/third_party/WebKit/Source/modules/exported/WebSpeechRecognitionResult.cpp
@@ -44,9 +44,10 @@
 
   HeapVector<Member<SpeechRecognitionAlternative>> alternatives(
       transcripts.size());
-  for (size_t i = 0; i < transcripts.size(); ++i)
+  for (size_t i = 0; i < transcripts.size(); ++i) {
     alternatives[i] =
         SpeechRecognitionAlternative::Create(transcripts[i], confidences[i]);
+  }
 
   private_ = SpeechRecognitionResult::Create(alternatives, final);
 }
diff --git a/third_party/WebKit/Source/modules/speech/BUILD.gn b/third_party/WebKit/Source/modules/speech/BUILD.gn
index 0e60ce45..a5c366c 100644
--- a/third_party/WebKit/Source/modules/speech/BUILD.gn
+++ b/third_party/WebKit/Source/modules/speech/BUILD.gn
@@ -18,6 +18,8 @@
     "SpeechRecognitionAlternative.cpp",
     "SpeechRecognitionAlternative.h",
     "SpeechRecognitionClient.h",
+    "SpeechRecognitionClientProxy.cpp",
+    "SpeechRecognitionClientProxy.h",
     "SpeechRecognitionController.cpp",
     "SpeechRecognitionController.h",
     "SpeechRecognitionError.cpp",
diff --git a/third_party/WebKit/Source/web/SpeechRecognitionClientProxy.cpp b/third_party/WebKit/Source/modules/speech/SpeechRecognitionClientProxy.cpp
similarity index 96%
rename from third_party/WebKit/Source/web/SpeechRecognitionClientProxy.cpp
rename to third_party/WebKit/Source/modules/speech/SpeechRecognitionClientProxy.cpp
index 01fea41d..325266f 100644
--- a/third_party/WebKit/Source/web/SpeechRecognitionClientProxy.cpp
+++ b/third_party/WebKit/Source/modules/speech/SpeechRecognitionClientProxy.cpp
@@ -23,7 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "web/SpeechRecognitionClientProxy.h"
+#include "modules/speech/SpeechRecognitionClientProxy.h"
 
 #include <memory>
 #include "core/dom/ExecutionContext.h"
@@ -120,15 +120,17 @@
 
   HeapVector<Member<SpeechRecognitionResult>> final_results_vector(
       new_final_results.size());
-  for (size_t i = 0; i < new_final_results.size(); ++i)
+  for (size_t i = 0; i < new_final_results.size(); ++i) {
     final_results_vector[i] =
         Member<SpeechRecognitionResult>(new_final_results[i]);
+  }
 
   HeapVector<Member<SpeechRecognitionResult>> interim_results_vector(
       current_interim_results.size());
-  for (size_t i = 0; i < current_interim_results.size(); ++i)
+  for (size_t i = 0; i < current_interim_results.size(); ++i) {
     interim_results_vector[i] =
         Member<SpeechRecognitionResult>(current_interim_results[i]);
+  }
 
   recognition->DidReceiveResults(final_results_vector, interim_results_vector);
 }
diff --git a/third_party/WebKit/Source/web/SpeechRecognitionClientProxy.h b/third_party/WebKit/Source/modules/speech/SpeechRecognitionClientProxy.h
similarity index 94%
rename from third_party/WebKit/Source/web/SpeechRecognitionClientProxy.h
rename to third_party/WebKit/Source/modules/speech/SpeechRecognitionClientProxy.h
index 018910c..1c8a95d 100644
--- a/third_party/WebKit/Source/web/SpeechRecognitionClientProxy.h
+++ b/third_party/WebKit/Source/modules/speech/SpeechRecognitionClientProxy.h
@@ -27,6 +27,7 @@
 #define SpeechRecognitionClientProxy_h
 
 #include <memory>
+#include "modules/ModulesExport.h"
 #include "modules/speech/SpeechRecognitionClient.h"
 #include "platform/wtf/Compiler.h"
 #include "platform/wtf/text/WTFString.h"
@@ -38,8 +39,9 @@
 class WebSpeechRecognizer;
 class WebString;
 
-class SpeechRecognitionClientProxy final : public SpeechRecognitionClient,
-                                           public WebSpeechRecognizerClient {
+class MODULES_EXPORT SpeechRecognitionClientProxy final
+    : public NON_EXPORTED_BASE(SpeechRecognitionClient),
+      public WebSpeechRecognizerClient {
  public:
   ~SpeechRecognitionClientProxy() override;
 
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
index e214fdd5..1d95bc7 100644
--- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -31,7 +31,6 @@
 #include "public/platform/WebURLRequest.h"
 
 #include <memory>
-#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/loader/fetch/ResourceRequest.h"
 #include "platform/wtf/Allocator.h"
 #include "platform/wtf/Noncopyable.h"
@@ -402,9 +401,7 @@
 }
 
 WebURLRequest::LoadingIPCType WebURLRequest::GetLoadingIPCType() const {
-  if (RuntimeEnabledFeatures::loadingWithMojoEnabled())
-    return WebURLRequest::LoadingIPCType::kMojo;
-  return WebURLRequest::LoadingIPCType::kChromeIPC;
+  return resource_request_->GetLoadingIPCType();
 }
 
 void WebURLRequest::SetNavigationStartTime(double navigation_start_seconds) {
diff --git a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
index 2c8bbc3..465b30df 100644
--- a/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
+++ b/third_party/WebKit/Source/platform/graphics/BitmapImage.cpp
@@ -80,7 +80,7 @@
       size_available_(false),
       have_frame_count_(false),
       repetition_count_status_(kUnknown),
-      repetition_count_(kCAnimationNone),
+      repetition_count_(kAnimationNone),
       repetitions_complete_(0),
       desired_frame_start_time_(0),
       frame_count_(0) {}
@@ -98,7 +98,7 @@
       size_available_(true),
       have_frame_count_(true),
       repetition_count_status_(kUnknown),
-      repetition_count_(kCAnimationNone),
+      repetition_count_(kAnimationNone),
       repetitions_complete_(0),
       frame_count_(1) {
   // Since we don't have a decoder, we can't figure out the image orientation.
@@ -158,7 +158,7 @@
   frames_[index].orientation_ = source_.OrientationAtIndex(index);
   frames_[index].have_metadata_ = true;
   frames_[index].is_complete_ = source_.FrameIsCompleteAtIndex(index);
-  if (RepetitionCount(false) != kCAnimationNone)
+  if (RepetitionCount(false) != kAnimationNone)
     frames_[index].duration_ = source_.FrameDurationAtIndex(index);
   frames_[index].has_alpha_ = source_.FrameHasAlphaAtIndex(index);
   frames_[index].frame_bytes_ = source_.FrameBytesAtIndex(index);
@@ -441,7 +441,7 @@
     // the count again once the whole image is decoded.
     repetition_count_ = source_.RepetitionCount();
     repetition_count_status_ =
-        (image_known_to_be_complete || repetition_count_ == kCAnimationNone)
+        (image_known_to_be_complete || repetition_count_ == kAnimationNone)
             ? kCertain
             : kUncertain;
   }
@@ -449,7 +449,7 @@
 }
 
 bool BitmapImage::ShouldAnimate() {
-  bool animated = RepetitionCount(false) != kCAnimationNone &&
+  bool animated = RepetitionCount(false) != kAnimationNone &&
                   !animation_finished_ && GetImageObserver();
   if (animated && animation_policy_ == kImageAnimationPolicyNoAnimation)
     animated = false;
@@ -475,7 +475,7 @@
   // in a GIF can potentially come after all the rest of the image data, so
   // wait on it.
   if (!all_data_received_ &&
-      (RepetitionCount(false) == kCAnimationLoopOnce ||
+      (RepetitionCount(false) == kAnimationLoopOnce ||
        animation_policy_ == kImageAnimationPolicyAnimateOnce) &&
       current_frame_ >= (FrameCount() - 1))
     return;
@@ -568,7 +568,7 @@
   if (FrameCount() > 1)
     return true;
 
-  return source_.RepetitionCount() != kCAnimationNone;
+  return source_.RepetitionCount() != kAnimationNone;
 }
 
 void BitmapImage::AdvanceTime(double delta_time_in_seconds) {
@@ -612,7 +612,7 @@
     // now, so it should now be available.
     // We don't need to special-case cAnimationLoopOnce here because it is
     // 0 (see comments on its declaration in ImageAnimation.h).
-    if ((RepetitionCount(true) != kCAnimationLoopInfinite &&
+    if ((RepetitionCount(true) != kAnimationLoopInfinite &&
          repetitions_complete_ > repetition_count_) ||
         animation_policy_ == kImageAnimationPolicyAnimateOnce) {
       animation_finished_ = true;
diff --git a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
index cedd523..79bddb6 100644
--- a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoder.cpp
@@ -85,7 +85,7 @@
 DeferredImageDecoder::DeferredImageDecoder(
     std::unique_ptr<ImageDecoder> actual_decoder)
     : actual_decoder_(std::move(actual_decoder)),
-      repetition_count_(kCAnimationNone),
+      repetition_count_(kAnimationNone),
       all_data_received_(false),
       can_yuv_decode_(false),
       has_hot_spot_(false) {}
@@ -266,7 +266,7 @@
   color_space_for_sk_images_ = actual_decoder_->ColorSpaceForSkImages();
 
   const bool is_single_frame =
-      actual_decoder_->RepetitionCount() == kCAnimationNone ||
+      actual_decoder_->RepetitionCount() == kAnimationNone ||
       (all_data_received_ && actual_decoder_->FrameCount() == 1u);
   const SkISize decoded_size =
       SkISize::Make(actual_decoder_->DecodedSize().Width(),
diff --git a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
index 2e0e007..1518f51 100644
--- a/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/DeferredImageDecoderTest.cpp
@@ -112,7 +112,7 @@
     bitmap_.allocPixels(SkImageInfo::MakeN32Premul(100, 100));
     canvas_ = base::MakeUnique<cc::SkiaPaintCanvas>(bitmap_);
     decode_request_count_ = 0;
-    repetition_count_ = kCAnimationNone;
+    repetition_count_ = kAnimationNone;
     status_ = ImageFrame::kFrameComplete;
     frame_duration_ = 0;
     decoded_size_ = actual_decoder_->Size();
diff --git a/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
index a56f0cf..3c655965 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageDecodingStoreTest.cpp
@@ -54,7 +54,7 @@
   ImageFrame::Status GetStatus() override { return ImageFrame::kFramePartial; }
 
   size_t FrameCount() override { return 1; }
-  int RepetitionCount() const override { return kCAnimationNone; }
+  int RepetitionCount() const override { return kAnimationNone; }
   float FrameDuration() const override { return 0; }
 
  protected:
diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
index e7fe76d..e022cdf 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGeneratorTest.cpp
@@ -89,7 +89,7 @@
 
   size_t FrameCount() override { return frame_count_; }
   int RepetitionCount() const override {
-    return frame_count_ == 1 ? kCAnimationNone : kCAnimationLoopOnce;
+    return frame_count_ == 1 ? kAnimationNone : kAnimationLoopOnce;
   }
   float FrameDuration() const override { return 0; }
 
diff --git a/third_party/WebKit/Source/platform/graphics/ImageSource.cpp b/third_party/WebKit/Source/platform/graphics/ImageSource.cpp
index 85de405..ccac03fb 100644
--- a/third_party/WebKit/Source/platform/graphics/ImageSource.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ImageSource.cpp
@@ -100,7 +100,7 @@
 }
 
 int ImageSource::RepetitionCount() {
-  return decoder_ ? decoder_->RepetitionCount() : kCAnimationNone;
+  return decoder_ ? decoder_->RepetitionCount() : kAnimationNone;
 }
 
 size_t ImageSource::FrameCount() const {
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageAnimation.h b/third_party/WebKit/Source/platform/image-decoders/ImageAnimation.h
index de03898..26c8442 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageAnimation.h
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageAnimation.h
@@ -34,17 +34,17 @@
 // animated GIF should be cycled.  If the loop count is absent, the animation
 // cycles once; if it is 0, the animation cycles infinitely; otherwise the
 // animation plays n + 1 cycles (where n is the specified loop count).  If the
-// GIF decoder defaults to kCAnimationLoopOnce in the absence of any loop count
-// and translates an explicit "0" loop count to kCAnimationLoopInfinite, then we
+// GIF decoder defaults to kAnimationLoopOnce in the absence of any loop count
+// and translates an explicit "0" loop count to kAnimationLoopInfinite, then we
 // get a couple of nice side effects:
-//   * By making kCAnimationLoopOnce be 0, we allow the animation cycling code
-//     in BitmapImage.cpp to avoid special-casing it, and simply treat all
+//   * By making kAnimationLoopOnce be 0, we allow the animation cycling code in
+//     BitmapImage.cpp to avoid special-casing it, and simply treat all
 //     non-negative loop counts identically.
 //   * By making the other two constants negative, we avoid conflicts with any
 //     real loop count values.
-const int kCAnimationLoopOnce = 0;
-const int kCAnimationLoopInfinite = -1;
-const int kCAnimationNone = -2;
+const int kAnimationLoopOnce = 0;
+const int kAnimationLoopInfinite = -1;
+const int kAnimationNone = -2;
 
 }  // namespace blink
 
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
index a41bf4e6..ad951bf 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
@@ -183,7 +183,7 @@
   // correct size and returns its size.
   size_t FrameCount();
 
-  virtual int RepetitionCount() const { return kCAnimationNone; }
+  virtual int RepetitionCount() const { return kAnimationNone; }
 
   // Decodes as much of the requested frame as possible, and returns an
   // ImageDecoder-owned pointer.
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
index 42f4536..41643a03 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
@@ -235,7 +235,7 @@
       EXPECT_TRUE(decoder->Size().IsEmpty());
       EXPECT_FALSE(decoder->HasEmbeddedColorSpace());
       EXPECT_EQ(0u, decoder->FrameCount());
-      EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+      EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
       EXPECT_FALSE(decoder->FrameBufferAtIndex(0));
     } else {
       EXPECT_TRUE(decoder->IsSizeAvailable());
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
index 5ee289a4..845fba9a 100644
--- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -36,7 +36,7 @@
                                  const ColorBehavior& color_behavior,
                                  size_t max_decoded_bytes)
     : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
-      repetition_count_(kCAnimationLoopOnce) {}
+      repetition_count_(kAnimationLoopOnce) {}
 
 GIFImageDecoder::~GIFImageDecoder() {}
 
@@ -71,9 +71,9 @@
   // later in the stream. It is also possible that no frames are in the
   // stream. In these cases we should just loop once.
   if (IsAllDataReceived() && ParseCompleted() && reader_->imagesCount() == 1)
-    repetition_count_ = kCAnimationNone;
+    repetition_count_ = kAnimationNone;
   else if (Failed() || (reader_ && (!reader_->imagesCount())))
-    repetition_count_ = kCAnimationLoopOnce;
+    repetition_count_ = kAnimationLoopOnce;
   else if (reader_ && reader_->loopCount() != cLoopCountNotSeen)
     repetition_count_ = reader_->loopCount();
   return repetition_count_;
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
index 580b7a2..79ced47 100644
--- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoderTest.cpp
@@ -59,7 +59,7 @@
   RefPtr<SharedBuffer> data = ReadFile(dir, file);
   ASSERT_TRUE(data.Get());
   decoder->SetData(data.Get(), true);
-  EXPECT_EQ(kCAnimationLoopOnce,
+  EXPECT_EQ(kAnimationLoopOnce,
             decoder->RepetitionCount());  // Default value before decode.
 
   for (size_t i = 0; i < decoder->FrameCount(); ++i) {
@@ -79,7 +79,7 @@
   RefPtr<SharedBuffer> data = ReadFile(kLayoutTestResourcesDir, "animated.gif");
   ASSERT_TRUE(data.Get());
   decoder->SetData(data.Get(), true);
-  EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
 
   ImageFrame* frame = decoder->FrameBufferAtIndex(0);
   uint32_t generation_id0 = frame->Bitmap().getGenerationID();
@@ -95,7 +95,7 @@
   EXPECT_TRUE(generation_id0 != generation_id1);
 
   EXPECT_EQ(2u, decoder->FrameCount());
-  EXPECT_EQ(kCAnimationLoopInfinite, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
 }
 
 TEST(GIFImageDecoderTest, parseAndDecode) {
@@ -104,7 +104,7 @@
   RefPtr<SharedBuffer> data = ReadFile(kLayoutTestResourcesDir, "animated.gif");
   ASSERT_TRUE(data.Get());
   decoder->SetData(data.Get(), true);
-  EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
 
   // This call will parse the entire file.
   EXPECT_EQ(2u, decoder->FrameCount());
@@ -118,7 +118,7 @@
   EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
   EXPECT_EQ(16, frame->Bitmap().width());
   EXPECT_EQ(16, frame->Bitmap().height());
-  EXPECT_EQ(kCAnimationLoopInfinite, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
 }
 
 TEST(GIFImageDecoderTest, parseByteByByte) {
@@ -142,13 +142,13 @@
 
   decoder->FrameBufferAtIndex(0);
   decoder->FrameBufferAtIndex(1);
-  EXPECT_EQ(kCAnimationLoopInfinite, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
 }
 
 TEST(GIFImageDecoderTest, parseAndDecodeByteByByte) {
   TestByteByByteDecode(&CreateDecoder, kLayoutTestResourcesDir,
                        "animated-gif-with-offsets.gif", 5u,
-                       kCAnimationLoopInfinite);
+                       kAnimationLoopInfinite);
 }
 
 TEST(GIFImageDecoderTest, brokenSecondFrame) {
@@ -199,7 +199,7 @@
   EXPECT_FALSE(decoder->Failed());
   EXPECT_TRUE(decoder->FrameIsCompleteAtIndex(0));
   EXPECT_TRUE(decoder->FrameIsCompleteAtIndex(1));
-  EXPECT_EQ(kCAnimationLoopInfinite, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
 }
 
 TEST(GIFImageDecoderTest, frameIsCompleteLoading) {
@@ -353,7 +353,7 @@
 
 TEST(GIFImageDecoderTest, verifyRepetitionCount) {
   TestRepetitionCount(kLayoutTestResourcesDir, "full2loop.gif", 2);
-  TestRepetitionCount(kDecodersTestingDir, "radient.gif", kCAnimationNone);
+  TestRepetitionCount(kDecodersTestingDir, "radient.gif", kAnimationNone);
 }
 
 TEST(GIFImageDecoderTest, bitmapAlphaType) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp
index ea8a630..38cf46e 100644
--- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageReader.cpp
@@ -684,7 +684,7 @@
 
           // Zero loop count is infinite animation loop request.
           if (!m_loopCount)
-            m_loopCount = blink::kCAnimationLoopInfinite;
+            m_loopCount = blink::kAnimationLoopInfinite;
 
           GETN(1, GIFNetscapeExtensionBlock);
         } else if (netscapeExtension == 2) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp
index 576710e8..37bd35d 100644
--- a/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/ico/ICOImageDecoderTest.cpp
@@ -70,22 +70,22 @@
 TEST(ICOImageDecoderTests, parseAndDecodeByteByByte) {
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/png-in-ico.ico", 1u,
-                       kCAnimationNone);
+                       kAnimationNone);
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/2entries.ico", 2u,
-                       kCAnimationNone);
+                       kAnimationNone);
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/greenbox-3frames.cur", 3u,
-                       kCAnimationNone);
+                       kAnimationNone);
   TestByteByByteDecode(
       &CreateDecoder,
       "/LayoutTests/images/resources/icon-without-and-bitmap.ico", 1u,
-      kCAnimationNone);
+      kAnimationNone);
   TestByteByByteDecode(&CreateDecoder, "/LayoutTests/images/resources/1bit.ico",
-                       1u, kCAnimationNone);
+                       1u, kAnimationNone);
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/bug653075.ico", 2u,
-                       kCAnimationNone);
+                       kAnimationNone);
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp
index 54e2d78b..03cb8fe 100644
--- a/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/jpeg/JPEGImageDecoderTest.cpp
@@ -273,20 +273,20 @@
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/"
                        "small-square-with-colorspin-profile.jpg",
-                       1u, kCAnimationNone);
+                       1u, kAnimationNone);
 }
 
 TEST(JPEGImageDecoderTest, byteByByteProgressiveJPEG) {
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/bug106024.jpg", 1u,
-                       kCAnimationNone);
+                       kAnimationNone);
 }
 
 TEST(JPEGImageDecoderTest, byteByByteRGBJPEGWithAdobeMarkers) {
   TestByteByByteDecode(
       &CreateDecoder,
       "/LayoutTests/images/resources/rgb-jpeg-with-adobe-marker-only.jpg", 1u,
-      kCAnimationNone);
+      kAnimationNone);
 }
 
 // This test verifies that calling SharedBuffer::MergeSegmentsIntoBuffer() does
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
index 9890b7c..0e12da8 100644
--- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -47,10 +47,10 @@
     : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
       offset_(offset),
       current_frame_(0),
-      // It would be logical to default to kCAnimationNone, but BitmapImage uses
+      // It would be logical to default to kAnimationNone, but BitmapImage uses
       // that as a signal to never check again, meaning the actual count will
       // never be respected.
-      repetition_count_(kCAnimationLoopOnce),
+      repetition_count_(kAnimationLoopOnce),
       has_alpha_channel_(false),
       current_buffer_saw_alpha_(false) {}
 
@@ -122,7 +122,7 @@
 }
 
 int PNGImageDecoder::RepetitionCount() const {
-  return Failed() ? kCAnimationLoopOnce : repetition_count_;
+  return Failed() ? kAnimationLoopOnce : repetition_count_;
 }
 
 void PNGImageDecoder::InitializeNewFrame(size_t index) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp
index 4bfa9c3..17e8f45 100644
--- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageDecoderTest.cpp
@@ -171,7 +171,7 @@
   ASSERT_NE(nullptr, frame);
   EXPECT_EQ(ImageFrame::kFrameComplete, frame->GetStatus());
   EXPECT_FALSE(decoder->Failed());
-  EXPECT_EQ(kCAnimationNone, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationNone, decoder->RepetitionCount());
 }
 
 // Decode up to the indicated fcTL offset and then provide an fcTL with the
@@ -312,7 +312,7 @@
   TestRepetitionCount(
       "/LayoutTests/images/resources/"
       "png-animated-idat-not-part-of-animation.png",
-      kCAnimationNone);
+      kAnimationNone);
 }
 
 // Test if the decoded metdata corresponds to the defined expectations
@@ -456,7 +456,7 @@
     decoder->SetData(no_actl_data, true);
     EXPECT_EQ(1u, decoder->FrameCount());
     EXPECT_FALSE(decoder->Failed());
-    EXPECT_EQ(kCAnimationNone, decoder->RepetitionCount());
+    EXPECT_EQ(kAnimationNone, decoder->RepetitionCount());
   }
 
   // Store the acTL for more tests.
@@ -506,7 +506,7 @@
       decoder->SetData(extra_actl_data, true);
       EXPECT_EQ(1u, decoder->FrameCount());
       EXPECT_FALSE(decoder->Failed());
-      EXPECT_EQ(kCAnimationNone, decoder->RepetitionCount());
+      EXPECT_EQ(kAnimationNone, decoder->RepetitionCount());
       EXPECT_NE(nullptr, decoder->FrameBufferAtIndex(0));
       EXPECT_FALSE(decoder->Failed());
     }
@@ -936,14 +936,14 @@
   ASSERT_EQ(original_data->size(), data->size());
 
   // This will test both byte by byte and using the full data, and compare.
-  TestByteByByteDecode(CreateDecoder, data.Get(), 1, kCAnimationNone);
+  TestByteByByteDecode(CreateDecoder, data.Get(), 1, kAnimationNone);
 }
 
 // Static PNG tests
 
 TEST(StaticPNGTests, repetitionCountTest) {
   TestRepetitionCount("/LayoutTests/images/resources/png-simple.png",
-                      kCAnimationNone);
+                      kAnimationNone);
 }
 
 TEST(StaticPNGTests, sizeTest) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp
index f43cbdf..3a3268c7 100644
--- a/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/png/PNGImageReader.cpp
@@ -535,7 +535,7 @@
       if (ignore_animation_)
         is_animated_ = false;
       if (!is_animated_ || 1 == reported_frame_count_)
-        decoder_->SetRepetitionCount(kCAnimationNone);
+        decoder_->SetRepetitionCount(kAnimationNone);
       if (!decoder_->SetSize(width_, height_))
         return false;
       decoder_->SetColorSpace();
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 12e0b2f..2fdf29e 100644
--- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -126,7 +126,7 @@
       demux_(0),
       demux_state_(WEBP_DEMUX_PARSING_HEADER),
       have_already_parsed_this_data_(false),
-      repetition_count_(kCAnimationLoopOnce),
+      repetition_count_(kAnimationLoopOnce),
       decoded_height_(0) {
   blend_function_ = (alpha_option == kAlphaPremultiplied)
                         ? alphaBlendPremultiplied
@@ -156,7 +156,7 @@
 }
 
 int WEBPImageDecoder::RepetitionCount() const {
-  return Failed() ? kCAnimationLoopOnce : repetition_count_;
+  return Failed() ? kAnimationLoopOnce : repetition_count_;
 }
 
 bool WEBPImageDecoder::FrameIsCompleteAtIndex(size_t index) const {
@@ -211,7 +211,7 @@
 
     format_flags_ = WebPDemuxGetI(demux_, WEBP_FF_FORMAT_FLAGS);
     if (!(format_flags_ & ANIMATION_FLAG)) {
-      repetition_count_ = kCAnimationNone;
+      repetition_count_ = kAnimationNone;
     } else {
       // Since we have parsed at least one frame, even if partially,
       // the global animation (ANIM) properties have been read since
@@ -220,7 +220,7 @@
       // Repetition count is always <= 16 bits.
       DCHECK_EQ(repetition_count_, repetition_count_ & 0xffff);
       if (!repetition_count_)
-        repetition_count_ = kCAnimationLoopInfinite;
+        repetition_count_ = kAnimationLoopInfinite;
       // FIXME: Implement ICC profile support for animated images.
       format_flags_ &= ~ICCP_FLAG;
     }
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp
index b39b9ad..db4ea63 100644
--- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp
+++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoderTest.cpp
@@ -75,7 +75,7 @@
     ASSERT_TRUE(frame);
     EXPECT_EQ(ImageFrame::kFramePartial, frame->GetStatus());
   }
-  EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
   EXPECT_TRUE(decoder->Failed());
 }
 
@@ -99,7 +99,7 @@
 
 TEST(AnimatedWebPTests, verifyAnimationParametersTransparentImage) {
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
-  EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-animated.webp");
@@ -140,13 +140,13 @@
   }
 
   EXPECT_EQ(WTF_ARRAY_LENGTH(kFrameParameters), decoder->FrameCount());
-  EXPECT_EQ(kCAnimationLoopInfinite, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
 }
 
 TEST(AnimatedWebPTests,
      verifyAnimationParametersOpaqueFramesTransparentBackground) {
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
-  EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-animated-opaque.webp");
@@ -189,12 +189,12 @@
   }
 
   EXPECT_EQ(WTF_ARRAY_LENGTH(kFrameParameters), decoder->FrameCount());
-  EXPECT_EQ(kCAnimationLoopInfinite, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
 }
 
 TEST(AnimatedWebPTests, verifyAnimationParametersBlendOverwrite) {
   std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
-  EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
 
   RefPtr<SharedBuffer> data =
       ReadFile("/LayoutTests/images/resources/webp-animated-no-blend.webp");
@@ -237,13 +237,13 @@
   }
 
   EXPECT_EQ(WTF_ARRAY_LENGTH(kFrameParameters), decoder->FrameCount());
-  EXPECT_EQ(kCAnimationLoopInfinite, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopInfinite, decoder->RepetitionCount());
 }
 
 TEST(AnimatedWebPTests, parseAndDecodeByteByByte) {
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/webp-animated.webp", 3u,
-                       kCAnimationLoopInfinite);
+                       kAnimationLoopInfinite);
   TestByteByByteDecode(
       &CreateDecoder,
       "/LayoutTests/images/resources/webp-animated-icc-xmp.webp", 13u, 32000);
@@ -327,7 +327,7 @@
   frame = decoder->FrameBufferAtIndex(0);
   ASSERT_TRUE(frame);
   EXPECT_EQ(ImageFrame::kFramePartial, frame->GetStatus());
-  EXPECT_EQ(kCAnimationLoopOnce, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationLoopOnce, decoder->RepetitionCount());
   EXPECT_TRUE(decoder->Failed());
 }
 
@@ -432,7 +432,7 @@
 TEST(AnimatedWebPTests, isSizeAvailable) {
   TestByteByByteSizeAvailable(
       &CreateDecoder, "/LayoutTests/images/resources/webp-animated.webp", 142u,
-      false, kCAnimationLoopInfinite);
+      false, kAnimationLoopInfinite);
   // FIXME: Add color profile support for animated webp images.
   TestByteByByteSizeAvailable(
       &CreateDecoder,
@@ -528,17 +528,17 @@
 TEST(StaticWebPTests, incrementalDecode) {
   TestByteByByteDecode(&CreateDecoder,
                        "/LayoutTests/images/resources/crbug.364830.webp", 1u,
-                       kCAnimationNone);
+                       kAnimationNone);
 }
 
 TEST(StaticWebPTests, isSizeAvailable) {
   TestByteByByteSizeAvailable(
       &CreateDecoder,
       "/LayoutTests/images/resources/webp-color-profile-lossy.webp", 520u, true,
-      kCAnimationNone);
+      kAnimationNone);
   TestByteByByteSizeAvailable(&CreateDecoder,
                               "/LayoutTests/images/resources/test.webp", 30u,
-                              false, kCAnimationNone);
+                              false, kAnimationNone);
 }
 
 TEST(StaticWebPTests, notAnimated) {
@@ -548,7 +548,7 @@
   ASSERT_TRUE(data.Get());
   decoder->SetData(data.Get(), true);
   EXPECT_EQ(1u, decoder->FrameCount());
-  EXPECT_EQ(kCAnimationNone, decoder->RepetitionCount());
+  EXPECT_EQ(kAnimationNone, decoder->RepetitionCount());
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/loader/fetch/CrossOriginAccessControl.cpp b/third_party/WebKit/Source/platform/loader/fetch/CrossOriginAccessControl.cpp
index 9a7e0144..47f16e8 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/CrossOriginAccessControl.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/CrossOriginAccessControl.cpp
@@ -150,16 +150,11 @@
     const ResourceResponse& response,
     StoredCredentials include_credentials,
     const SecurityOrigin* security_origin) {
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      AtomicString, allow_origin_header_name,
-      (new AtomicString("access-control-allow-origin")));
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      AtomicString, allow_credentials_header_name,
-      (new AtomicString("access-control-allow-credentials")));
-  DEFINE_THREAD_SAFE_STATIC_LOCAL(
-      AtomicString, allow_suborigin_header_name,
-      (new AtomicString("access-control-allow-suborigin")));
-
+  static const char allow_origin_header_name[] = "access-control-allow-origin";
+  static const char allow_credentials_header_name[] =
+      "access-control-allow-credentials";
+  static const char allow_suborigin_header_name[] =
+      "access-control-allow-suborigin";
   int status_code = response.HttpStatusCode();
   if (!status_code)
     return kInvalidResponse;
@@ -181,7 +176,7 @@
     }
   }
 
-  if (allow_origin_header_value == g_star_atom) {
+  if (allow_origin_header_value == "*") {
     // A wildcard Access-Control-Allow-Origin can not be used if credentials are
     // to be sent, even with Access-Control-Allow-Credentials set to true.
     if (include_credentials == kDoNotAllowStoredCredentials)
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
index afa38a3b..c874c07 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -269,7 +269,12 @@
       integrity_disposition_(ResourceIntegrityDisposition::kNotChecked),
       options_(options),
       response_timestamp_(CurrentTime()),
-      cancel_timer_(Platform::Current()->MainThread()->GetWebTaskRunner(),
+      cancel_timer_(IsMainThread()
+                        ? Platform::Current()->MainThread()->GetWebTaskRunner()
+                        : Platform::Current()
+                              ->CurrentThread()
+                              ->Scheduler()
+                              ->LoadingTaskRunner(),
                     this,
                     &Resource::CancelTimerFired),
       resource_request_(request) {
@@ -278,7 +283,8 @@
   // Currently we support the metadata caching only for HTTP family.
   if (GetResourceRequest().Url().ProtocolIsInHTTPFamily())
     cache_handler_ = CachedMetadataHandlerImpl::Create(this);
-  MemoryCoordinator::Instance().RegisterClient(this);
+  if (IsMainThread())
+    MemoryCoordinator::Instance().RegisterClient(this);
 }
 
 Resource::~Resource() {
@@ -357,7 +363,7 @@
   error_ = error;
   is_revalidating_ = false;
 
-  if (error_.IsCancellation() || !IsPreloaded())
+  if ((error_.IsCancellation() || !IsPreloaded()) && IsMainThread())
     GetMemoryCache()->Remove(this);
 
   if (!ErrorOccurred())
@@ -586,7 +592,7 @@
     builder.AppendNumber(preload_count_);
     builder.Append(')');
   }
-  if (GetMemoryCache()->Contains(this)) {
+  if (IsMainThread() && GetMemoryCache()->Contains(this)) {
     if (!builder.IsEmpty())
       builder.Append(' ');
     builder.Append("in_memory_cache");
@@ -712,7 +718,8 @@
     // operation."
     // We allow non-secure content to be reused in history, but we do not allow
     // secure content to be reused.
-    if (HasCacheControlNoStoreHeader() && Url().ProtocolIs("https"))
+    if (HasCacheControlNoStoreHeader() && Url().ProtocolIs("https") &&
+        IsMainThread())
       GetMemoryCache()->Remove(this);
   }
 }
@@ -735,7 +742,8 @@
     return;
   size_t old_size = size();
   decoded_size_ = decoded_size;
-  GetMemoryCache()->Update(this, old_size, size());
+  if (IsMainThread())
+    GetMemoryCache()->Update(this, old_size, size());
 }
 
 void Resource::SetEncodedSize(size_t encoded_size) {
@@ -745,7 +753,8 @@
   size_t old_size = size();
   encoded_size_ = encoded_size;
   encoded_size_memory_usage_ = encoded_size;
-  GetMemoryCache()->Update(this, old_size, size());
+  if (IsMainThread())
+    GetMemoryCache()->Update(this, old_size, size());
 }
 
 void Resource::FinishPendingClients() {
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
index a638d74..4ca1989f 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceFetcher.cpp
@@ -604,7 +604,7 @@
     if (!resource && !is_data_url && archive_)
       return nullptr;
   }
-  if (!resource) {
+  if (!resource && IsMainThread()) {
     resource =
         GetMemoryCache()->ResourceForURL(params.Url(), GetCacheIdentifier());
   }
@@ -751,7 +751,8 @@
     const String& charset,
     const ResourceFactory& factory) {
   const String cache_identifier = GetCacheIdentifier();
-  DCHECK(!GetMemoryCache()->ResourceForURL(params.GetResourceRequest().Url(),
+  DCHECK(!IsMainThread() ||
+         !GetMemoryCache()->ResourceForURL(params.GetResourceRequest().Url(),
                                            cache_identifier));
 
   RESOURCE_LOADING_DVLOG(1) << "Loading Resource for "
@@ -767,7 +768,7 @@
 
   // - Don't add main resource to cache to prevent reuse.
   // - Don't add the resource if its body will not be stored.
-  if (factory.GetType() != Resource::kMainResource &&
+  if (IsMainThread() && factory.GetType() != Resource::kMainResource &&
       params.Options().data_buffering_policy != kDoNotBufferData) {
     GetMemoryCache()->Add(resource);
   }
@@ -1276,9 +1277,10 @@
         prohibit_add_remove_client_in_scope(resource);
     Resource::RevalidationStartForbiddenScope
         revalidation_start_forbidden_scope(resource);
-    ScriptForbiddenScope script_forbidden_scope;
+    ScriptForbiddenIfMainThreadScope script_forbidden_scope;
 
-    if (!Context().ShouldLoadNewResource(resource->GetType())) {
+    if (!Context().ShouldLoadNewResource(resource->GetType()) &&
+        IsMainThread()) {
       GetMemoryCache()->Remove(resource);
       return false;
     }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
index 60db8457..d6a19cc 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.cpp
@@ -75,6 +75,9 @@
       check_for_browser_side_navigation_(true),
       ui_start_time_(0),
       is_external_request_(false),
+      loading_ipc_type_(RuntimeEnabledFeatures::loadingWithMojoEnabled()
+                            ? WebURLRequest::LoadingIPCType::kMojo
+                            : WebURLRequest::LoadingIPCType::kChromeIPC),
       is_same_document_navigation_(false),
       input_perf_metric_report_policy_(
           InputToLoadPerfMetricReportPolicy::kNoReport),
@@ -114,6 +117,7 @@
   check_for_browser_side_navigation_ = data->check_for_browser_side_navigation_;
   ui_start_time_ = data->ui_start_time_;
   is_external_request_ = data->is_external_request_;
+  loading_ipc_type_ = data->loading_ipc_type_;
   input_perf_metric_report_policy_ = data->input_perf_metric_report_policy_;
   redirect_status_ = data->redirect_status_;
 }
@@ -162,6 +166,7 @@
   data->check_for_browser_side_navigation_ = check_for_browser_side_navigation_;
   data->ui_start_time_ = ui_start_time_;
   data->is_external_request_ = is_external_request_;
+  data->loading_ipc_type_ = loading_ipc_type_;
   data->input_perf_metric_report_policy_ = input_perf_metric_report_policy_;
   data->redirect_status_ = redirect_status_;
   return data;
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
index a3e1fdf2..9964ecd 100644
--- a/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
+++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceRequest.h
@@ -299,6 +299,13 @@
   bool IsExternalRequest() const { return is_external_request_; }
   void SetExternalRequestStateFromRequestorAddressSpace(WebAddressSpace);
 
+  void OverrideLoadingIPCType(WebURLRequest::LoadingIPCType loading_ipc_type) {
+    loading_ipc_type_ = loading_ipc_type;
+  }
+  WebURLRequest::LoadingIPCType GetLoadingIPCType() const {
+    return loading_ipc_type_;
+  }
+
   InputToLoadPerfMetricReportPolicy InputPerfMetricReportPolicy() const {
     return input_perf_metric_report_policy_;
   }
@@ -358,6 +365,7 @@
   bool check_for_browser_side_navigation_;
   double ui_start_time_;
   bool is_external_request_;
+  WebURLRequest::LoadingIPCType loading_ipc_type_;
   bool is_same_document_navigation_;
   InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
 
@@ -410,6 +418,7 @@
   bool check_for_browser_side_navigation_;
   double ui_start_time_;
   bool is_external_request_;
+  WebURLRequest::LoadingIPCType loading_ipc_type_;
   InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
   ResourceRequest::RedirectStatus redirect_status_;
 };
diff --git a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
index 4ef02ef7..9fc57c7 100644
--- a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
+++ b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
@@ -226,6 +226,7 @@
 
   RefPtr<SharedBuffer> packet_data = SharedBuffer::Create();
   size_t position = 0;
+  size_t next_frame_to_decode = 0;
   while (true) {
     const char* packet;
     size_t length = data->GetSomeData(packet, position);
@@ -235,12 +236,14 @@
     position += length;
 
     bool all_data_received = position == data->size();
-    decoder->SetData(packet_data.Get(), all_data_received);
-
-    int frame_count = decoder->FrameCount();
-    for (int i = 0; i < frame_count; ++i) {
-      if (!decoder->FrameBufferAtIndex(i))
+    size_t frame_count = decoder->FrameCount();
+    for (; next_frame_to_decode < frame_count; ++next_frame_to_decode) {
+      decoder->SetData(packet_data.Get(), all_data_received);
+      ImageFrame* frame = decoder->FrameBufferAtIndex(next_frame_to_decode);
+      if (frame->GetStatus() != ImageFrame::kFrameComplete)
         break;
+      decoder->SetData(PassRefPtr<SegmentReader>(nullptr), false);
+      decoder->ClearCacheExceptFrame(next_frame_to_decode);
     }
 
     if (all_data_received || decoder->Failed())
diff --git a/third_party/WebKit/Source/web/BUILD.gn b/third_party/WebKit/Source/web/BUILD.gn
index d5a93ed..d3cd52fe6 100644
--- a/third_party/WebKit/Source/web/BUILD.gn
+++ b/third_party/WebKit/Source/web/BUILD.gn
@@ -106,8 +106,6 @@
     "ServiceWorkerGlobalScopeClientImpl.h",
     "ServiceWorkerGlobalScopeProxy.cpp",
     "ServiceWorkerGlobalScopeProxy.h",
-    "SpeechRecognitionClientProxy.cpp",
-    "SpeechRecognitionClientProxy.h",
     "SpellCheckerClientImpl.cpp",
     "SpellCheckerClientImpl.h",
     "StorageClientImpl.cpp",
@@ -206,9 +204,6 @@
     "WebSharedWorkerImpl.h",
     "WebSharedWorkerReportingProxyImpl.cpp",
     "WebSharedWorkerReportingProxyImpl.h",
-    "WebSpeechGrammar.cpp",
-    "WebSpeechRecognitionHandle.cpp",
-    "WebSpeechRecognitionResult.cpp",
     "WebStorageEventDispatcherImpl.cpp",
     "WebSurroundingText.cpp",
     "WebTextCheckingCompletionImpl.cpp",
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index 4f6f905..30bf6d3 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -91,6 +91,7 @@
 #include "modules/accessibility/AXObjectCacheImpl.h"
 #include "modules/credentialmanager/CredentialManagerClient.h"
 #include "modules/encryptedmedia/MediaKeysController.h"
+#include "modules/speech/SpeechRecognitionClientProxy.h"
 #include "modules/storage/StorageNamespaceController.h"
 #include "modules/webdatabase/DatabaseClient.h"
 #include "modules/webgl/WebGLRenderingContext.h"
@@ -164,7 +165,6 @@
 #include "web/LinkHighlightImpl.h"
 #include "web/PageOverlay.h"
 #include "web/PrerendererClientImpl.h"
-#include "web/SpeechRecognitionClientProxy.h"
 #include "web/StorageQuotaClientImpl.h"
 #include "web/ValidationMessageClientImpl.h"
 #include "web/WebDevToolsAgentImpl.h"