diff --git a/DEPS b/DEPS
index 9fdc181..b62fcb3 100644
--- a/DEPS
+++ b/DEPS
@@ -39,11 +39,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '88fa7476ab923923022bcf75b72d94adf8a3b5bc',
+  'skia_revision': 'c7165c239a0068b0b79b1bbe63e2a22bcb53ae38',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '093de95395ae4fc559b7719d8cea35bb778d3101',
+  'v8_revision': '55eb1195b010521a1e005f2aad1494cef0c3d1d4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -95,7 +95,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '7bd27cc8aa245e48f12ac3cb131c9d48597db9fa',
+  'catapult_revision': '5b5774b1223d05518b1d75da409297ebcf93e24a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/WATCHLISTS b/WATCHLISTS
index 62740659..156484b1 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -75,7 +75,8 @@
                   'chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java',
     },
     'android_webapk': {
-      'filepath': 'chrome/android/webapk/'
+      'filepath': 'chrome/android/webapk/|'\
+                  'chrome/browser/android/webapk/',
     },
     'android_webview': {
       'filepath': 'android_webview/',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 5e8547f..166ae62d 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1223,7 +1223,6 @@
     "common/system/chromeos/session/logout_confirmation_controller_unittest.cc",
     "common/system/chromeos/session/tray_session_length_limit_unittest.cc",
     "common/system/chromeos/supervised/tray_supervised_user_unittest.cc",
-    "common/system/date/date_view_unittest.cc",
     "common/system/ime/tray_ime_chromeos_unittest.cc",
     "common/system/tiles/tray_tiles_unittest.cc",
     "common/system/tray/system_tray_unittest.cc",
diff --git a/ash/common/BUILD.gn b/ash/common/BUILD.gn
index 0cbebfffa..ff59cb6 100644
--- a/ash/common/BUILD.gn
+++ b/ash/common/BUILD.gn
@@ -6,6 +6,7 @@
   testonly = true
   sources = [
     "accelerators/accelerator_table_unittest.cc",
+    "system/date/date_view_unittest.cc",
     "system/update/tray_update_unittest.cc",
     "wm/container_finder_unittest.cc",
     "wm/mru_window_tracker_unittest.cc",
diff --git a/ash/common/system/date/date_view_unittest.cc b/ash/common/system/date/date_view_unittest.cc
index df7d639..deec34c 100644
--- a/ash/common/system/date/date_view_unittest.cc
+++ b/ash/common/system/date/date_view_unittest.cc
@@ -4,13 +4,13 @@
 
 #include "ash/common/system/date/date_view.h"
 
-#include "ash/test/ash_test_base.h"
+#include "ash/common/test/ash_test.h"
 #include "ui/views/controls/label.h"
 
 namespace ash {
 namespace tray {
 
-class TimeViewTest : public ash::test::AshTestBase {
+class TimeViewTest : public AshTest {
  public:
   TimeViewTest() {}
   ~TimeViewTest() override {}
diff --git a/cc/blink/web_compositor_support_impl.cc b/cc/blink/web_compositor_support_impl.cc
index be6d95e9b..ac2b815 100644
--- a/cc/blink/web_compositor_support_impl.cc
+++ b/cc/blink/web_compositor_support_impl.cc
@@ -4,8 +4,9 @@
 
 #include "cc/blink/web_compositor_support_impl.h"
 
-#include <memory>
+#include <utility>
 
+#include "base/memory/ptr_util.h"
 #include "cc/blink/web_content_layer_impl.h"
 #include "cc/blink/web_display_item_list_impl.h"
 #include "cc/blink/web_external_texture_layer_impl.h"
@@ -35,44 +36,49 @@
 WebCompositorSupportImpl::~WebCompositorSupportImpl() {
 }
 
-WebLayer* WebCompositorSupportImpl::createLayer() {
-  return new WebLayerImpl();
+std::unique_ptr<WebLayer> WebCompositorSupportImpl::createLayer() {
+  return base::MakeUnique<WebLayerImpl>();
 }
 
-WebLayer* WebCompositorSupportImpl::createLayerFromCCLayer(cc::Layer* layer) {
-  return new WebLayerImpl(layer);
+std::unique_ptr<WebLayer> WebCompositorSupportImpl::createLayerFromCCLayer(
+    cc::Layer* layer) {
+  return base::MakeUnique<WebLayerImpl>(layer);
 }
 
-WebContentLayer* WebCompositorSupportImpl::createContentLayer(
+std::unique_ptr<WebContentLayer> WebCompositorSupportImpl::createContentLayer(
     WebContentLayerClient* client) {
-  return new WebContentLayerImpl(client);
+  return base::MakeUnique<WebContentLayerImpl>(client);
 }
 
-WebExternalTextureLayer* WebCompositorSupportImpl::createExternalTextureLayer(
+std::unique_ptr<WebExternalTextureLayer>
+WebCompositorSupportImpl::createExternalTextureLayer(
     cc::TextureLayerClient* client) {
-  return new WebExternalTextureLayerImpl(client);
+  return base::MakeUnique<WebExternalTextureLayerImpl>(client);
 }
 
-blink::WebImageLayer* WebCompositorSupportImpl::createImageLayer() {
-  return new WebImageLayerImpl();
+std::unique_ptr<blink::WebImageLayer>
+WebCompositorSupportImpl::createImageLayer() {
+  return base::MakeUnique<WebImageLayerImpl>();
 }
 
-WebScrollbarLayer* WebCompositorSupportImpl::createScrollbarLayer(
-    WebScrollbar* scrollbar,
+std::unique_ptr<WebScrollbarLayer>
+WebCompositorSupportImpl::createScrollbarLayer(
+    std::unique_ptr<WebScrollbar> scrollbar,
     WebScrollbarThemePainter painter,
-    WebScrollbarThemeGeometry* geometry) {
-  return new WebScrollbarLayerImpl(scrollbar, painter, geometry);
+    std::unique_ptr<WebScrollbarThemeGeometry> geometry) {
+  return base::MakeUnique<WebScrollbarLayerImpl>(std::move(scrollbar), painter,
+                                                 std::move(geometry));
 }
 
-WebScrollbarLayer* WebCompositorSupportImpl::createSolidColorScrollbarLayer(
+std::unique_ptr<WebScrollbarLayer>
+WebCompositorSupportImpl::createSolidColorScrollbarLayer(
     WebScrollbar::Orientation orientation,
     int thumb_thickness,
     int track_start,
     bool is_left_side_vertical_scrollbar) {
-  return new WebScrollbarLayerImpl(orientation,
-                                   thumb_thickness,
-                                   track_start,
-                                   is_left_side_vertical_scrollbar);
+  return base::MakeUnique<WebScrollbarLayerImpl>(
+      orientation, thumb_thickness, track_start,
+      is_left_side_vertical_scrollbar);
 }
 
 }  // namespace cc_blink
diff --git a/cc/blink/web_compositor_support_impl.h b/cc/blink/web_compositor_support_impl.h
index d402d85..91a205a 100644
--- a/cc/blink/web_compositor_support_impl.h
+++ b/cc/blink/web_compositor_support_impl.h
@@ -20,18 +20,18 @@
   WebCompositorSupportImpl();
   ~WebCompositorSupportImpl() override;
 
-  blink::WebLayer* createLayer() override;
-  blink::WebLayer* createLayerFromCCLayer(cc::Layer*) override;
-  blink::WebContentLayer* createContentLayer(
+  std::unique_ptr<blink::WebLayer> createLayer() override;
+  std::unique_ptr<blink::WebLayer> createLayerFromCCLayer(cc::Layer*) override;
+  std::unique_ptr<blink::WebContentLayer> createContentLayer(
       blink::WebContentLayerClient* client) override;
-  blink::WebExternalTextureLayer* createExternalTextureLayer(
+  std::unique_ptr<blink::WebExternalTextureLayer> createExternalTextureLayer(
       cc::TextureLayerClient* client) override;
-  blink::WebImageLayer* createImageLayer() override;
-  blink::WebScrollbarLayer* createScrollbarLayer(
-      blink::WebScrollbar* scrollbar,
+  std::unique_ptr<blink::WebImageLayer> createImageLayer() override;
+  std::unique_ptr<blink::WebScrollbarLayer> createScrollbarLayer(
+      std::unique_ptr<blink::WebScrollbar> scrollbar,
       blink::WebScrollbarThemePainter painter,
-      blink::WebScrollbarThemeGeometry*) override;
-  blink::WebScrollbarLayer* createSolidColorScrollbarLayer(
+      std::unique_ptr<blink::WebScrollbarThemeGeometry>) override;
+  std::unique_ptr<blink::WebScrollbarLayer> createSolidColorScrollbarLayer(
       blink::WebScrollbar::Orientation orientation,
       int thumb_thickness,
       int track_start,
diff --git a/cc/blink/web_content_layer_impl.h b/cc/blink/web_content_layer_impl.h
index 227225d..46b087ae 100644
--- a/cc/blink/web_content_layer_impl.h
+++ b/cc/blink/web_content_layer_impl.h
@@ -31,12 +31,12 @@
  public:
   CC_BLINK_EXPORT explicit WebContentLayerImpl(blink::WebContentLayerClient*);
 
+  ~WebContentLayerImpl() override;
+
   // WebContentLayer implementation.
   blink::WebLayer* layer() override;
 
  protected:
-  ~WebContentLayerImpl() override;
-
   // ContentLayerClient implementation.
   gfx::Rect PaintableRegion() override;
   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList(
diff --git a/cc/blink/web_scrollbar_layer_impl.cc b/cc/blink/web_scrollbar_layer_impl.cc
index 7011d5f..b9c6df3 100644
--- a/cc/blink/web_scrollbar_layer_impl.cc
+++ b/cc/blink/web_scrollbar_layer_impl.cc
@@ -4,6 +4,8 @@
 
 #include "cc/blink/web_scrollbar_layer_impl.h"
 
+#include <utility>
+
 #include "base/memory/ptr_util.h"
 #include "cc/blink/scrollbar_impl.h"
 #include "cc/blink/web_layer_impl.h"
@@ -28,15 +30,13 @@
 namespace cc_blink {
 
 WebScrollbarLayerImpl::WebScrollbarLayerImpl(
-    blink::WebScrollbar* scrollbar,
+    std::unique_ptr<blink::WebScrollbar> scrollbar,
     blink::WebScrollbarThemePainter painter,
-    blink::WebScrollbarThemeGeometry* geometry)
+    std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry)
     : layer_(new WebLayerImpl(PaintedScrollbarLayer::Create(
-
-          std::unique_ptr<cc::Scrollbar>(
-              new ScrollbarImpl(base::WrapUnique(scrollbar),
-                                painter,
-                                base::WrapUnique(geometry))),
+          base::MakeUnique<ScrollbarImpl>(std::move(scrollbar),
+                                          painter,
+                                          std::move(geometry)),
           0))) {}
 
 WebScrollbarLayerImpl::WebScrollbarLayerImpl(
diff --git a/cc/blink/web_scrollbar_layer_impl.h b/cc/blink/web_scrollbar_layer_impl.h
index 0239b41..3fd192e 100644
--- a/cc/blink/web_scrollbar_layer_impl.h
+++ b/cc/blink/web_scrollbar_layer_impl.h
@@ -24,9 +24,9 @@
 class WebScrollbarLayerImpl : public blink::WebScrollbarLayer {
  public:
   CC_BLINK_EXPORT WebScrollbarLayerImpl(
-      blink::WebScrollbar* scrollbar,
+      std::unique_ptr<blink::WebScrollbar> scrollbar,
       blink::WebScrollbarThemePainter painter,
-      blink::WebScrollbarThemeGeometry* geometry);
+      std::unique_ptr<blink::WebScrollbarThemeGeometry> geometry);
   CC_BLINK_EXPORT WebScrollbarLayerImpl(
       blink::WebScrollbar::Orientation orientation,
       int thumb_thickness,
diff --git a/chrome/VERSION b/chrome/VERSION
index 3f8b97a..ac8e841 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=56
 MINOR=0
-BUILD=2889
+BUILD=2890
 PATCH=0
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 55cabc3..bff3c0d 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1416,12 +1416,6 @@
   <message name="IDS_FLAGS_QUICK_UNLOCK_PIN_DESCRIPTION" desc="Description of the flag used to enable quick unlock pin.">
     Enabling PIN quick unlock allows you to use a PIN to unlock your Chromebook on the lock screen after you have signed into your device.
   </message>
-  <message name="IDS_FLAGS_STORAGE_MANAGER_NAME" desc="Description for the flag to enable experimental storage manager.">
-    Storage manager
-  </message>
-  <message name="IDS_FLAGS_STORAGE_MANAGER_DESCRIPTION" desc="Description for the flag to enable experimental storage manager.">
-    Enables storage manager to manage local storage.
-  </message>
   <message name="IDS_OFFERS_CONSENT_INFOBAR_LABEL_LEARN_MORE" desc="Text of the Learn More link in the echo dialog.">
     Learn More
   </message>
diff --git a/chrome/app/mash/chrome_mash_manifest.json b/chrome/app/mash/chrome_mash_manifest.json
index 79ba4748..7693eec 100644
--- a/chrome/app/mash/chrome_mash_manifest.json
+++ b/chrome/app/mash/chrome_mash_manifest.json
@@ -10,6 +10,9 @@
   "name": "service:chrome_mash",
   "display_name": "Chrome Mash Packaged Services",
   "capabilities": {
+    "provided": {
+      "shell:service_factory": [ "shell::mojom::ServiceFactory" ]
+    },
     "required": {
       "service:mash_session": { "classes": [ "app" ] },
       "service:catalog": { "classes": [ "control" ] }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 1594077f..dd5c76a1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1126,10 +1126,6 @@
     {"enable-fullscreen-app-list", IDS_FLAGS_FULLSCREEN_APP_LIST_NAME,
      IDS_FLAGS_FULLSCREEN_APP_LIST_DESCRIPTION, kOsCrOS,
      SINGLE_VALUE_TYPE(ash::switches::kAshEnableFullscreenAppList)},
-    {"enable-storage-manager", IDS_FLAGS_STORAGE_MANAGER_NAME,
-     IDS_FLAGS_STORAGE_MANAGER_DESCRIPTION, kOsCrOS,
-     ENABLE_DISABLE_VALUE_TYPE(chromeos::switches::kEnableStorageManager,
-                               chromeos::switches::kDisableStorageManager)},
     {"enable-md-storage-manager", IDS_FLAGS_MD_STORAGE_MANAGER_NAME,
      IDS_FLAGS_MD_STORAGE_MANAGER_DESCRIPTION, kOsCrOS,
      SINGLE_VALUE_TYPE(chromeos::switches::kEnableMdStorageManager)},
diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc
index a42484fb..0997b5d3 100644
--- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc
+++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.cc
@@ -170,6 +170,116 @@
   }
 }
 
+bool AppBannerInfoBarDelegateAndroid::Accept() {
+  has_user_interaction_ = true;
+
+  content::WebContents* web_contents =
+      InfoBarService::WebContentsFromInfoBar(infobar());
+  if (!web_contents) {
+    TrackDismissEvent(DISMISS_EVENT_ERROR);
+    return true;
+  }
+
+  if (!native_app_data_.is_null())
+    return AcceptNativeApp(web_contents);
+
+  if (is_webapk_)
+    return AcceptWebApk(web_contents);
+
+  return AcceptWebApp(web_contents);
+}
+
+AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
+    base::WeakPtr<AppBannerManager> weak_manager,
+    const base::string16& app_title,
+    std::unique_ptr<ShortcutInfo> shortcut_info,
+    std::unique_ptr<SkBitmap> icon,
+    int event_request_id,
+    bool is_webapk,
+    webapk::InstallSource webapk_install_source)
+    : weak_manager_(weak_manager),
+      app_title_(app_title),
+      shortcut_info_(std::move(shortcut_info)),
+      icon_(std::move(icon)),
+      event_request_id_(event_request_id),
+      has_user_interaction_(false),
+      is_webapk_(is_webapk),
+      install_state_(INSTALL_NOT_STARTED),
+      webapk_install_source_(webapk_install_source),
+      weak_ptr_factory_(this) {
+  DCHECK(!IsInfoEmpty(shortcut_info_));
+  CreateJavaDelegate();
+}
+
+AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
+    const base::string16& app_title,
+    const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
+    std::unique_ptr<SkBitmap> icon,
+    const std::string& native_app_package,
+    const std::string& referrer,
+    int event_request_id)
+    : app_title_(app_title),
+      native_app_data_(native_app_data),
+      icon_(std::move(icon)),
+      native_app_package_(native_app_package),
+      referrer_(referrer),
+      event_request_id_(event_request_id),
+      has_user_interaction_(false),
+      weak_ptr_factory_(this) {
+  DCHECK(!native_app_data_.is_null());
+  CreateJavaDelegate();
+}
+
+void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() {
+  java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create(
+      base::android::AttachCurrentThread(),
+      reinterpret_cast<intptr_t>(this)));
+}
+
+bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp(
+    content::WebContents* web_contents) {
+  TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED);
+  JNIEnv* env = base::android::AttachCurrentThread();
+
+  TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
+  DCHECK(tab);
+  ScopedJavaLocalRef<jstring> jreferrer(
+      ConvertUTF8ToJavaString(env, referrer_));
+
+  bool was_opened =
+      Java_AppBannerInfoBarDelegateAndroid_installOrOpenNativeApp(
+          env, java_delegate_, tab->GetJavaObject(),
+          native_app_data_, jreferrer);
+
+  if (was_opened)
+    TrackDismissEvent(DISMISS_EVENT_APP_OPEN);
+  else
+    TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED);
+
+  SendBannerAccepted(web_contents, "play");
+  return was_opened;
+}
+
+bool AppBannerInfoBarDelegateAndroid::AcceptWebApp(
+    content::WebContents* web_contents) {
+  if (IsInfoEmpty(shortcut_info_))
+    return true;
+  TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
+
+  AppBannerSettingsHelper::RecordBannerInstallEvent(
+      web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB);
+
+  if (weak_manager_) {
+    const std::string& uid = base::GenerateGUID();
+    ShortcutHelper::AddToLauncherWithSkBitmap(
+        web_contents->GetBrowserContext(), *shortcut_info_, uid,
+        *icon_.get(), weak_manager_->FetchWebappSplashScreenImageCallback(uid));
+  }
+
+  SendBannerAccepted(web_contents, "web");
+  return true;
+}
+
 bool AppBannerInfoBarDelegateAndroid::AcceptWebApk(
     content::WebContents* web_contents) {
   if (IsInfoEmpty(shortcut_info_))
@@ -224,53 +334,6 @@
   return false;
 }
 
-AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
-    base::WeakPtr<AppBannerManager> weak_manager,
-    const base::string16& app_title,
-    std::unique_ptr<ShortcutInfo> shortcut_info,
-    std::unique_ptr<SkBitmap> icon,
-    int event_request_id,
-    bool is_webapk,
-    webapk::InstallSource webapk_install_source)
-    : weak_manager_(weak_manager),
-      app_title_(app_title),
-      shortcut_info_(std::move(shortcut_info)),
-      icon_(std::move(icon)),
-      event_request_id_(event_request_id),
-      has_user_interaction_(false),
-      is_webapk_(is_webapk),
-      install_state_(INSTALL_NOT_STARTED),
-      webapk_install_source_(webapk_install_source),
-      weak_ptr_factory_(this) {
-  DCHECK(!IsInfoEmpty(shortcut_info_));
-  CreateJavaDelegate();
-}
-
-AppBannerInfoBarDelegateAndroid::AppBannerInfoBarDelegateAndroid(
-    const base::string16& app_title,
-    const base::android::ScopedJavaGlobalRef<jobject>& native_app_data,
-    std::unique_ptr<SkBitmap> icon,
-    const std::string& native_app_package,
-    const std::string& referrer,
-    int event_request_id)
-    : app_title_(app_title),
-      native_app_data_(native_app_data),
-      icon_(std::move(icon)),
-      native_app_package_(native_app_package),
-      referrer_(referrer),
-      event_request_id_(event_request_id),
-      has_user_interaction_(false),
-      weak_ptr_factory_(this) {
-  DCHECK(!native_app_data_.is_null());
-  CreateJavaDelegate();
-}
-
-void AppBannerInfoBarDelegateAndroid::CreateJavaDelegate() {
-  java_delegate_.Reset(Java_AppBannerInfoBarDelegateAndroid_create(
-      base::android::AttachCurrentThread(),
-      reinterpret_cast<intptr_t>(this)));
-}
-
 void AppBannerInfoBarDelegateAndroid::SendBannerAccepted(
     content::WebContents* web_contents,
     const std::string& platform) {
@@ -281,6 +344,44 @@
           platform));
 }
 
+void AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished(
+    bool success,
+    const std::string& webapk_package_name) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  if (!success) {
+    DVLOG(1) << "The WebAPK installation failed.";
+    Java_AppBannerInfoBarDelegateAndroid_showWebApkInstallFailureToast(env);
+    webapk::TrackInstallEvent(webapk::INSTALL_FAILED);
+    if (infobar())
+      infobar()->RemoveSelf();
+    return;
+  }
+
+  webapk_package_name_ = webapk_package_name;
+  ScopedJavaLocalRef<jstring> java_webapk_package_name =
+      base::android::ConvertUTF8ToJavaString(env, webapk_package_name);
+  Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState(
+      env, java_delegate_, false);
+  Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName(
+      env, java_delegate_, java_webapk_package_name);
+  UpdateInstallState(env, nullptr);
+  install_state_ = INSTALLED;
+  webapk::TrackInstallEvent(webapk::INSTALL_COMPLETED);
+}
+
+void AppBannerInfoBarDelegateAndroid::TrackWebApkInstallationDismissEvents(
+    InstallState install_state) {
+  if (install_state == INSTALL_NOT_STARTED) {
+    webapk::TrackInstallEvent(webapk::INFOBAR_DISMISSED_BEFORE_INSTALLATION);
+  } else if (install_state == INSTALLING) {
+    webapk::TrackInstallEvent(webapk::INFOBAR_DISMISSED_DURING_INSTALLATION);
+  } else if (install_state == INSTALLED) {
+    // When |install_state| is INSTALLED, the install Event will be recorded in
+    // OnWebApkInstallFinished().
+    webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN_DISMISS);
+  }
+}
+
 infobars::InfoBarDelegate::InfoBarIdentifier
 AppBannerInfoBarDelegateAndroid::GetIdentifier() const {
   return APP_BANNER_INFOBAR_DELEGATE_ANDROID;
@@ -322,107 +423,6 @@
   return BUTTON_OK;
 }
 
-bool AppBannerInfoBarDelegateAndroid::Accept() {
-  has_user_interaction_ = true;
-
-  content::WebContents* web_contents =
-      InfoBarService::WebContentsFromInfoBar(infobar());
-  if (!web_contents) {
-    TrackDismissEvent(DISMISS_EVENT_ERROR);
-    return true;
-  }
-
-  if (!native_app_data_.is_null())
-    return AcceptNativeApp(web_contents);
-
-  if (is_webapk_)
-    return AcceptWebApk(web_contents);
-
-  return AcceptWebApp(web_contents);
-}
-
-bool AppBannerInfoBarDelegateAndroid::AcceptNativeApp(
-    content::WebContents* web_contents) {
-  TrackUserResponse(USER_RESPONSE_NATIVE_APP_ACCEPTED);
-  JNIEnv* env = base::android::AttachCurrentThread();
-
-  TabAndroid* tab = TabAndroid::FromWebContents(web_contents);
-  DCHECK(tab);
-  ScopedJavaLocalRef<jstring> jreferrer(
-      ConvertUTF8ToJavaString(env, referrer_));
-
-  bool was_opened =
-      Java_AppBannerInfoBarDelegateAndroid_installOrOpenNativeApp(
-          env, java_delegate_, tab->GetJavaObject(),
-          native_app_data_, jreferrer);
-
-  if (was_opened)
-    TrackDismissEvent(DISMISS_EVENT_APP_OPEN);
-  else
-    TrackInstallEvent(INSTALL_EVENT_NATIVE_APP_INSTALL_TRIGGERED);
-
-  SendBannerAccepted(web_contents, "play");
-  return was_opened;
-}
-
-bool AppBannerInfoBarDelegateAndroid::AcceptWebApp(
-    content::WebContents* web_contents) {
-  if (IsInfoEmpty(shortcut_info_))
-    return true;
-  TrackUserResponse(USER_RESPONSE_WEB_APP_ACCEPTED);
-
-  AppBannerSettingsHelper::RecordBannerInstallEvent(
-      web_contents, shortcut_info_->url.spec(), AppBannerSettingsHelper::WEB);
-
-  if (weak_manager_) {
-    const std::string& uid = base::GenerateGUID();
-    ShortcutHelper::AddToLauncherWithSkBitmap(
-        web_contents->GetBrowserContext(), *shortcut_info_, uid,
-        *icon_.get(), weak_manager_->FetchWebappSplashScreenImageCallback(uid));
-  }
-
-  SendBannerAccepted(web_contents, "web");
-  return true;
-}
-
-void AppBannerInfoBarDelegateAndroid::OnWebApkInstallFinished(
-    bool success,
-    const std::string& webapk_package_name) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  if (!success) {
-    DVLOG(1) << "The WebAPK installation failed.";
-    Java_AppBannerInfoBarDelegateAndroid_showWebApkInstallFailureToast(env);
-    webapk::TrackInstallEvent(webapk::INSTALL_FAILED);
-    if (infobar())
-      infobar()->RemoveSelf();
-    return;
-  }
-
-  webapk_package_name_ = webapk_package_name;
-  ScopedJavaLocalRef<jstring> java_webapk_package_name =
-      base::android::ConvertUTF8ToJavaString(env, webapk_package_name);
-  Java_AppBannerInfoBarDelegateAndroid_setWebApkInstallingState(
-      env, java_delegate_, false);
-  Java_AppBannerInfoBarDelegateAndroid_setWebApkPackageName(
-      env, java_delegate_, java_webapk_package_name);
-  UpdateInstallState(env, nullptr);
-  install_state_ = INSTALLED;
-  webapk::TrackInstallEvent(webapk::INSTALL_COMPLETED);
-}
-
-void AppBannerInfoBarDelegateAndroid::TrackWebApkInstallationDismissEvents(
-    InstallState install_state) {
-  if (install_state == INSTALL_NOT_STARTED) {
-    webapk::TrackInstallEvent(webapk::INFOBAR_DISMISSED_BEFORE_INSTALLATION);
-  } else if (install_state == INSTALLING) {
-    webapk::TrackInstallEvent(webapk::INFOBAR_DISMISSED_DURING_INSTALLATION);
-  } else if (install_state == INSTALLED) {
-    // When |install_state| is INSTALLED, the install Event will be recorded in
-    // OnWebApkInstallFinished().
-    webapk::TrackUserAction(webapk::USER_ACTION_INSTALLED_OPEN_DISMISS);
-  }
-}
-
 bool AppBannerInfoBarDelegateAndroid::LinkClicked(
     WindowOpenDisposition disposition) {
   if (native_app_data_.is_null())
diff --git a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h
index 92d5bdd..0dc66c5c 100644
--- a/chrome/browser/android/banners/app_banner_infobar_delegate_android.h
+++ b/chrome/browser/android/banners/app_banner_infobar_delegate_android.h
@@ -23,7 +23,6 @@
 class InfoBarManager;
 }
 
-class AppBannerInfoBar;
 struct ShortcutInfo;
 
 namespace banners {
@@ -43,7 +42,6 @@
       bool is_webapk,
       webapk::InstallSource webapk_install_source);
 
-  // Creates and shows the infobar for an Android app.
   // Creates an infobar and delegate for promoting the installation of an
   // Android app, and adds the infobar to the InfoBarManager for |web_contents|.
   static bool Create(
@@ -57,7 +55,7 @@
 
   ~AppBannerInfoBarDelegateAndroid() override;
 
-  // Called when the AppBannerInfoBar's button needs to be updated.
+  // Called when the AppBannerInfoBarAndroid's button needs to be updated.
   void UpdateInstallState(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj);
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index e650d84..dd7abdb 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3143,8 +3143,7 @@
 #endif
 
 #if defined(ENABLE_EXTENSIONS)
-  if (!handle->IsInMainFrame())
-    throttles.push_back(new extensions::ExtensionNavigationThrottle(handle));
+  throttles.push_back(new extensions::ExtensionNavigationThrottle(handle));
 #endif
 
   subresource_filter::ContentSubresourceFilterDriverFactory*
diff --git a/chrome/browser/chromeos/file_manager/open_util.cc b/chrome/browser/chromeos/file_manager/open_util.cc
index 4bee157..a5c634d 100644
--- a/chrome/browser/chromeos/file_manager/open_util.cc
+++ b/chrome/browser/chromeos/file_manager/open_util.cc
@@ -37,6 +37,9 @@
 
 bool shell_operations_allowed = true;
 
+void IgnoreFileTaskExecuteResult(
+    extensions::api::file_manager_private::TaskResult result) {}
+
 // Executes the |task| for the file specified by |url|.
 void ExecuteFileTaskForUrl(Profile* profile,
                            const file_tasks::TaskDescriptor& task,
@@ -50,7 +53,7 @@
       profile,
       GetFileManagerMainPageUrl(),  // Executing task on behalf of Files.app.
       task, std::vector<FileSystemURL>(1, file_system_context->CrackURL(url)),
-      file_tasks::FileTaskFinishedCallback());
+      base::Bind(&IgnoreFileTaskExecuteResult));
 }
 
 // Opens the file manager for the specified |url|. Used to implement
diff --git a/chrome/browser/net/chrome_extensions_network_delegate.cc b/chrome/browser/net/chrome_extensions_network_delegate.cc
index 4443f084..b126cdb 100644
--- a/chrome/browser/net/chrome_extensions_network_delegate.cc
+++ b/chrome/browser/net/chrome_extensions_network_delegate.cc
@@ -22,8 +22,6 @@
 #include "extensions/browser/extension_navigation_ui_data.h"
 #include "extensions/browser/info_map.h"
 #include "extensions/browser/process_manager.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/permissions/api_permission.h"
 #include "net/url_request/url_request.h"
 
 using content::BrowserThread;
@@ -179,31 +177,6 @@
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     GURL* new_url) {
-  const content::ResourceRequestInfo* info =
-      content::ResourceRequestInfo::ForRequest(request);
-  GURL url(request->url());
-
-  // Block top-level navigations to blob: or filesystem: URLs with extension
-  // origin from non-extension processes.  See https://crbug.com/645028.
-  bool is_nested_url = url.SchemeIsFileSystem() || url.SchemeIsBlob();
-  bool is_navigation =
-      info && content::IsResourceTypeFrame(info->GetResourceType());
-  url::Origin origin(url);
-  if (is_nested_url && is_navigation && info->IsMainFrame() &&
-      origin.scheme() == extensions::kExtensionScheme &&
-      !extension_info_map_->process_map().Contains(info->GetChildID())) {
-    // Relax this restriction for apps that use <webview>.  See
-    // https://crbug.com/652077.
-    const extensions::Extension* extension =
-        extension_info_map_->extensions().GetByID(origin.host());
-    bool has_webview_permission =
-        extension &&
-        extension->permissions_data()->HasAPIPermission(
-            extensions::APIPermission::kWebView);
-    if (!has_webview_permission)
-      return net::ERR_ABORTED;
-  }
-
   return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
       profile_, extension_info_map_.get(),
       GetExtensionNavigationUIData(request), request, callback, new_url);
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index 7c7f962..c63cdfc 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -134,7 +134,7 @@
           </button>
         </span>
         <button id="storage-manager-button"
-            i18n-content="storageManagerButtonTitle" hidden>
+            i18n-content="storageManagerButtonTitle">
         </button>
       </div>
       <div id="stylus-row" hidden>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 684c40b..e9da4b9 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -361,14 +361,11 @@
           chrome.send('coreOptionsUserMetricsAction',
                       ['Options_ShowTouchpadSettings']);
         };
-        if (loadTimeData.getBoolean('enableStorageManager')) {
-          $('storage-manager-button').hidden = false;
-          $('storage-manager-button').onclick = function(evt) {
-            PageManager.showPageByName('storage');
-            chrome.send('coreOptionsUserMetricsAction',
-                        ['Options_ShowStorageManager']);
-          };
-        }
+        $('storage-manager-button').onclick = function(evt) {
+          PageManager.showPageByName('storage');
+          chrome.send('coreOptionsUserMetricsAction',
+                      ['Options_ShowStorageManager']);
+        };
       }
 
       // Search section.
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index 7f03120c..dd49ee7c 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -926,17 +926,25 @@
       subresource_filter::ContentSubresourceFilterDriverFactory::
           FromWebContents(web_contents);
 
-  EXPECT_EQ(0U, driver_factory->activation_set().size());
+  EXPECT_EQ(0U,
+            driver_factory->safe_browsing_blacklisted_patterns_set().size());
   chrome::NavigateParams params(browser(), bad_url, ui::PAGE_TRANSITION_LINK);
   ui_test_utils::NavigateToURL(&params);
-
-  EXPECT_EQ(1U, driver_factory->activation_set().size());
+  EXPECT_EQ(1U,
+            driver_factory->safe_browsing_blacklisted_patterns_set().size());
   EXPECT_TRUE(got_hit_report());
 }
 
 IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, SocEngReportingBlacklistEmpty) {
   // Tests that URLS which doesn't belong to the SOCIAL_ENGINEERING_ADS threat
   // type aren't seen by the Subresource Filter.
+  subresource_filter::testing::ScopedSubresourceFilterFeatureToggle
+      scoped_feature_toggle(
+          base::FeatureList::OVERRIDE_ENABLE_FEATURE,
+          subresource_filter::kActivationStateEnabled,
+          subresource_filter::kActivationScopeNoSites,
+          subresource_filter::kActivationListSocialEngineeringAdsInterstitial);
+
   GURL bad_url = embedded_test_server()->GetURL(kMalwarePage);
 
   SBFullHashResult malware_full_hash;
@@ -951,11 +959,12 @@
       subresource_filter::ContentSubresourceFilterDriverFactory::
           FromWebContents(web_contents);
 
-  EXPECT_EQ(0U, driver_factory->activation_set().size());
+  EXPECT_EQ(0U,
+            driver_factory->safe_browsing_blacklisted_patterns_set().size());
   chrome::NavigateParams params(browser(), bad_url, ui::PAGE_TRANSITION_LINK);
   ui_test_utils::NavigateToURL(&params);
-
-  EXPECT_EQ(0U, driver_factory->activation_set().size());
+  EXPECT_EQ(0U,
+            driver_factory->safe_browsing_blacklisted_patterns_set().size());
   EXPECT_TRUE(got_hit_report());
 }
 
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index 6a632f3..df89a2a 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -740,10 +740,6 @@
   cros_settings->GetBoolean(chromeos::kAllowBluetooth, &allow_bluetooth);
   values->SetBoolean("allowBluetooth", allow_bluetooth);
 
-  values->SetBoolean("enableStorageManager",
-      !base::CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kDisableStorageManager));
-
   values->SetBoolean("showQuickUnlockSettings",
                      chromeos::IsQuickUnlockEnabled());
   if (chromeos::IsQuickUnlockEnabled()) {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index b7b9b12e..1423059 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-8889.0.0
\ No newline at end of file
+8892.0.0
\ No newline at end of file
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 6dda959..11a8d53 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -196,9 +196,6 @@
 // Disables rollback option on reset screen.
 const char kDisableRollbackOption[] = "disable-rollback-option";
 
-// Disables experimental storage manager to manage local storage.
-const char kDisableStorageManager[] = "disable-storage-manager";
-
 // Disables SystemTimezoneAutomaticDetection policy.
 const char kDisableSystemTimezoneAutomaticDetectionPolicy[] =
     "disable-system-timezone-automatic-detection";
@@ -267,9 +264,6 @@
 const char kEnableScreenshotTestingWithMode[] =
     "enable-screenshot-testing-with-mode";
 
-// Enables experimental storage manager to manage local storage.
-const char kEnableStorageManager[] = "enable-storage-manager";
-
 // Enables touchpad three-finger-click as middle button.
 const char kEnableTouchpadThreeFingerClick[] =
     "enable-touchpad-three-finger-click";
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index a0a28eb..95e3d2c3 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -69,7 +69,6 @@
 CHROMEOS_EXPORT extern const char kDisableOfficeEditingComponentApp[];
 CHROMEOS_EXPORT extern const char kDisablePhysicalKeyboardAutocorrect[];
 CHROMEOS_EXPORT extern const char kDisableRollbackOption[];
-CHROMEOS_EXPORT extern const char kDisableStorageManager[];
 CHROMEOS_EXPORT extern const char
     kDisableSystemTimezoneAutomaticDetectionPolicy[];
 CHROMEOS_EXPORT extern const char kDisableTimeZoneTrackingOption[];
@@ -91,7 +90,6 @@
 CHROMEOS_EXPORT extern const char kEnablePhysicalKeyboardAutocorrect[];
 CHROMEOS_EXPORT extern const char kEnableRequestTabletSite[];
 CHROMEOS_EXPORT extern const char kEnableScreenshotTestingWithMode[];
-CHROMEOS_EXPORT extern const char kEnableStorageManager[];
 CHROMEOS_EXPORT extern const char kEnableTouchpadThreeFingerClick[];
 CHROMEOS_EXPORT extern const char kEnableVideoPlayerChromecastSupport[];
 CHROMEOS_EXPORT extern const char kEnterpriseDisableArc[];
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index d37fee8a..6637fda 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -449,8 +449,8 @@
   if (cc_import || address_import)
     return true;
 
-  FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
-                    OnInsufficientFormData());
+  for (PersonalDataManagerObserver& observer : observers_)
+    observer.OnInsufficientFormData();
   return false;
 }
 
@@ -1246,8 +1246,8 @@
 }
 
 void PersonalDataManager::NotifyPersonalDataChanged() {
-  FOR_EACH_OBSERVER(PersonalDataManagerObserver, observers_,
-                    OnPersonalDataChanged());
+  for (PersonalDataManagerObserver& observer : observers_)
+    observer.OnPersonalDataChanged();
 }
 
 std::string PersonalDataManager::SaveImportedCreditCard(
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
index d4117a0a..022fe44 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -71,8 +71,8 @@
   DCHECK(db_thread_->BelongsToCurrentThread());
 
   // DB thread notification.
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, db_observer_list_,
-                    AutofillMultipleChanged());
+  for (auto& db_observer : db_observer_list_)
+    db_observer.AutofillMultipleChanged();
 
   // UI thread notification.
   ui_thread_->PostTask(FROM_HERE, on_changed_callback_);
@@ -114,9 +114,8 @@
   // Post the notifications including the list of affected keys.
   // This is sent here so that work resulting from this notification will be
   // done on the DB thread, and not the UI thread.
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                    db_observer_list_,
-                    AutofillEntriesChanged(changes));
+  for (auto& db_observer : db_observer_list_)
+    db_observer.AutofillEntriesChanged(changes);
 
   return WebDatabase::COMMIT_NEEDED;
 }
@@ -148,9 +147,8 @@
       // Post the notifications including the list of affected keys.
       // This is sent here so that work resulting from this notification
       // will be done on the DB thread, and not the UI thread.
-      FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                        db_observer_list_,
-                        AutofillEntriesChanged(changes));
+      for (auto& db_observer : db_observer_list_)
+        db_observer.AutofillEntriesChanged(changes);
     }
     return WebDatabase::COMMIT_NEEDED;
   }
@@ -167,9 +165,8 @@
         AutofillChange(AutofillChange::REMOVE, AutofillKey(name, value)));
 
     // Post the notifications including the list of affected keys.
-    FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                      db_observer_list_,
-                      AutofillEntriesChanged(changes));
+    for (auto& db_observer : db_observer_list_)
+      db_observer.AutofillEntriesChanged(changes);
 
     return WebDatabase::COMMIT_NEEDED;
   }
@@ -187,9 +184,8 @@
   // Send GUID-based notification.
   AutofillProfileChange change(
       AutofillProfileChange::ADD, profile.guid(), &profile);
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                    db_observer_list_,
-                    AutofillProfileChanged(change));
+  for (auto& db_observer : db_observer_list_)
+    db_observer.AutofillProfileChanged(change);
 
   return WebDatabase::COMMIT_NEEDED;
 }
@@ -213,9 +209,8 @@
   // Send GUID-based notification.
   AutofillProfileChange change(
       AutofillProfileChange::UPDATE, profile.guid(), &profile);
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                    db_observer_list_,
-                    AutofillProfileChanged(change));
+  for (auto& db_observer : db_observer_list_)
+    db_observer.AutofillProfileChanged(change);
 
   return WebDatabase::COMMIT_NEEDED;
 }
@@ -237,9 +232,8 @@
 
   // Send GUID-based notification.
   AutofillProfileChange change(AutofillProfileChange::REMOVE, guid, NULL);
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                    db_observer_list_,
-                    AutofillProfileChanged(change));
+  for (auto& db_observer : db_observer_list_)
+    db_observer.AutofillProfileChanged(change);
 
   return WebDatabase::COMMIT_NEEDED;
 }
@@ -299,10 +293,10 @@
     return WebDatabase::COMMIT_NOT_NEEDED;
   }
 
-  FOR_EACH_OBSERVER(
-      AutofillWebDataServiceObserverOnDBThread, db_observer_list_,
-      CreditCardChanged(CreditCardChange(CreditCardChange::ADD,
-                                         credit_card.guid(), &credit_card)));
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.CreditCardChanged(CreditCardChange(
+        CreditCardChange::ADD, credit_card.guid(), &credit_card));
+  }
   return WebDatabase::COMMIT_NEEDED;
 }
 
@@ -321,10 +315,10 @@
     return WebDatabase::COMMIT_NOT_NEEDED;
   }
 
-  FOR_EACH_OBSERVER(
-      AutofillWebDataServiceObserverOnDBThread, db_observer_list_,
-      CreditCardChanged(CreditCardChange(CreditCardChange::UPDATE,
-                                         credit_card.guid(), &credit_card)));
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.CreditCardChanged(CreditCardChange(
+        CreditCardChange::UPDATE, credit_card.guid(), &credit_card));
+  }
   return WebDatabase::COMMIT_NEEDED;
 }
 
@@ -336,9 +330,10 @@
     return WebDatabase::COMMIT_NOT_NEEDED;
   }
 
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, db_observer_list_,
-                    CreditCardChanged(CreditCardChange(CreditCardChange::REMOVE,
-                                                       guid, nullptr)));
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.CreditCardChanged(
+        CreditCardChange(CreditCardChange::REMOVE, guid, nullptr));
+  }
   return WebDatabase::COMMIT_NEEDED;
 }
 
@@ -396,9 +391,10 @@
   if (!AutofillTable::FromWebDatabase(db)->UpdateServerCardUsageStats(card))
     return WebDatabase::COMMIT_NOT_NEEDED;
 
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, db_observer_list_,
-                    CreditCardChanged(CreditCardChange(CreditCardChange::UPDATE,
-                                                       card.guid(), &card)));
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.CreditCardChanged(
+        CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+  }
 
   return WebDatabase::COMMIT_NEEDED;
 }
@@ -412,10 +408,10 @@
     return WebDatabase::COMMIT_NOT_NEEDED;
   }
 
-  FOR_EACH_OBSERVER(
-      AutofillWebDataServiceObserverOnDBThread, db_observer_list_,
-      AutofillProfileChanged(AutofillProfileChange(
-          AutofillProfileChange::UPDATE, profile.guid(), &profile)));
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.AutofillProfileChanged(AutofillProfileChange(
+        AutofillProfileChange::UPDATE, profile.guid(), &profile));
+  }
 
   return WebDatabase::COMMIT_NEEDED;
 }
@@ -429,9 +425,10 @@
     return WebDatabase::COMMIT_NOT_NEEDED;
   }
 
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, db_observer_list_,
-                    CreditCardChanged(CreditCardChange(CreditCardChange::UPDATE,
-                                                       card.guid(), &card)));
+  for (auto& db_observer : db_observer_list_) {
+    db_observer.CreditCardChanged(
+        CreditCardChange(CreditCardChange::UPDATE, card.guid(), &card));
+  }
 
   return WebDatabase::COMMIT_NEEDED;
 }
@@ -460,16 +457,16 @@
           &profile_guids,
           &credit_card_guids)) {
     for (const std::string& guid : profile_guids) {
-      FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                        db_observer_list_,
-                        AutofillProfileChanged(AutofillProfileChange(
-                            AutofillProfileChange::REMOVE, guid, nullptr)));
+      for (auto& db_observer : db_observer_list_) {
+        db_observer.AutofillProfileChanged(AutofillProfileChange(
+            AutofillProfileChange::REMOVE, guid, nullptr));
+      }
     }
     for (const std::string& guid : credit_card_guids) {
-      FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                        db_observer_list_,
-                        CreditCardChanged(CreditCardChange(
-                            CreditCardChange::REMOVE, guid, nullptr)));
+      for (auto& db_observer : db_observer_list_) {
+        db_observer.CreditCardChanged(
+            CreditCardChange(CreditCardChange::REMOVE, guid, nullptr));
+      }
     }
     // Note: It is the caller's responsibility to post notifications for any
     // changes, e.g. by calling the Refresh() method of PersonalDataManager.
@@ -491,9 +488,8 @@
 
   for (const AutofillProfile* it : profiles) {
     AutofillProfileChange change(AutofillProfileChange::UPDATE, it->guid(), it);
-    FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                      db_observer_list_,
-                      AutofillProfileChanged(change));
+    for (auto& db_observer : db_observer_list_)
+      db_observer.AutofillProfileChanged(change);
   }
   // Note: It is the caller's responsibility to post notifications for any
   // changes, e.g. by calling the Refresh() method of PersonalDataManager.
@@ -510,9 +506,8 @@
       // Post the notifications including the list of affected keys.
       // This is sent here so that work resulting from this notification
       // will be done on the DB thread, and not the UI thread.
-      FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread,
-                        db_observer_list_,
-                        AutofillEntriesChanged(changes));
+      for (auto& db_observer : db_observer_list_)
+        db_observer.AutofillEntriesChanged(changes);
     }
     return WebDatabase::COMMIT_NEEDED;
   }
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
index fa84a59..22377e9 100644
--- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -295,17 +295,15 @@
 
 void AutofillWebDataService::NotifyAutofillMultipleChangedOnUIThread() {
   DCHECK(ui_thread_->BelongsToCurrentThread());
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnUIThread,
-                    ui_observer_list_,
-                    AutofillMultipleChanged());
+  for (auto& ui_observer : ui_observer_list_)
+    ui_observer.AutofillMultipleChanged();
 }
 
 void AutofillWebDataService::NotifySyncStartedOnUIThread(
     syncer::ModelType model_type) {
   DCHECK(ui_thread_->BelongsToCurrentThread());
-  FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnUIThread,
-                    ui_observer_list_,
-                    SyncStarted(model_type));
+  for (auto& ui_observer : ui_observer_list_)
+    ui_observer.SyncStarted(model_type);
 }
 
 }  // namespace autofill
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 309a0b48..65dc202 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -97,26 +97,7 @@
 // Determine whether we need any tiles from PopularSites to fill up a grid of
 // |num_tiles| tiles.
 bool NeedPopularSites(const PrefService* prefs, int num_tiles) {
-  if (num_tiles <= prefs->GetInteger(prefs::kNumPersonalTiles))
-    return false;
-
-  // TODO(treib): Remove after M55.
-  const base::ListValue* source_list =
-      prefs->GetList(prefs::kDeprecatedNTPTilesIsPersonal);
-  // If there aren't enough previous tiles to fill the grid, we need tiles from
-  // PopularSites.
-  if (static_cast<int>(source_list->GetSize()) < num_tiles)
-    return true;
-  // Otherwise, if any of the previous tiles are not personal, then also
-  // get tiles from PopularSites.
-  for (int i = 0; i < num_tiles; ++i) {
-    bool is_personal = false;
-    if (source_list->GetBoolean(i, &is_personal) && !is_personal)
-      return true;
-  }
-  // The whole grid is already filled with personal tiles, no point in bothering
-  // with popular ones.
-  return false;
+  return prefs->GetInteger(prefs::kNumPersonalTiles) < num_tiles;
 }
 
 bool AreURLsEquivalent(const GURL& url1, const GURL& url2) {
@@ -276,9 +257,6 @@
 void MostVisitedSites::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
   registry->RegisterIntegerPref(prefs::kNumPersonalTiles, 0);
-  // TODO(treib): Remove after M55.
-  registry->RegisterListPref(prefs::kDeprecatedNTPTilesURL);
-  registry->RegisterListPref(prefs::kDeprecatedNTPTilesIsPersonal);
 }
 
 void MostVisitedSites::BuildCurrentTiles() {
@@ -478,9 +456,6 @@
       num_personal_tiles++;
   }
   prefs_->SetInteger(prefs::kNumPersonalTiles, num_personal_tiles);
-  // TODO(treib): Remove after M55.
-  prefs_->ClearPref(prefs::kDeprecatedNTPTilesIsPersonal);
-  prefs_->ClearPref(prefs::kDeprecatedNTPTilesURL);
 }
 
 // static
diff --git a/components/ntp_tiles/pref_names.cc b/components/ntp_tiles/pref_names.cc
index 1ec52196..1988357 100644
--- a/components/ntp_tiles/pref_names.cc
+++ b/components/ntp_tiles/pref_names.cc
@@ -7,9 +7,6 @@
 namespace ntp_tiles {
 namespace prefs {
 
-const char kDeprecatedNTPTilesURL[] = "ntp.suggestions_url";
-const char kDeprecatedNTPTilesIsPersonal[] = "ntp.suggestions_is_personal";
-
 // The number of personal tiles we had previously. Used to figure out
 // whether we need popular sites.
 const char kNumPersonalTiles[] = "ntp.num_personal_suggestions";
diff --git a/components/ntp_tiles/pref_names.h b/components/ntp_tiles/pref_names.h
index 243a5fa..cdaa896 100644
--- a/components/ntp_tiles/pref_names.h
+++ b/components/ntp_tiles/pref_names.h
@@ -8,10 +8,6 @@
 namespace ntp_tiles {
 namespace prefs {
 
-// TODO(treib): Remove after M55.
-extern const char kDeprecatedNTPTilesURL[];
-extern const char kDeprecatedNTPTilesIsPersonal[];
-
 extern const char kNumPersonalTiles[];
 
 extern const char kPopularSitesOverrideURL[];
diff --git a/components/password_manager/core/browser/log_router.cc b/components/password_manager/core/browser/log_router.cc
index f23c95c..b07cb37 100644
--- a/components/password_manager/core/browser/log_router.cc
+++ b/components/password_manager/core/browser/log_router.cc
@@ -19,7 +19,8 @@
   // inactive), because in that case the logs cannot be displayed.
   DCHECK(receivers_.might_have_observers());
   accumulated_logs_.append(text);
-  FOR_EACH_OBSERVER(LogReceiver, receivers_, LogSavePasswordProgress(text));
+  for (LogReceiver& receiver : receivers_)
+    receiver.LogSavePasswordProgress(text);
 }
 
 bool LogRouter::RegisterManager(LogManager* manager) {
@@ -38,8 +39,8 @@
   DCHECK(accumulated_logs_.empty() || receivers_.might_have_observers());
 
   if (!receivers_.might_have_observers()) {
-    FOR_EACH_OBSERVER(LogManager, managers_,
-                      OnLogRouterAvailabilityChanged(true));
+    for (LogManager& manager : managers_)
+      manager.OnLogRouterAvailabilityChanged(true);
   }
   receivers_.AddObserver(receiver);
   return accumulated_logs_;
@@ -52,8 +53,8 @@
     // |accumulated_logs_| can become very long; use the swap instead of clear()
     // to ensure that the memory is freed.
     std::string().swap(accumulated_logs_);
-    FOR_EACH_OBSERVER(LogManager, managers_,
-                      OnLogRouterAvailabilityChanged(false));
+    for (LogManager& manager : managers_)
+      manager.OnLogRouterAvailabilityChanged(false);
   }
 }
 
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 1f9577f..40d749f 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -170,7 +170,8 @@
 }
 
 PasswordManager::~PasswordManager() {
-  FOR_EACH_OBSERVER(LoginModelObserver, observers_, OnLoginModelDestroying());
+  for (LoginModelObserver& observer : observers_)
+    observer.OnLoginModelDestroying();
 }
 
 void PasswordManager::GenerationAvailableForForm(const PasswordForm& form) {
@@ -811,8 +812,8 @@
                        observers_.might_have_observers());
   }
 
-  FOR_EACH_OBSERVER(LoginModelObserver, observers_,
-                    OnAutofillDataAvailable(preferred_match));
+  for (LoginModelObserver& observer : observers_)
+    observer.OnAutofillDataAvailable(preferred_match);
   DCHECK(!best_matches.empty());
   client_->PasswordWasAutofilled(best_matches,
                                  best_matches.begin()->second->origin, nullptr);
diff --git a/components/safe_browsing_db/v4_store.cc b/components/safe_browsing_db/v4_store.cc
index 1330383..83f3b99 100644
--- a/components/safe_browsing_db/v4_store.cc
+++ b/components/safe_browsing_db/v4_store.cc
@@ -22,8 +22,24 @@
 
 namespace {
 
-const uint32_t kFileMagic = 0x600D71FE;
+// UMA related strings.
+// Part 1: Represent the overall operation being performed.
+const char kProcessFullUpdate[] = "SafeBrowsing.V4ProcessFullUpdate";
+const char kProcessPartialUpdate[] = "SafeBrowsing.V4ProcessPartialUpdate";
+const char kReadFromDisk[] = "SafeBrowsing.V4ReadFromDisk";
+// Part 2: Represent the sub-operation being performed as part of the larger
+// operation from part 1.
+const char kApplyUpdate[] = ".ApplyUpdate";
+const char kDecodeAdditions[] = ".DecodeAdditions";
+const char kDecodeRemovals[] = ".DecodeRemovals";
+const char kMergeUpdate[] = ".MergeUpdate";
+// Part 3: Represent the unit of value being measured and logged.
+const char kResult[] = ".Result";
+const char kTime[] = ".Time";
+// UMA metric names for this file are generated by appending one value each,
+// in order, from parts 1, 2, and 3.
 
+const uint32_t kFileMagic = 0x600D71FE;
 const uint32_t kFileVersion = 9;
 
 std::string GetUmaSuffixForStore(const base::FilePath& file_path) {
@@ -31,16 +47,16 @@
       ".%" PRIsFP, file_path.BaseName().RemoveExtension().value().c_str());
 }
 
-void RecordTimeWithAndWithoutStore(const std::string& metric,
-                                   base::TimeDelta time,
-                                   const base::FilePath& file_path) {
+void RecordTimeWithAndWithoutSuffix(const std::string& metric,
+                                    base::TimeDelta time,
+                                    const base::FilePath& file_path) {
   // The histograms below are a modified expansion of the
   // UMA_HISTOGRAM_LONG_TIMES macro adapted to allow for a dynamically suffixed
   // histogram name.
   // Note: The factory creates and owns the histogram.
   const int kBucketCount = 100;
   base::HistogramBase* histogram = base::Histogram::FactoryTimeGet(
-      metric, base::TimeDelta::FromMilliseconds(1),
+      metric + kTime, base::TimeDelta::FromMilliseconds(1),
       base::TimeDelta::FromMinutes(1), kBucketCount,
       base::HistogramBase::kUmaTargetedHistogramFlag);
   if (histogram) {
@@ -49,7 +65,7 @@
 
   std::string suffix = GetUmaSuffixForStore(file_path);
   base::HistogramBase* histogram_suffix = base::Histogram::FactoryTimeGet(
-      metric + suffix, base::TimeDelta::FromMilliseconds(1),
+      metric + suffix + kTime, base::TimeDelta::FromMilliseconds(1),
       base::TimeDelta::FromMinutes(1), kBucketCount,
       base::HistogramBase::kUmaTargetedHistogramFlag);
   if (histogram_suffix) {
@@ -57,74 +73,87 @@
   }
 }
 
-void RecordAddUnlumpedHashesTime(base::TimeDelta time) {
-  UMA_HISTOGRAM_LONG_TIMES("SafeBrowsing.V4AddUnlumpedHashesTime", time);
-}
-
-void RecordApplyUpdateResult(ApplyUpdateResult result) {
-  UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4ApplyUpdateResult", result,
-                            APPLY_UPDATE_RESULT_MAX);
-}
-
-void RecordApplyUpdateResultWhenReadingFromDisk(ApplyUpdateResult result) {
-  UMA_HISTOGRAM_ENUMERATION(
-      "SafeBrowsing.V4ApplyUpdateResultWhenReadingFromDisk", result,
-      APPLY_UPDATE_RESULT_MAX);
-}
-
-void RecordDecodeAdditionsResult(V4DecodeResult result) {
-  UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeAdditionsResult", result,
-                            DECODE_RESULT_MAX);
-}
-
-void RecordDecodeAdditionsTime(base::TimeDelta time,
-                               const base::FilePath& file_path) {
-  RecordTimeWithAndWithoutStore("SafeBrowsing.V4DecodeAdditionsTime", time,
-                                file_path);
-}
-
-void RecordDecodeRemovalsResult(V4DecodeResult result) {
-  UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeRemovalsResult", result,
-                            DECODE_RESULT_MAX);
-}
-
-void RecordDecodeRemovalsTime(base::TimeDelta time,
-                              const base::FilePath& file_path) {
-  RecordTimeWithAndWithoutStore("SafeBrowsing.V4DecodeRemovalsTime", time,
-                                file_path);
-}
-
-void RecordMergeUpdateTime(base::TimeDelta time,
-                           const base::FilePath& file_path) {
-  RecordTimeWithAndWithoutStore("SafeBrowsing.V4MergeUpdateTime", time,
-                                file_path);
-}
-
-void RecordProcessFullUpdateTime(base::TimeDelta time,
-                                 const base::FilePath& file_path) {
-  RecordTimeWithAndWithoutStore("SafeBrowsing.V4ProcessFullUpdateTime", time,
-                                file_path);
-}
-
-void RecordProcessPartialUpdateTime(base::TimeDelta time,
+void RecordEnumWithAndWithoutSuffix(const std::string& metric,
+                                    int32_t value,
+                                    int32_t maximum,
                                     const base::FilePath& file_path) {
-  RecordTimeWithAndWithoutStore("SafeBrowsing.V4ProcessPartialUpdateTime", time,
-                                file_path);
+  // The histograms below are an expansion of the UMA_HISTOGRAM_ENUMERATION
+  // macro adapted to allow for a dynamically suffixed histogram name.
+  // Note: The factory creates and owns the histogram.
+  base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
+      metric + kResult, 1, maximum, maximum + 1,
+      base::HistogramBase::kUmaTargetedHistogramFlag);
+  if (histogram) {
+    histogram->Add(value);
+  }
+
+  std::string suffix = GetUmaSuffixForStore(file_path);
+  base::HistogramBase* histogram_suffix = base::LinearHistogram::FactoryGet(
+      metric + suffix + kResult, 1, maximum, maximum + 1,
+      base::HistogramBase::kUmaTargetedHistogramFlag);
+  if (histogram_suffix) {
+    histogram_suffix->Add(value);
+  }
 }
 
-void RecordReadFromDiskTime(base::TimeDelta time,
-                            const base::FilePath& file_path) {
-  RecordTimeWithAndWithoutStore("SafeBrowsing.V4ReadFromDiskTime", time,
-                                file_path);
+void RecordAddUnlumpedHashesTime(base::TimeDelta time) {
+  UMA_HISTOGRAM_LONG_TIMES("SafeBrowsing.V4AddUnlumpedHashes.Time", time);
+}
+
+void RecordApplyUpdateResult(const std::string& base_metric,
+                             ApplyUpdateResult result,
+                             const base::FilePath& file_path) {
+  RecordEnumWithAndWithoutSuffix(base_metric + kApplyUpdate, result,
+                                 APPLY_UPDATE_RESULT_MAX, file_path);
+}
+
+void RecordApplyUpdateTime(const std::string& base_metric,
+                           base::TimeDelta time,
+                           const base::FilePath& file_path) {
+  RecordTimeWithAndWithoutSuffix(base_metric + kApplyUpdate, time, file_path);
+}
+
+void RecordDecodeAdditionsResult(const std::string& base_metric,
+                                 V4DecodeResult result,
+                                 const base::FilePath& file_path) {
+  RecordEnumWithAndWithoutSuffix(base_metric + kDecodeAdditions, result,
+                                 DECODE_RESULT_MAX, file_path);
+}
+
+void RecordDecodeAdditionsTime(const std::string& base_metric,
+                               base::TimeDelta time,
+                               const base::FilePath& file_path) {
+  RecordTimeWithAndWithoutSuffix(base_metric + kDecodeAdditions, time,
+                                 file_path);
+}
+
+void RecordDecodeRemovalsResult(const std::string& base_metric,
+                                V4DecodeResult result,
+                                const base::FilePath& file_path) {
+  RecordEnumWithAndWithoutSuffix(base_metric + kDecodeRemovals, result,
+                                 DECODE_RESULT_MAX, file_path);
+}
+
+void RecordDecodeRemovalsTime(const std::string& base_metric,
+                              base::TimeDelta time,
+                              const base::FilePath& file_path) {
+  RecordTimeWithAndWithoutSuffix(base_metric + kDecodeRemovals, time,
+                                 file_path);
+}
+
+void RecordMergeUpdateTime(const std::string& base_metric,
+                           base::TimeDelta time,
+                           const base::FilePath& file_path) {
+  RecordTimeWithAndWithoutSuffix(base_metric + kMergeUpdate, time, file_path);
 }
 
 void RecordStoreReadResult(StoreReadResult result) {
-  UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreReadResult", result,
+  UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreRead.Result", result,
                             STORE_READ_RESULT_MAX);
 }
 
 void RecordStoreWriteResult(StoreWriteResult result) {
-  UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreWriteResult", result,
+  UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreWrite.Result", result,
                             STORE_WRITE_RESULT_MAX);
 }
 
@@ -182,33 +211,29 @@
 }
 
 ApplyUpdateResult V4Store::ProcessPartialUpdateAndWriteToDisk(
+    const std::string& metric,
     const HashPrefixMap& hash_prefix_map_old,
     std::unique_ptr<ListUpdateResponse> response) {
   DCHECK(response->has_response_type());
   DCHECK_EQ(ListUpdateResponse::PARTIAL_UPDATE, response->response_type());
 
-  TimeTicks before = TimeTicks::Now();
-  ApplyUpdateResult result = ProcessUpdate(hash_prefix_map_old, response);
-  if (result == APPLY_UPDATE_SUCCESS) {
-    RecordProcessPartialUpdateTime(TimeTicks::Now() - before, store_path_);
-    // TODO(vakh): Create a ListUpdateResponse containing RICE encoded
-    // hash prefixes and response_type as FULL_UPDATE, and write that to disk.
-  }
+  ApplyUpdateResult result =
+      ProcessUpdate(metric, hash_prefix_map_old, response);
   return result;
 }
 
 ApplyUpdateResult V4Store::ProcessFullUpdateAndWriteToDisk(
+    const std::string& metric,
     std::unique_ptr<ListUpdateResponse> response) {
-  TimeTicks before = TimeTicks::Now();
-  ApplyUpdateResult result = ProcessFullUpdate(response);
+  ApplyUpdateResult result = ProcessFullUpdate(metric, response);
   if (result == APPLY_UPDATE_SUCCESS) {
-    RecordProcessFullUpdateTime(TimeTicks::Now() - before, store_path_);
     RecordStoreWriteResult(WriteToDisk(std::move(response)));
   }
   return result;
 }
 
 ApplyUpdateResult V4Store::ProcessFullUpdate(
+    const std::string& metric,
     const std::unique_ptr<ListUpdateResponse>& response) {
   DCHECK(response->has_response_type());
   DCHECK_EQ(ListUpdateResponse::FULL_UPDATE, response->response_type());
@@ -217,10 +242,11 @@
   // checksum. It might save some CPU cycles to store the full update as-is and
   // walk the list of hash prefixes in lexographical order only for checksum
   // calculation.
-  return ProcessUpdate(HashPrefixMap(), response);
+  return ProcessUpdate(metric, HashPrefixMap(), response);
 }
 
 ApplyUpdateResult V4Store::ProcessUpdate(
+    const std::string& metric,
     const HashPrefixMap& hash_prefix_map_old,
     const std::unique_ptr<ListUpdateResponse>& response) {
   const RepeatedField<int32>* raw_removals = nullptr;
@@ -242,11 +268,11 @@
           rice_indices.num_entries(), rice_indices.encoded_data(),
           &rice_removals);
 
-      RecordDecodeRemovalsResult(decode_result);
+      RecordDecodeRemovalsResult(metric, decode_result, store_path_);
       if (decode_result != DECODE_SUCCESS) {
         return RICE_DECODING_FAILURE;
       }
-      RecordDecodeRemovalsTime(TimeTicks::Now() - before, store_path_);
+      RecordDecodeRemovalsTime(metric, TimeTicks::Now() - before, store_path_);
       raw_removals = &rice_removals;
     } else {
       NOTREACHED() << "Unexpected compression_type type: " << compression_type;
@@ -255,8 +281,8 @@
   }
 
   HashPrefixMap hash_prefix_map;
-  ApplyUpdateResult apply_update_result =
-      UpdateHashPrefixMapFromAdditions(response->additions(), &hash_prefix_map);
+  ApplyUpdateResult apply_update_result = UpdateHashPrefixMapFromAdditions(
+      metric, response->additions(), &hash_prefix_map);
   if (apply_update_result != APPLY_UPDATE_SUCCESS) {
     return apply_update_result;
   }
@@ -272,7 +298,7 @@
   if (apply_update_result != APPLY_UPDATE_SUCCESS) {
     return apply_update_result;
   }
-  RecordMergeUpdateTime(TimeTicks::Now() - before, store_path_);
+  RecordMergeUpdateTime(metric, TimeTicks::Now() - before, store_path_);
 
   state_ = response->new_client_state();
   return APPLY_UPDATE_SUCCESS;
@@ -282,15 +308,18 @@
     std::unique_ptr<ListUpdateResponse> response,
     const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner,
     UpdatedStoreReadyCallback callback) {
-  std::unique_ptr<V4Store> new_store(
-      new V4Store(this->task_runner_, this->store_path_));
+  std::unique_ptr<V4Store> new_store(new V4Store(task_runner_, store_path_));
   ApplyUpdateResult apply_update_result;
+  std::string metric;
+  TimeTicks before = TimeTicks::Now();
   if (response->response_type() == ListUpdateResponse::PARTIAL_UPDATE) {
+    metric = kProcessPartialUpdate;
     apply_update_result = new_store->ProcessPartialUpdateAndWriteToDisk(
-        hash_prefix_map_, std::move(response));
+        metric, hash_prefix_map_, std::move(response));
   } else if (response->response_type() == ListUpdateResponse::FULL_UPDATE) {
+    metric = kProcessFullUpdate;
     apply_update_result =
-        new_store->ProcessFullUpdateAndWriteToDisk(std::move(response));
+        new_store->ProcessFullUpdateAndWriteToDisk(metric, std::move(response));
   } else {
     apply_update_result = UNEXPECTED_RESPONSE_TYPE_FAILURE;
     NOTREACHED() << "Failure: Unexpected response type: "
@@ -298,6 +327,7 @@
   }
 
   if (apply_update_result == APPLY_UPDATE_SUCCESS) {
+    RecordApplyUpdateTime(metric, TimeTicks::Now() - before, store_path_);
     // new_store is done updating, pass it to the callback.
     callback_task_runner->PostTask(
         FROM_HERE, base::Bind(callback, base::Passed(&new_store)));
@@ -308,10 +338,11 @@
     callback_task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr));
   }
 
-  RecordApplyUpdateResult(apply_update_result);
+  RecordApplyUpdateResult(metric, apply_update_result, store_path_);
 }
 
 ApplyUpdateResult V4Store::UpdateHashPrefixMapFromAdditions(
+    const std::string& metric,
     const RepeatedPtrField<ThreatEntrySet>& additions,
     HashPrefixMap* additions_map) {
   for (const auto& addition : additions) {
@@ -333,11 +364,12 @@
       V4DecodeResult decode_result = V4RiceDecoder::DecodePrefixes(
           rice_hashes.first_value(), rice_hashes.rice_parameter(),
           rice_hashes.num_entries(), rice_hashes.encoded_data(), &raw_hashes);
-      RecordDecodeAdditionsResult(decode_result);
+      RecordDecodeAdditionsResult(metric, decode_result, store_path_);
       if (decode_result != DECODE_SUCCESS) {
         return RICE_DECODING_FAILURE;
       } else {
-        RecordDecodeAdditionsTime(TimeTicks::Now() - before, store_path_);
+        RecordDecodeAdditionsTime(metric, TimeTicks::Now() - before,
+                                  store_path_);
         char* raw_hashes_start = reinterpret_cast<char*>(raw_hashes.data());
         size_t raw_hashes_size = sizeof(uint32_t) * raw_hashes.size();
 
@@ -627,13 +659,14 @@
 
   std::unique_ptr<ListUpdateResponse> response(new ListUpdateResponse);
   response->Swap(file_format.mutable_list_update_response());
-  ApplyUpdateResult apply_update_result = ProcessFullUpdate(response);
-  RecordApplyUpdateResultWhenReadingFromDisk(apply_update_result);
+  ApplyUpdateResult apply_update_result =
+      ProcessFullUpdate(kReadFromDisk, response);
+  RecordApplyUpdateResult(kReadFromDisk, apply_update_result, store_path_);
   if (apply_update_result != APPLY_UPDATE_SUCCESS) {
     hash_prefix_map_.clear();
     return HASH_PREFIX_MAP_GENERATION_FAILURE;
   }
-  RecordReadFromDiskTime(TimeTicks::Now() - before, store_path_);
+  RecordApplyUpdateTime(kReadFromDisk, TimeTicks::Now() - before, store_path_);
 
   return READ_SUCCESS;
 }
@@ -750,7 +783,8 @@
   checksum_ctx->Finish(checksum, sizeof(checksum));
   for (size_t i = 0; i < crypto::kSHA256Length; i++) {
     if (checksum[i] != expected_checksum_[i]) {
-      RecordApplyUpdateResultWhenReadingFromDisk(CHECKSUM_MISMATCH_FAILURE);
+      RecordApplyUpdateResult(kReadFromDisk, CHECKSUM_MISMATCH_FAILURE,
+                              store_path_);
 #if DCHECK_IS_ON()
       std::string checksum_b64, expected_checksum_b64;
       base::Base64Encode(base::StringPiece(checksum, arraysize(checksum)),
diff --git a/components/safe_browsing_db/v4_store.h b/components/safe_browsing_db/v4_store.h
index a2a89be..3c6ea9d0 100644
--- a/components/safe_browsing_db/v4_store.h
+++ b/components/safe_browsing_db/v4_store.h
@@ -313,31 +313,39 @@
 
   // Processes the FULL_UPDATE |response| from the server, and writes the
   // merged V4Store to disk. If processing the |response| succeeds, it returns
-  // APPLY_UPDATE_SUCCESS.
+  // APPLY_UPDATE_SUCCESS. The UMA metrics for all interesting sub-operations
+  // use the prefix |metric|.
   // This method is only called when we receive a FULL_UPDATE from the server.
   ApplyUpdateResult ProcessFullUpdateAndWriteToDisk(
+      const std::string& metric,
       std::unique_ptr<ListUpdateResponse> response);
 
   // Processes a FULL_UPDATE |response| and updates the V4Store. If processing
   // the |response| succeeds, it returns APPLY_UPDATE_SUCCESS.
   // This method is called when we receive a FULL_UPDATE from the server, and
-  // when we read a store file from disk on startup.
+  // when we read a store file from disk on startup. The UMA metrics for all
+  // interesting sub-operations use the prefix |metric|.
   ApplyUpdateResult ProcessFullUpdate(
+      const std::string& metric,
       const std::unique_ptr<ListUpdateResponse>& response);
 
   // Merges the hash prefixes in |hash_prefix_map_old| and |response|, updates
   // the |hash_prefix_map_| and |state_| in the V4Store, and writes the merged
   // store to disk. If processing succeeds, it returns APPLY_UPDATE_SUCCESS.
   // This method is only called when we receive a PARTIAL_UPDATE from the
-  // server.
+  // server. The UMA metrics for all interesting sub-operations use the prefix
+  // |metric|.
   ApplyUpdateResult ProcessPartialUpdateAndWriteToDisk(
+      const std::string& metric,
       const HashPrefixMap& hash_prefix_map_old,
       std::unique_ptr<ListUpdateResponse> response);
 
   // Merges the hash prefixes in |hash_prefix_map_old| and |response|, and
   // updates the |hash_prefix_map_| and |state_| in the V4Store. If processing
-  // succeeds, it returns APPLY_UPDATE_SUCCESS.
+  // succeeds, it returns APPLY_UPDATE_SUCCESS. The UMA metrics for all
+  // interesting sub-operations use the prefix |metric|.
   ApplyUpdateResult ProcessUpdate(
+      const std::string& metric,
       const HashPrefixMap& hash_prefix_map_old,
       const std::unique_ptr<ListUpdateResponse>& response);
 
@@ -346,8 +354,10 @@
   StoreReadResult ReadFromDisk();
 
   // Updates the |additions_map| with the additions received in the partial
-  // update from the server.
+  // update from the server. The UMA metrics for all interesting sub-operations
+  // use the prefix |metric|.
   ApplyUpdateResult UpdateHashPrefixMapFromAdditions(
+      const std::string& metric,
       const ::google::protobuf::RepeatedPtrField<ThreatEntrySet>& additions,
       HashPrefixMap* additions_map);
 
diff --git a/components/safe_browsing_db/v4_store_unittest.cc b/components/safe_browsing_db/v4_store_unittest.cc
index 28191da..c3824c8 100644
--- a/components/safe_browsing_db/v4_store_unittest.cc
+++ b/components/safe_browsing_db/v4_store_unittest.cc
@@ -711,7 +711,8 @@
   HashPrefixMap additions_map;
   EXPECT_EQ(RICE_DECODING_FAILURE,
             V4Store(task_runner_, store_path_)
-                .UpdateHashPrefixMapFromAdditions(additions, &additions_map));
+                .UpdateHashPrefixMapFromAdditions("V4Metric", additions,
+                                                  &additions_map));
 }
 #endif
 
@@ -732,7 +733,8 @@
   HashPrefixMap additions_map;
   EXPECT_EQ(APPLY_UPDATE_SUCCESS,
             V4Store(task_runner_, store_path_)
-                .UpdateHashPrefixMapFromAdditions(additions, &additions_map));
+                .UpdateHashPrefixMapFromAdditions("V4Metric", additions,
+                                                  &additions_map));
   EXPECT_EQ(1u, additions_map.size());
   EXPECT_EQ(std::string("\x5\0\0\0\fL\x93\xADV\x7F\xF6o\xCEo1\x81", 16),
             additions_map[4]);
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
index 3f2947d3..3a3747d4 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.cc
@@ -74,15 +74,12 @@
   return whitelisted_set().find(url.host()) != whitelisted_set().end();
 }
 
-bool ContentSubresourceFilterDriverFactory::IsBlacklisted(
-    const GURL& url) const {
-  return activation_set().find(url.host()) != activation_set().end();
+bool ContentSubresourceFilterDriverFactory::IsHit(const GURL& url) const {
+  return safe_browsing_blacklisted_patterns_set().find(url.host() +
+                                                       url.path()) !=
+         safe_browsing_blacklisted_patterns_set().end();
 }
 
-bool ContentSubresourceFilterDriverFactory::ShouldActivateForURL(
-    const GURL& url) const {
-  return IsBlacklisted(url) && !IsWhitelisted(url);
-}
 
 void ContentSubresourceFilterDriverFactory::
     OnMainResourceMatchedSafeBrowsingBlacklist(
@@ -101,9 +98,7 @@
   }
   if (!proceed)
     return;
-  AddHostOfURLToActivationSet(url);
-  for (const auto& url : redirect_urls)
-    AddHostOfURLToActivationSet(url);
+  AddToActivationHitsSet(url);
 }
 
 void ContentSubresourceFilterDriverFactory::AddHostOfURLToWhitelistSet(
@@ -112,10 +107,10 @@
     whitelisted_hosts_.insert(url.host());
 }
 
-void ContentSubresourceFilterDriverFactory::AddHostOfURLToActivationSet(
+void ContentSubresourceFilterDriverFactory::AddToActivationHitsSet(
     const GURL& url) {
   if (!url.host().empty() && url.SchemeIsHTTPOrHTTPS())
-    activate_on_hosts_.insert(url.host());
+    safe_browsing_blacklisted_patterns_.insert(url.host() + url.path());
 }
 
 void ContentSubresourceFilterDriverFactory::ReadyToCommitMainFrameNavigation(
@@ -132,7 +127,7 @@
   if (GetCurrentActivationScope() == ActivationScope::ALL_SITES)
     return !IsWhitelisted(url);
   else if (GetCurrentActivationScope() == ActivationScope::ACTIVATION_LIST)
-    return ShouldActivateForURL(url);
+    return IsHit(url) && !IsWhitelisted(url);
   return false;
 }
 
@@ -182,6 +177,7 @@
     const GURL& validated_url,
     bool is_error_page,
     bool is_iframe_srcdoc) {
+  safe_browsing_blacklisted_patterns_.clear();
   if (!render_frame_host->GetParent()) {
     client_->ToggleNotificationVisibility(false);
     set_activation_state(ActivationState::DISABLED);
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h
index 2c9b4d4..049e85f 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h
+++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory.h
@@ -56,18 +56,13 @@
   bool IsWhitelisted(const GURL& url) const;
   bool IsBlacklisted(const GURL& url) const;
 
-  // Returns true if the subresource filtering should be active for the |url|.
-  bool ShouldActivateForURL(const GURL& url) const;
-
-  // Adds the host of the |url| to the set of hosts for which Subresource
-  // Filtering should be active for the lifetime of this WebContents.
-  void AddHostOfURLToActivationSet(const GURL& url);
-
   // Whitelists the host of |url|, so that page loads with the main-frame
   // document being loaded from this host will be exempted from subresource
   // filtering for the lifetime of this WebContents.
   void AddHostOfURLToWhitelistSet(const GURL& url);
 
+  void AddToActivationHitsSet(const GURL& url);
+
   // Called when Safe Browsing detects that the |url| corresponding to the load
   // of the main frame belongs to the blacklist with |threat_type|. If the
   // blacklist is the Safe Browsing Social Engineering ads landing, then |url|
@@ -96,7 +91,9 @@
       content::RenderFrameHost* render_frame_host,
       const GURL& url);
 
-  const HostSet& activation_set() const { return activate_on_hosts_; }
+  const HostSet& safe_browsing_blacklisted_patterns_set() const {
+    return safe_browsing_blacklisted_patterns_;
+  }
   const HostSet& whitelisted_set() const { return whitelisted_hosts_; }
   ActivationState activation_state() { return activation_state_; }
 
@@ -136,14 +133,22 @@
 
   void set_activation_state(const ActivationState& new_activation_state);
 
+  bool IsHit(const GURL& url) const;
+
   static const char kWebContentsUserDataKey[];
 
   FrameHostToOwnedDriverMap frame_drivers_;
   std::unique_ptr<SubresourceFilterClient> client_;
 
-  HostSet activate_on_hosts_;
   HostSet whitelisted_hosts_;
 
+  // Host+path list of the URLs, where the Safe Browsing detected hit to the
+  // threat list of interest. When the navigation is commited
+  // |safe_browsing_blacklisted_patterns_| is used to determine whenever
+  // the activation signal should be sent. All entities are deleted from the
+  // list on navigation commit event.
+  HostSet safe_browsing_blacklisted_patterns_;
+
   ActivationState activation_state_;
 
   DISALLOW_COPY_AND_ASSIGN(ContentSubresourceFilterDriverFactory);
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
index 2b48bf6..8661f44 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_driver_factory_unittest.cc
@@ -148,11 +148,22 @@
   MockSubresourceFilterDriver* subframe_driver() { return subframe_driver_; }
   content::RenderFrameHost* subframe_rfh() { return subframe_rfh_; }
 
-  void BlacklistURLWithRedirects(const GURL& url,
-                                 const std::vector<GURL>& redirects) {
+  void BlacklistURLWithRedirectsNavigateAndCommit(
+      const GURL& bad_url,
+      const std::vector<GURL>& redirects,
+      const GURL& url,
+      bool should_activate) {
+    EXPECT_CALL(*client(), ToggleNotificationVisibility(false)).Times(1);
+    content::WebContentsTester::For(web_contents())->StartNavigation(url);
+    ::testing::Mock::VerifyAndClearExpectations(client());
     factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
-        url, redirects, safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
+        bad_url, redirects, safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
         safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS);
+
+    ActivateAndExpectForFrameHostForUrl(driver(), main_rfh(), url,
+                                        should_activate);
+    content::RenderFrameHostTester::For(main_rfh())
+        ->SimulateNavigationCommit(url);
   }
 
   void ActivateAndExpectForFrameHostForUrl(MockSubresourceFilterDriver* driver,
@@ -165,9 +176,7 @@
     ::testing::Mock::VerifyAndClearExpectations(driver);
   }
 
-  void NavigateToUrlAndExpectActivationAndHidingPromptSubFrame(
-      const GURL& url,
-      bool should_activate) {
+  void NavigateAndCommitSubframe(const GURL& url, bool should_activate) {
     EXPECT_CALL(*subframe_driver(), ActivateForProvisionalLoad(::testing::_))
         .Times(should_activate);
     EXPECT_CALL(*client(), ToggleNotificationVisibility(::testing::_)).Times(0);
@@ -181,27 +190,20 @@
     ::testing::Mock::VerifyAndClearExpectations(client());
   }
 
-  void NavigateToUrlAndExpectActivationAndHidingPrompt(
+  void BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      const GURL& bad_url,
+      const std::vector<GURL>& redirects,
       const GURL& url,
-      bool should_activate,
-      ActivationState expected_activation_state) {
-    EXPECT_CALL(*driver(), ActivateForProvisionalLoad(::testing::_))
-        .Times(should_activate);
-    EXPECT_CALL(*client(), ToggleNotificationVisibility(false)).Times(1);
-    content::WebContentsTester::For(web_contents())->StartNavigation(url);
-    ::testing::Mock::VerifyAndClearExpectations(client());
-    factory()->ReadyToCommitMainFrameNavigation(main_rfh(), url);
-    content::RenderFrameHostTester::For(main_rfh())
-        ->SimulateNavigationCommit(url);
+      bool should_activate) {
+    BlacklistURLWithRedirectsNavigateAndCommit(bad_url, redirects, url,
+                                               should_activate);
 
-    ::testing::Mock::VerifyAndClearExpectations(driver());
-
-    NavigateToUrlAndExpectActivationAndHidingPromptSubFrame(
-        GURL(kExampleLoginUrl), should_activate);
+    NavigateAndCommitSubframe(GURL(kExampleLoginUrl), should_activate);
   }
 
-  void SpecialCaseNavSeq(bool should_activate,
-                         ActivationState state) {
+  void SpecialCaseNavSeq(const GURL& bad_url,
+                         const std::vector<GURL>& redirects,
+                         bool should_activate) {
     // This test-case examinse the nevigation woth following sequence of event:
     //   DidStartProvisional(main, "example.com")
     //   ReadyToCommitMainFrameNavigation(“example.com”)
@@ -210,8 +212,8 @@
     //   DidCommitProvisional(sub, "example.com/login")
     //   DidCommitProvisional(main, "example.com#ref")
 
-    NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrl),
-                                                    should_activate, state);
+    BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+        bad_url, redirects, GURL(kExampleUrl), should_activate);
     EXPECT_CALL(*driver(), ActivateForProvisionalLoad(::testing::_)).Times(0);
     EXPECT_CALL(*client(), ToggleNotificationVisibility(::testing::_)).Times(0);
     content::RenderFrameHostTester::For(main_rfh())
@@ -238,93 +240,10 @@
   ContentSubresourceFilterDriverFactoryThreatTypeTest() {}
   ~ContentSubresourceFilterDriverFactoryThreatTypeTest() override {}
 
-  void VerifyEntitiesNotInTheBlacklist(
-      const GURL& test_url,
-      const std::vector<GURL>& redirects,
-      const ActivationListTestData& test_data) {
-    factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
-        test_url, std::vector<GURL>(), test_data.threat_type,
-        test_data.threat_type_metadata);
-    EXPECT_EQ(test_data.should_add ? 1 : 0U,
-              factory()->activation_set().size());
-    EXPECT_EQ(test_data.should_add,
-              factory()->ShouldActivateForURL(GURL(test_url)));
-    EXPECT_EQ(test_data.should_add, factory()->ShouldActivateForURL(
-                                        GURL(test_url.GetWithEmptyPath())));
-    EXPECT_EQ(test_data.should_add,
-              factory()->ShouldActivateForURL(
-                  GURL("http://" + test_url.host() + "/path?q=q")));
-    factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
-        test_url, redirects, test_data.threat_type,
-        test_data.threat_type_metadata);
-    for (const auto& redirect : redirects) {
-      EXPECT_EQ(test_data.should_add,
-                factory()->ShouldActivateForURL(redirect));
-      EXPECT_EQ(test_data.should_add,
-                factory()->ShouldActivateForURL(redirect.GetWithEmptyPath()));
-      EXPECT_EQ(test_data.should_add, factory()->ShouldActivateForURL(
-                                          GURL("http://" + redirect.host())));
-      EXPECT_EQ(test_data.should_add,
-                factory()->ShouldActivateForURL(
-                    GURL("http://" + redirect.host() + "/path?q=q")));
-    }
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ContentSubresourceFilterDriverFactoryThreatTypeTest);
 };
 
-TEST_F(ContentSubresourceFilterDriverFactoryTest, SocEngHitEmptyRedirects) {
-  base::FieldTrialList field_trial_list(nullptr);
-  testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
-      base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
-      kActivationScopeNoSites, kActivationListSocialEngineeringAdsInterstitial);
-
-  BlacklistURLWithRedirects(GURL(kExampleUrlWithParams), std::vector<GURL>());
-  EXPECT_EQ(1U, factory()->activation_set().size());
-
-  EXPECT_TRUE(factory()->ShouldActivateForURL(GURL(kExampleUrl)));
-  EXPECT_TRUE(factory()->ShouldActivateForURL(GURL("http://example.com")));
-  EXPECT_TRUE(
-      factory()->ShouldActivateForURL(GURL("http://example.com/42?q=42!")));
-  EXPECT_TRUE(
-      factory()->ShouldActivateForURL(GURL("https://example.com/42?q=42!")));
-  EXPECT_TRUE(
-      factory()->ShouldActivateForURL(GURL("http://example.com/awesomepath")));
-  const GURL whitelisted("http://example.com/page?q=whitelisted");
-  EXPECT_TRUE(factory()->ShouldActivateForURL(whitelisted));
-  factory()->AddHostOfURLToWhitelistSet(whitelisted);
-  EXPECT_FALSE(factory()->ShouldActivateForURL(whitelisted));
-}
-
-TEST_F(ContentSubresourceFilterDriverFactoryTest, SocEngHitWithRedirects) {
-  base::FieldTrialList field_trial_list(nullptr);
-  testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
-      base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
-      kActivationScopeNoSites, kActivationListSocialEngineeringAdsInterstitial);
-
-  std::vector<GURL> redirects;
-  redirects.push_back(GURL("https://example1.com"));
-  redirects.push_back(GURL("https://example2.com"));
-  redirects.push_back(GURL("https://example3.com"));
-  BlacklistURLWithRedirects(GURL(kExampleUrlWithParams), redirects);
-  EXPECT_EQ(4U, factory()->activation_set().size());
-  EXPECT_TRUE(factory()->ShouldActivateForURL(GURL(kExampleUrl)));
-
-  for (const auto& redirect : redirects) {
-    EXPECT_TRUE(factory()->ShouldActivateForURL(redirect));
-    EXPECT_TRUE(factory()->ShouldActivateForURL(redirect.GetWithEmptyPath()));
-    EXPECT_TRUE(
-        factory()->ShouldActivateForURL(GURL("http://" + redirect.host())));
-    EXPECT_TRUE(factory()->ShouldActivateForURL(
-        GURL("http://" + redirect.host() + "/path?q=q")));
-  }
-  const GURL whitelisted("http://example.com/page?q=42");
-  EXPECT_TRUE(factory()->ShouldActivateForURL(whitelisted));
-  factory()->AddHostOfURLToWhitelistSet(whitelisted);
-  EXPECT_FALSE(factory()->ShouldActivateForURL(whitelisted));
-}
-
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
        ActivateForFrameHostNotNeeded) {
   base::FieldTrialList field_trial_list(nullptr);
@@ -333,10 +252,12 @@
       kActivationScopeNoSites, kActivationListSocialEngineeringAdsInterstitial);
   ActivateAndExpectForFrameHostForUrl(driver(), main_rfh(), GURL(kTestUrl),
                                       false /* should_activate */);
-  BlacklistURLWithRedirects(GURL(kExampleUrlWithParams), std::vector<GURL>());
-  ActivateAndExpectForFrameHostForUrl(driver(), main_rfh(),
-                                      GURL("https://not-example.com"),
-                                      false /* should_activate */);
+  const GURL url(kExampleUrlWithParams);
+  BlacklistURLWithRedirectsNavigateAndCommit(url, std::vector<GURL>(), url,
+                                             false /* should_activate */);
+  BlacklistURLWithRedirectsNavigateAndCommit(url, std::vector<GURL>(),
+                                             GURL("https://not-example.com"),
+                                             false /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest, ActivateForFrameHostNeeded) {
@@ -346,11 +267,11 @@
       kActivationScopeActivationList,
       kActivationListSocialEngineeringAdsInterstitial);
 
-  BlacklistURLWithRedirects(GURL(kExampleUrlWithParams), std::vector<GURL>());
-  ActivateAndExpectForFrameHostForUrl(driver(), main_rfh(), GURL(kTestUrl),
-                                      false /* should_activate */);
-  ActivateAndExpectForFrameHostForUrl(driver(), main_rfh(), GURL(kExampleUrl),
-                                      true /* should_activate */);
+  const GURL url(kExampleUrlWithParams);
+  BlacklistURLWithRedirectsNavigateAndCommit(url, std::vector<GURL>(), url,
+                                             true /* should_activate */);
+  BlacklistURLWithRedirectsNavigateAndCommit(
+      url, std::vector<GURL>(), GURL(kExampleUrl), false /* should_activate */);
 }
 
 TEST_P(ContentSubresourceFilterDriverFactoryThreatTypeTest, NonSocEngHit) {
@@ -366,7 +287,19 @@
   redirects.push_back(GURL("https://example3.com"));
 
   const GURL test_url("https://example.com/nonsoceng?q=engsocnon");
-  VerifyEntitiesNotInTheBlacklist(test_url, redirects, test_data);
+
+  BlacklistURLWithRedirectsNavigateAndCommit(GURL::EmptyGURL(),
+                                             std::vector<GURL>(), test_url,
+                                             false /* should_activate */);
+  EXPECT_CALL(*client(), ToggleNotificationVisibility(false)).Times(1);
+  content::WebContentsTester::For(web_contents())->StartNavigation(test_url);
+  ::testing::Mock::VerifyAndClearExpectations(client());
+  factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
+      test_url, redirects, test_data.threat_type,
+      test_data.threat_type_metadata);
+  ActivateAndExpectForFrameHostForUrl(driver(), main_rfh(), test_url, false);
+  content::RenderFrameHostTester::For(main_rfh())
+      ->SimulateNavigationCommit(test_url);
 };
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -376,8 +309,9 @@
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
       kActivationScopeActivationList,
       kActivationListSocialEngineeringAdsInterstitial);
-  NavigateToUrlAndExpectActivationAndHidingPromptSubFrame(
-      GURL(kExampleUrl), false /* should_prompt */);
+  BlacklistURLWithRedirectsNavigateAndCommit(
+      GURL::EmptyGURL(), std::vector<GURL>(), GURL(kExampleUrl),
+      false /* should_prompt */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -387,13 +321,13 @@
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateDryRun,
       kActivationScopeAllSites,
       kActivationListSocialEngineeringAdsInterstitial);
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  true /* should_activate */,
-                                                  ActivationState::DRYRUN);
-  factory()->AddHostOfURLToWhitelistSet(GURL(kExampleUrlWithParams));
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  false /* should_activate */,
-                                                  ActivationState::DISABLED);
+  const GURL url(kExampleUrlWithParams);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), url, true /* should_activate */);
+  factory()->AddHostOfURLToWhitelistSet(url);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), GURL(kExampleUrlWithParams),
+      false /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -403,13 +337,13 @@
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
       kActivationScopeAllSites,
       kActivationListSocialEngineeringAdsInterstitial);
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  true /* should_activate */,
-                                                  ActivationState::ENABLED);
-  factory()->AddHostOfURLToWhitelistSet(GURL(kExampleUrlWithParams));
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  false /* should_activate */,
-                                                  ActivationState::DISABLED);
+  const GURL url(kExampleUrlWithParams);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), url, true /* should_activate */);
+  factory()->AddHostOfURLToWhitelistSet(url);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), GURL(kExampleUrlWithParams),
+      false /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -419,14 +353,13 @@
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
       kActivationScopeActivationList,
       kActivationListSocialEngineeringAdsInterstitial);
-  BlacklistURLWithRedirects(GURL(kExampleUrlWithParams), std::vector<GURL>());
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  true /* should_activate */,
-                                                  ActivationState::ENABLED);
-  factory()->AddHostOfURLToWhitelistSet(GURL(kExampleUrlWithParams));
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  false /* should_activate */,
-                                                  ActivationState::DISABLED);
+  const GURL url(kExampleUrlWithParams);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), url, true /* should_activate */);
+  factory()->AddHostOfURLToWhitelistSet(url);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), GURL(kExampleUrlWithParams),
+      false /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -436,14 +369,12 @@
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateDryRun,
       kActivationScopeActivationList,
       kActivationListSocialEngineeringAdsInterstitial);
-  BlacklistURLWithRedirects(GURL(kExampleUrlWithParams), std::vector<GURL>());
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  true /* should_activate */,
-                                                  ActivationState::DRYRUN);
-  factory()->AddHostOfURLToWhitelistSet(GURL(kExampleUrlWithParams));
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  false /* should_activate */,
-                                                  ActivationState::DISABLED);
+  const GURL url(kExampleUrlWithParams);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), url, true /* should_activate */);
+  factory()->AddHostOfURLToWhitelistSet(url);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      url, std::vector<GURL>(), url, false /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -452,9 +383,9 @@
   testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateDryRun,
       kActivationScopeNoSites, kActivationListSocialEngineeringAdsInterstitial);
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  false /* should_activate */,
-                                                  ActivationState::DISABLED);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      GURL::EmptyGURL(), std::vector<GURL>(), GURL(kExampleUrlWithParams),
+      false /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -464,9 +395,9 @@
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateDisabled,
       kActivationScopeActivationList,
       kActivationListSocialEngineeringAdsInterstitial);
-  NavigateToUrlAndExpectActivationAndHidingPrompt(GURL(kExampleUrlWithParams),
-                                                  false /* should_activate */,
-                                                  ActivationState::DISABLED);
+  BlacklistURLWithRedirectsNavigateMainFrameAndSubrame(
+      GURL::EmptyGURL(), std::vector<GURL>(), GURL(kExampleUrlWithParams),
+      false /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -475,16 +406,20 @@
   testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateDryRun,
       kActivationScopeAllSites);
-  SpecialCaseNavSeq(true /* should_activate */, ActivationState::DRYRUN);
+  SpecialCaseNavSeq(GURL::EmptyGURL(), std::vector<GURL>(),
+                    true /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
        SpecialCaseNavigationAllSitesEnabled) {
+  // Check that when the experiment is enabled for all site, the activation
+  // signal is always sent.
   base::FieldTrialList field_trial_list(nullptr);
   testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
       kActivationScopeAllSites);
-  SpecialCaseNavSeq(true /* should_activate */, ActivationState::ENABLED);
+  SpecialCaseNavSeq(GURL::EmptyGURL(), std::vector<GURL>(),
+                    true /* should_activate */);
 }
 
 TEST_F(ContentSubresourceFilterDriverFactoryTest,
@@ -494,8 +429,8 @@
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
       kActivationScopeActivationList,
       kActivationListSocialEngineeringAdsInterstitial);
-  BlacklistURLWithRedirects(GURL(kExampleUrlWithParams), std::vector<GURL>());
-  SpecialCaseNavSeq(true /* should_activate */, ActivationState::ENABLED);
+  SpecialCaseNavSeq(GURL(kExampleUrl), std::vector<GURL>(),
+                    true /* should_activate */);
 }
 
 INSTANTIATE_TEST_CASE_P(NoSonEngHit,
diff --git a/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.cc
index b735d1c..7e9dee2 100644
--- a/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.cc
@@ -21,31 +21,11 @@
 
 SubresourceFilterNavigationThrottle::SubresourceFilterNavigationThrottle(
     content::NavigationHandle* handle)
-    : content::NavigationThrottle(handle),
-      initial_url_(navigation_handle()->GetURL()) {}
+    : content::NavigationThrottle(handle) {}
 
 SubresourceFilterNavigationThrottle::~SubresourceFilterNavigationThrottle() {}
 
 content::NavigationThrottle::ThrottleCheckResult
-SubresourceFilterNavigationThrottle::WillRedirectRequest() {
-  if (!navigation_handle()->GetURL().SchemeIsHTTPOrHTTPS())
-    return NavigationThrottle::PROCEED;
-  ContentSubresourceFilterDriverFactory* driver_factory =
-      ContentSubresourceFilterDriverFactory::FromWebContents(
-          navigation_handle()->GetWebContents());
-  // Ensure that the activation state of the subresource filter is persisted
-  // beyond redirects. In case of the desktop platforms, where Safe Browsing
-  // check is performed synchronously it's guaranteed that |driver_factory| has
-  // the information about the activation set. But if the Safe Browsing check in
-  // asynchronous, then we night miss some redirects.
-  if (driver_factory->ShouldActivateForURL(initial_url_)) {
-    driver_factory->AddHostOfURLToActivationSet(navigation_handle()->GetURL());
-  }
-
-  return NavigationThrottle::PROCEED;
-}
-
-content::NavigationThrottle::ThrottleCheckResult
 SubresourceFilterNavigationThrottle::WillProcessResponse() {
   if (!navigation_handle()->GetURL().SchemeIsHTTPOrHTTPS())
     return NavigationThrottle::PROCEED;
@@ -53,7 +33,8 @@
   ContentSubresourceFilterDriverFactory::FromWebContents(
       navigation_handle()->GetWebContents())
       ->ReadyToCommitMainFrameNavigation(
-          navigation_handle()->GetRenderFrameHost(), initial_url_);
+          navigation_handle()->GetRenderFrameHost(),
+          navigation_handle()->GetURL());
 
   return NavigationThrottle::PROCEED;
 }
diff --git a/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.h b/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.h
index 15816fc..a620512 100644
--- a/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.h
+++ b/components/subresource_filter/content/browser/subresource_filter_navigation_throttle.h
@@ -34,15 +34,12 @@
   ~SubresourceFilterNavigationThrottle() override;
 
   // content::NavigationThrottle implementation:
-  ThrottleCheckResult WillRedirectRequest() override;
   ThrottleCheckResult WillProcessResponse() override;
 
  private:
   explicit SubresourceFilterNavigationThrottle(
       content::NavigationHandle* navigation_handle);
 
-  GURL initial_url_;
-
   DISALLOW_COPY_AND_ASSIGN(SubresourceFilterNavigationThrottle);
 };
 
diff --git a/components/subresource_filter/content/browser/subresource_filter_navigation_throttle_unittests.cc b/components/subresource_filter/content/browser/subresource_filter_navigation_throttle_unittests.cc
index 952cbec..335eed7 100644
--- a/components/subresource_filter/content/browser/subresource_filter_navigation_throttle_unittests.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_navigation_throttle_unittests.cc
@@ -142,9 +142,6 @@
       .Times(1);
   SimulateWillProcessResponse();
   ::testing::Mock::VerifyAndClearExpectations(driver());
-
-  EXPECT_EQ(1U, factory()->activation_set().size());
-  EXPECT_TRUE(factory()->ShouldActivateForURL(url));
 }
 
 TEST_F(SubresourceFilterNavigationThrottleTest,
@@ -169,10 +166,6 @@
   EXPECT_CALL(*driver(), ActivateForProvisionalLoad(::testing::_)).Times(0);
   SimulateWillProcessResponse();
   ::testing::Mock::VerifyAndClearExpectations(driver());
-
-  EXPECT_EQ(1U, factory()->activation_set().size());
-  EXPECT_TRUE(factory()->ShouldActivateForURL(url_with_activation));
-  EXPECT_FALSE(factory()->ShouldActivateForURL(url_without_activation));
 }
 
 TEST_F(SubresourceFilterNavigationThrottleTest,
@@ -196,9 +189,6 @@
   EXPECT_CALL(*driver(), ActivateForProvisionalLoad(::testing::_)).Times(0);
   SimulateWillProcessResponse();
   ::testing::Mock::VerifyAndClearExpectations(driver());
-
-  EXPECT_EQ(0U, factory()->activation_set().size());
-  EXPECT_FALSE(factory()->ShouldActivateForURL(non_web_url));
 }
 
 TEST_F(SubresourceFilterNavigationThrottleTest,
@@ -218,7 +208,7 @@
   SetUpNavigationHandleForURL(url);
   SimulateWillStart();
   factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
-      url, std::vector<GURL>(), safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
+      redirect, std::vector<GURL>(), safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
       safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS);
   SimulateRedirects(redirect);
 
@@ -226,18 +216,13 @@
       .Times(1);
   SimulateWillProcessResponse();
   ::testing::Mock::VerifyAndClearExpectations(driver());
-
-  EXPECT_EQ(2U, factory()->activation_set().size());
-  EXPECT_TRUE(factory()->ShouldActivateForURL(url));
-  EXPECT_TRUE(factory()->ShouldActivateForURL(redirect));
 }
 
 TEST_F(SubresourceFilterNavigationThrottleTest,
        AddRedirectFromNavThrottleToServiceNonEmptyInitRedirects) {
   // Navigations |redirects| -> |url| -> |redirect_after_sb_classification|.
   // Safe Browsing classifies the |url| as containing deceptive content.
-  // Test checks that |url|, |redirects| and |redirect_after_sb_classification|
-  // are in the activation set.
+  // Test checks that |url| it doesn't lead to sending the activation signal.
   base::FieldTrialList field_trial_list(nullptr);
   testing::ScopedSubresourceFilterFeatureToggle scoped_feature_toggle(
       base::FeatureList::OVERRIDE_ENABLE_FEATURE, kActivationStateEnabled,
@@ -255,24 +240,14 @@
 
   std::vector<GURL> redirects = {first_redirect, second_redirect,
                                  third_redirect};
+  SimulateRedirects(redirect_after_sb_classification);
   factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
       url, redirects, safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
       safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS);
 
-  SimulateRedirects(redirect_after_sb_classification);
-
-  EXPECT_CALL(*driver(), ActivateForProvisionalLoad(ActivationState::ENABLED))
-      .Times(1);
+  EXPECT_CALL(*driver(), ActivateForProvisionalLoad(::testing::_)).Times(0);
   SimulateWillProcessResponse();
   ::testing::Mock::VerifyAndClearExpectations(driver());
-
-  EXPECT_EQ(redirects.size() + 2U, factory()->activation_set().size());
-  EXPECT_TRUE(factory()->ShouldActivateForURL(url));
-  EXPECT_TRUE(factory()->ShouldActivateForURL(first_redirect));
-  EXPECT_TRUE(factory()->ShouldActivateForURL(second_redirect));
-  EXPECT_TRUE(factory()->ShouldActivateForURL(third_redirect));
-  EXPECT_TRUE(
-      factory()->ShouldActivateForURL(redirect_after_sb_classification));
 }
 
 TEST_F(SubresourceFilterNavigationThrottleTest,
@@ -287,24 +262,17 @@
   const GURL redirect_with_match(kRedirectURLFirst);
   const GURL final_url(kRedirectURLSecond);
   std::vector<GURL> redirects = {redirect_with_match};
-  factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
-      init_url, redirects, safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
-      safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS);
-
   SetUpNavigationHandleForURL(init_url);
   SimulateWillStart();
   SimulateRedirects(redirect_with_match);
   SimulateRedirects(final_url);
-
+  factory()->OnMainResourceMatchedSafeBrowsingBlacklist(
+      final_url, redirects, safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
+      safe_browsing::ThreatPatternType::SOCIAL_ENGINEERING_ADS);
   EXPECT_CALL(*driver(), ActivateForProvisionalLoad(ActivationState::ENABLED))
       .Times(1);
   SimulateWillProcessResponse();
   ::testing::Mock::VerifyAndClearExpectations(driver());
-
-  EXPECT_EQ(3U, factory()->activation_set().size());
-  EXPECT_TRUE(factory()->ShouldActivateForURL(init_url));
-  EXPECT_TRUE(factory()->ShouldActivateForURL(redirect_with_match));
-  EXPECT_TRUE(factory()->ShouldActivateForURL(final_url));
 }
 
 }  // namespace subresource_filter
diff --git a/components/test_runner/test_interfaces.cc b/components/test_runner/test_interfaces.cc
index d2829325..49d88a9 100644
--- a/components/test_runner/test_interfaces.cc
+++ b/components/test_runner/test_interfaces.cc
@@ -113,7 +113,8 @@
     test_runner_->setShouldDumpAsMarkup(true);
   }
   if (spec.find("/imported/wpt/") != std::string::npos ||
-      spec.find("/imported/csswg-test/") != std::string::npos)
+      spec.find("/imported/csswg-test/") != std::string::npos ||
+      spec.find("://web-platform.test") != std::string::npos)
     test_runner_->set_is_web_platform_tests_mode();
 }
 
diff --git a/content/app/android/library_loader_hooks.cc b/content/app/android/library_loader_hooks.cc
index be9cd37f..2aebbb76 100644
--- a/content/app/android/library_loader_hooks.cc
+++ b/content/app/android/library_loader_hooks.cc
@@ -103,10 +103,10 @@
     if (!media::RegisterCaptureJni(env))
       return false;
 
-    if (!media::midi::RegisterJni(env))
+    if (!media::RegisterScreenCaptureJni(env))
       return false;
 
-    if (!media::RegisterScreenCaptureJni(env))
+    if (!midi::RegisterJni(env))
       return false;
 
     if (!ui::RegisterUIAndroidJni(env))
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 55b3de6..654db69 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -1288,7 +1288,7 @@
 
   {
     TRACE_EVENT0("startup", "BrowserThreadsStarted::Subsystem:MidiManager");
-    midi_manager_.reset(media::midi::MidiManager::Create());
+    midi_manager_.reset(midi::MidiManager::Create());
   }
 
 #if defined(OS_WIN)
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index c0217e72..ec0ec8b 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -49,10 +49,11 @@
 #if defined(OS_MACOSX)
 class DeviceMonitorMac;
 #endif
+}  // namespace media
+
 namespace midi {
 class MidiManager;
 }  // namespace midi
-}  // namespace media
 
 namespace mojo {
 namespace edk {
@@ -143,7 +144,7 @@
   device::TimeZoneMonitor* time_zone_monitor() const {
     return time_zone_monitor_.get();
   }
-  media::midi::MidiManager* midi_manager() const { return midi_manager_.get(); }
+  midi::MidiManager* midi_manager() const { return midi_manager_.get(); }
   base::Thread* indexed_db_thread() const { return indexed_db_thread_.get(); }
 
   bool is_tracing_startup_for_duration() const {
@@ -287,7 +288,7 @@
   std::unique_ptr<base::Thread> audio_thread_;
   media::ScopedAudioManagerPtr audio_manager_;
 
-  std::unique_ptr<media::midi::MidiManager> midi_manager_;
+  std::unique_ptr<midi::MidiManager> midi_manager_;
 
 #if defined(OS_WIN)
   std::unique_ptr<media::SystemMessageWindowWin> system_message_window_;
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc
index b0f6efe..b0cb428 100644
--- a/content/browser/frame_host/navigation_handle_impl.cc
+++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -91,6 +91,10 @@
       weak_factory_(this) {
   DCHECK(!navigation_start.is_null());
   redirect_chain_.push_back(url);
+
+  starting_site_instance_ =
+      frame_tree_node_->current_frame_host()->GetSiteInstance();
+
   GetDelegate()->DidStartNavigation(this);
 
   if (IsInMainFrame()) {
@@ -128,6 +132,10 @@
   return url_;
 }
 
+SiteInstance* NavigationHandleImpl::GetStartingSiteInstance() {
+  return starting_site_instance_.get();
+}
+
 bool NavigationHandleImpl::IsInMainFrame() {
   return frame_tree_node_->IsMainFrame();
 }
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h
index 66b9295..58aff96 100644
--- a/content/browser/frame_host/navigation_handle_impl.h
+++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -33,7 +33,6 @@
 class ResourceRequestBodyImpl;
 class ServiceWorkerContextWrapper;
 class ServiceWorkerNavigationHandle;
-class SiteInstance;
 
 // This class keeps track of a single navigation. It is created upon receipt of
 // a DidStartProvisionalLoad IPC in a RenderFrameHost. The RenderFrameHost owns
@@ -87,6 +86,7 @@
 
   // NavigationHandle implementation:
   const GURL& GetURL() override;
+  SiteInstance* GetStartingSiteInstance() override;
   bool IsInMainFrame() override;
   bool IsParentMainFrame() override;
   bool IsRendererInitiated() override;
@@ -335,6 +335,7 @@
 
   // See NavigationHandle for a description of those member variables.
   GURL url_;
+  scoped_refptr<SiteInstance> starting_site_instance_;
   Referrer sanitized_referrer_;
   bool has_user_gesture_;
   ui::PageTransition transition_;
diff --git a/content/browser/media/midi_host.cc b/content/browser/media/midi_host.cc
index 17dcccc..1f02d20 100644
--- a/content/browser/media/midi_host.cc
+++ b/content/browser/media/midi_host.cc
@@ -12,10 +12,8 @@
 #include "content/browser/bad_message.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/media/media_internals.h"
 #include "content/common/media/midi_messages.h"
 #include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/media_observer.h"
 #include "content/public/browser/user_metrics.h"
 #include "media/midi/midi_manager.h"
 #include "media/midi/midi_message_queue.h"
@@ -44,11 +42,11 @@
 
 }  // namespace
 
-using media::midi::kSysExByte;
-using media::midi::kEndOfSysExByte;
+using midi::kSysExByte;
+using midi::kEndOfSysExByte;
 
 MidiHost::MidiHost(int renderer_process_id,
-                   media::midi::MidiManager* midi_manager)
+                   midi::MidiManager* midi_manager)
     : BrowserMessageFilter(MidiMsgStart),
       renderer_process_id_(renderer_process_id),
       has_sys_ex_permission_(false),
@@ -143,9 +141,9 @@
     midi_manager_->EndSession(this);
 }
 
-void MidiHost::CompleteStartSession(media::midi::Result result) {
+void MidiHost::CompleteStartSession(midi::Result result) {
   DCHECK(is_session_requested_);
-  if (result == media::midi::Result::OK) {
+  if (result == midi::Result::OK) {
     // ChildSecurityPolicy is set just before OnStartSession by
     // MidiDispatcherHost. So we can safely cache the policy.
     has_sys_ex_permission_ = ChildProcessSecurityPolicyImpl::GetInstance()->
@@ -154,26 +152,26 @@
   Send(new MidiMsg_SessionStarted(result));
 }
 
-void MidiHost::AddInputPort(const media::midi::MidiPortInfo& info) {
+void MidiHost::AddInputPort(const midi::MidiPortInfo& info) {
   base::AutoLock auto_lock(messages_queues_lock_);
   // MidiMessageQueue is created later in ReceiveMidiData().
   received_messages_queues_.push_back(nullptr);
   Send(new MidiMsg_AddInputPort(info));
 }
 
-void MidiHost::AddOutputPort(const media::midi::MidiPortInfo& info) {
+void MidiHost::AddOutputPort(const midi::MidiPortInfo& info) {
   base::AutoLock auto_lock(output_port_count_lock_);
   output_port_count_++;
   Send(new MidiMsg_AddOutputPort(info));
 }
 
 void MidiHost::SetInputPortState(uint32_t port,
-                                 media::midi::MidiPortState state) {
+                                 midi::MidiPortState state) {
   Send(new MidiMsg_SetInputPortState(port, state));
 }
 
 void MidiHost::SetOutputPortState(uint32_t port,
-                                  media::midi::MidiPortState state) {
+                                  midi::MidiPortState state) {
   Send(new MidiMsg_SetOutputPortState(port, state));
 }
 
@@ -189,7 +187,7 @@
 
   // Lazy initialization
   if (received_messages_queues_[port] == nullptr)
-    received_messages_queues_[port] = new media::midi::MidiMessageQueue(true);
+    received_messages_queues_[port] = new midi::MidiMessageQueue(true);
 
   received_messages_queues_[port]->Add(data, length);
   std::vector<uint8_t> message;
@@ -262,7 +260,7 @@
       sysex_start_offset = i;
       continue;  // Found SysEX
     }
-    waiting_data_length = media::midi::GetMidiMessageLength(current);
+    waiting_data_length = midi::GetMidiMessageLength(current);
     if (waiting_data_length == 0)
       return false;  // Error: |current| should have been a valid status byte.
     --waiting_data_length;  // Found status byte
diff --git a/content/browser/media/midi_host.h b/content/browser/media/midi_host.h
index fc126ac..c563bb50 100644
--- a/content/browser/media/midi_host.h
+++ b/content/browser/media/midi_host.h
@@ -22,20 +22,18 @@
 #include "media/midi/midi_manager.h"
 #include "media/midi/midi_port_info.h"
 
-namespace media {
 namespace midi {
 class MidiManager;
 class MidiMessageQueue;
-}
-}
+}  // namespace midi
 
 namespace content {
 
 class CONTENT_EXPORT MidiHost : public BrowserMessageFilter,
-                                public media::midi::MidiManagerClient {
+                                public midi::MidiManagerClient {
  public:
   // Called from UI thread from the owner of this object.
-  MidiHost(int renderer_process_id, media::midi::MidiManager* midi_manager);
+  MidiHost(int renderer_process_id, midi::MidiManager* midi_manager);
 
   // BrowserMessageFilter implementation.
   void OnChannelClosing() override;
@@ -43,13 +41,13 @@
   bool OnMessageReceived(const IPC::Message& message) override;
 
   // MidiManagerClient implementation.
-  void CompleteStartSession(media::midi::Result result) override;
-  void AddInputPort(const media::midi::MidiPortInfo& info) override;
-  void AddOutputPort(const media::midi::MidiPortInfo& info) override;
+  void CompleteStartSession(midi::Result result) override;
+  void AddInputPort(const midi::MidiPortInfo& info) override;
+  void AddOutputPort(const midi::MidiPortInfo& info) override;
   void SetInputPortState(uint32_t port,
-                         media::midi::MidiPortState state) override;
+                         midi::MidiPortState state) override;
   void SetOutputPortState(uint32_t port,
-                          media::midi::MidiPortState state) override;
+                          midi::MidiPortState state) override;
   void ReceiveMidiData(uint32_t port,
                        const uint8_t* data,
                        size_t length,
@@ -96,10 +94,10 @@
   // does not support MIDI.  If not supported then a call to
   // OnRequestAccess() will always refuse access and a call to
   // OnSendData() will do nothing.
-  media::midi::MidiManager* midi_manager_;
+  midi::MidiManager* midi_manager_;
 
   // Buffers where data sent from each MIDI input port is stored.
-  ScopedVector<media::midi::MidiMessageQueue> received_messages_queues_;
+  ScopedVector<midi::MidiMessageQueue> received_messages_queues_;
 
   // Protects access to |received_messages_queues_|;
   base::Lock messages_queues_lock_;
diff --git a/content/browser/media/midi_host_unittest.cc b/content/browser/media/midi_host_unittest.cc
index 21306af..2a7afb8 100644
--- a/content/browser/media/midi_host_unittest.cc
+++ b/content/browser/media/midi_host_unittest.cc
@@ -71,9 +71,9 @@
   double timestamp;
 };
 
-class FakeMidiManager : public media::midi::MidiManager {
+class FakeMidiManager : public midi::MidiManager {
  public:
-  void DispatchSendMidiData(media::midi::MidiManagerClient* client,
+  void DispatchSendMidiData(midi::MidiManagerClient* client,
                             uint32_t port_index,
                             const std::vector<uint8_t>& data,
                             double timestamp) override {
@@ -88,7 +88,7 @@
 class MidiHostForTesting : public MidiHost {
  public:
   MidiHostForTesting(int renderer_process_id,
-                     media::midi::MidiManager* midi_manager)
+                     midi::MidiManager* midi_manager)
       : MidiHost(renderer_process_id, midi_manager) {}
 
  private:
@@ -119,8 +119,8 @@
     const std::string manufacturer("yukatan");
     const std::string name("doki-doki-pi-pine");
     const std::string version("3.14159265359");
-    media::midi::MidiPortState state = media::midi::MIDI_PORT_CONNECTED;
-    media::midi::MidiPortInfo info(id, manufacturer, name, version, state);
+    midi::MidiPortState state = midi::MIDI_PORT_CONNECTED;
+    midi::MidiPortInfo info(id, manufacturer, name, version, state);
 
     host_->AddOutputPort(info);
   }
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index e5b8d2a..9c9c424 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -41,6 +41,7 @@
 #include "content/common/renderer.mojom.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/interstitial_page_delegate.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
@@ -8349,4 +8350,33 @@
   transfer_manager.WaitForNavigationFinished();
 }
 
+class NavigationHandleWatcher : public WebContentsObserver {
+ public:
+  NavigationHandleWatcher(WebContents* web_contents)
+      : WebContentsObserver(web_contents) {}
+  void DidStartNavigation(NavigationHandle* navigation_handle) override {
+    DCHECK_EQ(GURL("http://b.com/"),
+              navigation_handle->GetStartingSiteInstance()->GetSiteURL());
+  }
+};
+
+// Verifies that the SiteInstance of a NavigationHandle correctly identifies the
+// RenderFrameHost that started the navigation (and not the destination RFH).
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+                       NavigationHandleSiteInstance) {
+  // Navigate to a page with a cross-site iframe.
+  GURL main_url(embedded_test_server()->GetURL(
+      "a.com", "/cross_site_iframe_factory.html?a(b)"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // Navigate the iframe cross-site.
+  NavigationHandleWatcher watcher(shell()->web_contents());
+  TestNavigationObserver load_observer(shell()->web_contents());
+  GURL frame_url = embedded_test_server()->GetURL("c.com", "/title1.html");
+  EXPECT_TRUE(ExecuteScript(
+      shell()->web_contents(),
+      "window.frames[0].location = \"" + frame_url.spec() + "\";"));
+  load_observer.Wait();
+}
+
 }  // namespace content
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index 59d8e32..95badb0 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -49,7 +49,6 @@
 #include "content/child/web_url_request_util.h"
 #include "content/child/worker_thread_registry.h"
 #include "content/public/common/content_client.h"
-#include "net/base/data_url.h"
 #include "net/base/net_errors.h"
 #include "third_party/WebKit/public/platform/WebData.h"
 #include "third_party/WebKit/public/platform/WebFloatPoint.h"
@@ -420,19 +419,6 @@
   return blink::WebString::fromUTF8(GetContentClient()->GetUserAgent());
 }
 
-WebData BlinkPlatformImpl::parseDataURL(const WebURL& url,
-                                        WebString& mimetype_out,
-                                        WebString& charset_out) {
-  std::string mime_type, char_set, data;
-  if (net::DataURL::Parse(url, &mime_type, &char_set, &data) &&
-      mime_util::IsSupportedMimeType(mime_type)) {
-    mimetype_out = WebString::fromUTF8(mime_type);
-    charset_out = WebString::fromUTF8(char_set);
-    return data;
-  }
-  return WebData();
-}
-
 WebURLError BlinkPlatformImpl::cancelledError(
     const WebURL& unreachableURL) const {
   return CreateWebURLError(unreachableURL, false, net::ERR_ABORTED);
diff --git a/content/child/blink_platform_impl.h b/content/child/blink_platform_impl.h
index 2553900..74acb64 100644
--- a/content/child/blink_platform_impl.h
+++ b/content/child/blink_platform_impl.h
@@ -86,9 +86,6 @@
   size_t maxDecodedImageBytes() override;
   uint32_t getUniqueIdForProcess() override;
   blink::WebString userAgent() override;
-  blink::WebData parseDataURL(const blink::WebURL& url,
-                              blink::WebString& mimetype,
-                              blink::WebString& charset) override;
   blink::WebURLError cancelledError(const blink::WebURL& url) const override;
   blink::WebThread* createThread(const char* name) override;
   blink::WebThread* currentThread() override;
diff --git a/content/common/media/midi_messages.h b/content/common/media/midi_messages.h
index 504b3956..44747a9b 100644
--- a/content/common/media/midi_messages.h
+++ b/content/common/media/midi_messages.h
@@ -18,10 +18,10 @@
 #define IPC_MESSAGE_EXPORT CONTENT_EXPORT
 #define IPC_MESSAGE_START MidiMsgStart
 
-IPC_ENUM_TRAITS_MAX_VALUE(media::midi::MidiPortState,
-                          media::midi::MIDI_PORT_STATE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(midi::MidiPortState,
+                          midi::MIDI_PORT_STATE_LAST)
 
-IPC_STRUCT_TRAITS_BEGIN(media::midi::MidiPortInfo)
+IPC_STRUCT_TRAITS_BEGIN(midi::MidiPortInfo)
   IPC_STRUCT_TRAITS_MEMBER(id)
   IPC_STRUCT_TRAITS_MEMBER(manufacturer)
   IPC_STRUCT_TRAITS_MEMBER(name)
@@ -29,7 +29,7 @@
   IPC_STRUCT_TRAITS_MEMBER(state)
 IPC_STRUCT_TRAITS_END()
 
-IPC_ENUM_TRAITS_MAX_VALUE(media::midi::Result, media::midi::Result::MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(midi::Result, midi::Result::MAX)
 
 // Messages for IPC between MidiMessageFilter and MidiHost.
 
@@ -46,20 +46,20 @@
 // Messages sent from the browser to the renderer.
 
 IPC_MESSAGE_CONTROL1(MidiMsg_AddInputPort,
-                     media::midi::MidiPortInfo /* input port */)
+                     midi::MidiPortInfo /* input port */)
 
 IPC_MESSAGE_CONTROL1(MidiMsg_AddOutputPort,
-                     media::midi::MidiPortInfo /* output port */)
+                     midi::MidiPortInfo /* output port */)
 
 IPC_MESSAGE_CONTROL2(MidiMsg_SetInputPortState,
                      uint32_t /* port */,
-                     media::midi::MidiPortState /* state */)
+                     midi::MidiPortState /* state */)
 
 IPC_MESSAGE_CONTROL2(MidiMsg_SetOutputPortState,
                      uint32_t /* port */,
-                     media::midi::MidiPortState /* state */)
+                     midi::MidiPortState /* state */)
 
-IPC_MESSAGE_CONTROL1(MidiMsg_SessionStarted, media::midi::Result /* result */)
+IPC_MESSAGE_CONTROL1(MidiMsg_SessionStarted, midi::Result /* result */)
 
 IPC_MESSAGE_CONTROL3(MidiMsg_DataReceived,
                      uint32_t /* port */,
diff --git a/content/public/browser/navigation_handle.h b/content/public/browser/navigation_handle.h
index 87707771..1c65544 100644
--- a/content/public/browser/navigation_handle.h
+++ b/content/public/browser/navigation_handle.h
@@ -23,6 +23,7 @@
 class NavigationData;
 class NavigationThrottle;
 class RenderFrameHost;
+class SiteInstance;
 class WebContents;
 
 // A NavigationHandle tracks information related to a single navigation.
@@ -48,6 +49,11 @@
   // virtual URL is prefixed with "view-source:".
   virtual const GURL& GetURL() = 0;
 
+  // Returns the SiteInstance that started the request.
+  // If a frame in SiteInstance A navigates a frame in SiteInstance B to a URL
+  // in SiteInstance C, then this returns B.
+  virtual SiteInstance* GetStartingSiteInstance() = 0;
+
   // Whether the navigation is taking place in the main frame or in a subframe.
   // This remains constant over the navigation lifetime.
   virtual bool IsInMainFrame() = 0;
diff --git a/content/renderer/media/midi_message_filter.cc b/content/renderer/media/midi_message_filter.cc
index a9810ab..98adfee 100644
--- a/content/renderer/media/midi_message_filter.cc
+++ b/content/renderer/media/midi_message_filter.cc
@@ -28,7 +28,7 @@
     : sender_(nullptr),
       io_task_runner_(io_task_runner),
       main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      session_result_(media::midi::Result::NOT_INITIALIZED),
+      session_result_(midi::Result::NOT_INITIALIZED),
       unacknowledged_bytes_sent_(0u) {
 }
 
@@ -38,7 +38,7 @@
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   TRACE_EVENT0("midi", "MidiMessageFilter::AddClient");
   clients_waiting_session_queue_.push_back(client);
-  if (session_result_ != media::midi::Result::NOT_INITIALIZED) {
+  if (session_result_ != midi::Result::NOT_INITIALIZED) {
     HandleClientAdded(session_result_);
   } else if (clients_waiting_session_queue_.size() == 1u) {
     io_task_runner_->PostTask(
@@ -56,7 +56,7 @@
   if (it != clients_waiting_session_queue_.end())
     clients_waiting_session_queue_.erase(it);
   if (clients_.empty() && clients_waiting_session_queue_.empty()) {
-    session_result_ = media::midi::Result::NOT_INITIALIZED;
+    session_result_ = midi::Result::NOT_INITIALIZED;
     inputs_.clear();
     outputs_.clear();
     io_task_runner_->PostTask(
@@ -142,7 +142,7 @@
   sender_ = nullptr;
 }
 
-void MidiMessageFilter::OnSessionStarted(media::midi::Result result) {
+void MidiMessageFilter::OnSessionStarted(midi::Result result) {
   TRACE_EVENT0("midi", "MidiMessageFilter::OnSessionStarted");
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   // Handle on the main JS thread.
@@ -151,14 +151,14 @@
       base::Bind(&MidiMessageFilter::HandleClientAdded, this, result));
 }
 
-void MidiMessageFilter::OnAddInputPort(media::midi::MidiPortInfo info) {
+void MidiMessageFilter::OnAddInputPort(midi::MidiPortInfo info) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   main_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&MidiMessageFilter::HandleAddInputPort, this, info));
 }
 
-void MidiMessageFilter::OnAddOutputPort(media::midi::MidiPortInfo info) {
+void MidiMessageFilter::OnAddOutputPort(midi::MidiPortInfo info) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   main_task_runner_->PostTask(
       FROM_HERE,
@@ -166,7 +166,7 @@
 }
 
 void MidiMessageFilter::OnSetInputPortState(uint32_t port,
-                                            media::midi::MidiPortState state) {
+                                            midi::MidiPortState state) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   main_task_runner_->PostTask(
       FROM_HERE, base::Bind(&MidiMessageFilter::HandleSetInputPortState, this,
@@ -174,7 +174,7 @@
 }
 
 void MidiMessageFilter::OnSetOutputPortState(uint32_t port,
-                                             media::midi::MidiPortState state) {
+                                             midi::MidiPortState state) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   main_task_runner_->PostTask(
       FROM_HERE, base::Bind(&MidiMessageFilter::HandleSetOutputPortState, this,
@@ -199,19 +199,19 @@
                             this, bytes_sent));
 }
 
-void MidiMessageFilter::HandleClientAdded(media::midi::Result result) {
+void MidiMessageFilter::HandleClientAdded(midi::Result result) {
   TRACE_EVENT0("midi", "MidiMessageFilter::HandleClientAdded");
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   session_result_ = result;
   std::string error;
   std::string message;
   switch (result) {
-    case media::midi::Result::OK:
+    case midi::Result::OK:
       break;
-    case media::midi::Result::NOT_SUPPORTED:
+    case midi::Result::NOT_SUPPORTED:
       error = "NotSupportedError";
       break;
-    case media::midi::Result::INITIALIZATION_ERROR:
+    case midi::Result::INITIALIZATION_ERROR:
       error = "InvalidStateError";
       message = "Platform dependent initialization failed.";
       break;
@@ -229,7 +229,7 @@
   while (!clients_waiting_session_queue_.empty()) {
     auto* client = clients_waiting_session_queue_.back();
     clients_waiting_session_queue_.pop_back();
-    if (result == media::midi::Result::OK) {
+    if (result == midi::Result::OK) {
       // Add the client's input and output ports.
       for (const auto& info : inputs_) {
         client->didAddInputPort(
@@ -249,13 +249,13 @@
             ToBlinkState(info.state));
       }
     }
-    client->didStartSession(result == media::midi::Result::OK, error16,
+    client->didStartSession(result == midi::Result::OK, error16,
                             message16);
     clients_.insert(client);
   }
 }
 
-void MidiMessageFilter::HandleAddInputPort(media::midi::MidiPortInfo info) {
+void MidiMessageFilter::HandleAddInputPort(midi::MidiPortInfo info) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   inputs_.push_back(info);
   const base::string16 id = base::UTF8ToUTF16(info.id);
@@ -268,7 +268,7 @@
     client->didAddInputPort(id, manufacturer, name, version, state);
 }
 
-void MidiMessageFilter::HandleAddOutputPort(media::midi::MidiPortInfo info) {
+void MidiMessageFilter::HandleAddOutputPort(midi::MidiPortInfo info) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   outputs_.push_back(info);
   const base::string16 id = base::UTF8ToUTF16(info.id);
@@ -301,7 +301,7 @@
 
 void MidiMessageFilter::HandleSetInputPortState(
     uint32_t port,
-    media::midi::MidiPortState state) {
+    midi::MidiPortState state) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   inputs_[port].state = state;
   for (auto* client : clients_)
@@ -310,7 +310,7 @@
 
 void MidiMessageFilter::HandleSetOutputPortState(
     uint32_t port,
-    media::midi::MidiPortState state) {
+    midi::MidiPortState state) {
   DCHECK(main_task_runner_->BelongsToCurrentThread());
   outputs_[port].state = state;
   for (auto* client : clients_)
diff --git a/content/renderer/media/midi_message_filter.h b/content/renderer/media/midi_message_filter.h
index 67a560f..c530975 100644
--- a/content/renderer/media/midi_message_filter.h
+++ b/content/renderer/media/midi_message_filter.h
@@ -55,10 +55,10 @@
   }
 
   static blink::WebMIDIAccessorClient::MIDIPortState ToBlinkState(
-      media::midi::MidiPortState state) {
+      midi::MidiPortState state) {
     // "open" status is separately managed by blink per MIDIAccess instance.
-    if (state == media::midi::MIDI_PORT_OPENED)
-      state = media::midi::MIDI_PORT_CONNECTED;
+    if (state == midi::MIDI_PORT_OPENED)
+      state = midi::MIDI_PORT_CONNECTED;
     return static_cast<blink::WebMIDIAccessorClient::MIDIPortState>(state);
   }
 
@@ -85,21 +85,21 @@
 
   // Called when the browser process has approved (or denied) access to
   // MIDI hardware.
-  void OnSessionStarted(media::midi::Result result);
+  void OnSessionStarted(midi::Result result);
 
   // These functions are called in 2 cases:
   //  (1) Just before calling |OnSessionStarted|, to notify the recipient about
   //      existing ports.
   //  (2) To notify the recipient that a new device was connected and that new
   //      ports have been created.
-  void OnAddInputPort(media::midi::MidiPortInfo info);
-  void OnAddOutputPort(media::midi::MidiPortInfo info);
+  void OnAddInputPort(midi::MidiPortInfo info);
+  void OnAddOutputPort(midi::MidiPortInfo info);
 
   // These functions are called to notify the recipient that a device that is
   // notified via OnAddInputPort() or OnAddOutputPort() gets disconnected, or
   // connected again.
-  void OnSetInputPortState(uint32_t port, media::midi::MidiPortState state);
-  void OnSetOutputPortState(uint32_t port, media::midi::MidiPortState state);
+  void OnSetInputPortState(uint32_t port, midi::MidiPortState state);
+  void OnSetOutputPortState(uint32_t port, midi::MidiPortState state);
 
   // Called when the browser process has sent MIDI data containing one or
   // more messages.
@@ -113,13 +113,13 @@
   void OnAcknowledgeSentData(size_t bytes_sent);
 
   // Following methods, Handle*, run on |main_task_runner_|.
-  void HandleClientAdded(media::midi::Result result);
+  void HandleClientAdded(midi::Result result);
 
-  void HandleAddInputPort(media::midi::MidiPortInfo info);
-  void HandleAddOutputPort(media::midi::MidiPortInfo info);
-  void HandleSetInputPortState(uint32_t port, media::midi::MidiPortState state);
+  void HandleAddInputPort(midi::MidiPortInfo info);
+  void HandleAddOutputPort(midi::MidiPortInfo info);
+  void HandleSetInputPortState(uint32_t port, midi::MidiPortState state);
   void HandleSetOutputPortState(uint32_t port,
-                                media::midi::MidiPortState state);
+                                midi::MidiPortState state);
 
   void HandleDataReceived(uint32_t port,
                           const std::vector<uint8_t>& data,
@@ -153,11 +153,11 @@
   ClientsQueue clients_waiting_session_queue_;
 
   // Represents a result on starting a session. Can be accessed only on
-  media::midi::Result session_result_;
+  midi::Result session_result_;
 
   // Holds MidiPortInfoList for input ports and output ports.
-  media::midi::MidiPortInfoList inputs_;
-  media::midi::MidiPortInfoList outputs_;
+  midi::MidiPortInfoList inputs_;
+  midi::MidiPortInfoList outputs_;
 
   size_t unacknowledged_bytes_sent_;
 
diff --git a/content/renderer/media/midi_message_filter_unittest.cc b/content/renderer/media/midi_message_filter_unittest.cc
index 4323b2e5..4e19855 100644
--- a/content/renderer/media/midi_message_filter_unittest.cc
+++ b/content/renderer/media/midi_message_filter_unittest.cc
@@ -17,18 +17,18 @@
   // Check if static_cast of ToMIDIPortState() just works fine for all states.
   EXPECT_EQ(
       BlinkState::MIDIPortStateDisconnected,
-      MidiMessageFilter::ToBlinkState(media::midi::MIDI_PORT_DISCONNECTED));
+      MidiMessageFilter::ToBlinkState(midi::MIDI_PORT_DISCONNECTED));
   EXPECT_EQ(BlinkState::MIDIPortStateConnected,
-            MidiMessageFilter::ToBlinkState(media::midi::MIDI_PORT_CONNECTED));
+            MidiMessageFilter::ToBlinkState(midi::MIDI_PORT_CONNECTED));
   // Web MIDI API manages DeviceState and ConnectionState separately.
   // "open", "pending", or "closed" are managed separately for ConnectionState
   // by Blink per MIDIAccess instance. So, MIDI_PORT_OPENED in content can be
   // converted to MIDIPortStateConnected.
   EXPECT_EQ(BlinkState::MIDIPortStateConnected,
-            MidiMessageFilter::ToBlinkState(media::midi::MIDI_PORT_OPENED));
+            MidiMessageFilter::ToBlinkState(midi::MIDI_PORT_OPENED));
 
   // Check if we do not have any unknown MidiPortState that is added later.
-  EXPECT_EQ(media::midi::MIDI_PORT_OPENED, media::midi::MIDI_PORT_STATE_LAST);
+  EXPECT_EQ(midi::MIDI_PORT_OPENED, midi::MIDI_PORT_STATE_LAST);
 }
 
 }  // namespace content
diff --git a/device/generic_sensor/platform_sensor.cc b/device/generic_sensor/platform_sensor.cc
index a9b2604b..ced76bb 100644
--- a/device/generic_sensor/platform_sensor.cc
+++ b/device/generic_sensor/platform_sensor.cc
@@ -98,12 +98,9 @@
 }
 
 void PlatformSensor::NotifySensorReadingChanged() {
-  using ClientsList = decltype(clients_);
-  ClientsList::Iterator it(&clients_);
-  Client* client;
-  while ((client = it.GetNext()) != nullptr) {
-    if (!client->IsNotificationSuspended())
-      client->OnSensorReadingChanged();
+  for (auto& client : clients_) {
+    if (!client.IsNotificationSuspended())
+      client.OnSensorReadingChanged();
   }
 }
 
diff --git a/extensions/browser/extension_navigation_throttle.cc b/extensions/browser/extension_navigation_throttle.cc
index bdf1a27..4e511a5f 100644
--- a/extensions/browser/extension_navigation_throttle.cc
+++ b/extensions/browser/extension_navigation_throttle.cc
@@ -14,6 +14,8 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/permissions_data.h"
 
 namespace extensions {
 
@@ -26,14 +28,44 @@
 content::NavigationThrottle::ThrottleCheckResult
 ExtensionNavigationThrottle::WillStartRequest() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  GURL url(navigation_handle()->GetURL());
+  ExtensionRegistry* registry = ExtensionRegistry::Get(
+      navigation_handle()->GetWebContents()->GetBrowserContext());
 
-  // This method for now enforces only web_accessible_resources for navigations.
-  // Top-level navigations should always be allowed.
-  DCHECK(!navigation_handle()->IsInMainFrame());
+  if (navigation_handle()->IsInMainFrame()) {
+    // Block top-level navigations to blob: or filesystem: URLs with extension
+    // origin from non-extension processes.  See https://crbug.com/645028.
+    bool is_nested_url = url.SchemeIsFileSystem() || url.SchemeIsBlob();
+    bool is_extension = false;
+    if (registry) {
+      is_extension = !!registry->enabled_extensions().GetExtensionOrAppByURL(
+          navigation_handle()->GetStartingSiteInstance()->GetSiteURL());
+    }
+
+    url::Origin origin(url);
+    if (is_nested_url && origin.scheme() == extensions::kExtensionScheme &&
+        !is_extension) {
+      // Relax this restriction for apps that use <webview>.  See
+      // https://crbug.com/652077.
+      const extensions::Extension* extension =
+          registry->enabled_extensions().GetByID(origin.host());
+      bool has_webview_permission =
+          extension &&
+          extension->permissions_data()->HasAPIPermission(
+              extensions::APIPermission::kWebView);
+      if (!has_webview_permission)
+        return content::NavigationThrottle::CANCEL;
+    }
+
+    return content::NavigationThrottle::PROCEED;
+  }
+
+  // Now enforce web_accessible_resources for navigations. Top-level navigations
+  // should always be allowed.
 
   // If the navigation is not to a chrome-extension:// URL, no need to perform
   // any more checks.
-  if (!navigation_handle()->GetURL().SchemeIs(extensions::kExtensionScheme))
+  if (!url.SchemeIs(extensions::kExtensionScheme))
     return content::NavigationThrottle::PROCEED;
 
   // The subframe which is navigated needs to have all of its ancestors be
@@ -58,8 +90,7 @@
   content::RenderFrameHost* ancestor = navigating_frame->GetParent();
   bool external_ancestor = false;
   while (ancestor) {
-    if (ancestor->GetLastCommittedURL().GetOrigin() !=
-        navigation_handle()->GetURL().GetOrigin()) {
+    if (ancestor->GetLastCommittedURL().GetOrigin() != url.GetOrigin()) {
       // Ignore DevTools, as it is allowed to embed extension pages.
       if (!ancestor->GetLastCommittedURL().SchemeIs(
               content::kChromeDevToolsScheme)) {
@@ -75,15 +106,12 @@
 
   // Since there was at least one origin different than the navigation URL,
   // explicitly check for the resource in web_accessible_resources.
-  std::string resource_path = navigation_handle()->GetURL().path();
-  ExtensionRegistry* registry = ExtensionRegistry::Get(
-      navigation_handle()->GetWebContents()->GetBrowserContext());
+  std::string resource_path = url.path();
   if (!registry)
     return content::NavigationThrottle::BLOCK_REQUEST;
 
   const extensions::Extension* extension =
-      registry->enabled_extensions().GetByID(
-          navigation_handle()->GetURL().host());
+      registry->enabled_extensions().GetByID(url.host());
   if (!extension)
     return content::NavigationThrottle::BLOCK_REQUEST;
 
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 8e5970b..7bb59619 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -255,7 +255,6 @@
   testonly = true
 
   deps = [
-    ":client_api_generator_tests",
     ":headless_browsertests",
     ":headless_unittests",
   ]
@@ -281,23 +280,6 @@
   ]
 }
 
-action("client_api_generator_tests") {
-  _stamp = "$target_gen_dir/client_api_generator_unittests.stamp"
-  inputs = [
-    "lib/browser/client_api_generator.py",
-    "lib/browser/client_api_generator_unittest.py",
-  ]
-  outputs = [
-    _stamp,
-  ]
-
-  script = "lib/browser/client_api_generator_unittest.py"
-  args = [
-    "--stamp",
-    rebase_path(_stamp, root_build_dir),
-  ]
-}
-
 mojom("embedder_mojo_for_testing") {
   sources = [
     "lib/embedder_test.mojom",
diff --git a/headless/lib/browser/client_api_generator_unittest.py b/headless/lib/browser/client_api_generator_unittest.py
old mode 100644
new mode 100755
index d9d3f81d..93eb9e6
--- a/headless/lib/browser/client_api_generator_unittest.py
+++ b/headless/lib/browser/client_api_generator_unittest.py
@@ -1,8 +1,9 @@
+#!/usr/bin/env python
+
 # Copyright 2016 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import argparse
 import client_api_generator
 import shutil
 import sys
@@ -453,6 +454,7 @@
     try:
       dirname = tempfile.mkdtemp()
       jinja_env = client_api_generator.InitializeJinjaEnv(dirname)
+      client_api_generator.CreateTypeDefinitions(json_api)
       client_api_generator.Generate(jinja_env, dirname, json_api, 'types',
                                     ['cc'])
       client_api_generator.Generate(jinja_env, dirname, json_api, 'types',
@@ -497,10 +499,4 @@
 
 
 if __name__ == '__main__':
-  cmdline_parser = argparse.ArgumentParser()
-  cmdline_parser.add_argument('--stamp')
-  args = cmdline_parser.parse_args()
-  unittest.main(verbosity=2, exit=False, argv=sys.argv[:1])
-  if args.stamp:
-    with open(args.stamp, 'a') as f:
-      pass
+  unittest.main(verbosity=2, exit=False, argv=sys.argv)
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 3ff4667..9dea8fb 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -251,9 +251,12 @@
   // TODO(xhwang): When we use an external Renderer, many methods won't work,
   // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
 
-  // Use the null sink if no sink was provided.
+  // Use the null sink if no valid sink was provided.
   audio_source_provider_ = new WebAudioSourceProviderImpl(
-      params.audio_renderer_sink().get()
+      params.audio_renderer_sink().get() &&
+              params.audio_renderer_sink()
+                      ->GetOutputDeviceInfo()
+                      .device_status() == OUTPUT_DEVICE_STATUS_OK
           ? params.audio_renderer_sink()
           : new NullAudioSink(media_task_runner_));
 }
diff --git a/media/midi/BUILD.gn b/media/midi/BUILD.gn
index a58f993c..b747936 100644
--- a/media/midi/BUILD.gn
+++ b/media/midi/BUILD.gn
@@ -50,25 +50,25 @@
     ]
 
     java_files = [
-      "java/src/org/chromium/media/midi/MidiDeviceAndroid.java",
-      "java/src/org/chromium/media/midi/MidiInputPortAndroid.java",
-      "java/src/org/chromium/media/midi/MidiManagerAndroid.java",
-      "java/src/org/chromium/media/midi/MidiOutputPortAndroid.java",
-      "java/src/org/chromium/media/midi/UsbMidiDeviceAndroid.java",
-      "java/src/org/chromium/media/midi/UsbMidiDeviceFactoryAndroid.java",
+      "java/src/org/chromium/midi/MidiDeviceAndroid.java",
+      "java/src/org/chromium/midi/MidiInputPortAndroid.java",
+      "java/src/org/chromium/midi/MidiManagerAndroid.java",
+      "java/src/org/chromium/midi/MidiOutputPortAndroid.java",
+      "java/src/org/chromium/midi/UsbMidiDeviceAndroid.java",
+      "java/src/org/chromium/midi/UsbMidiDeviceFactoryAndroid.java",
     ]
   }
 
   generate_jni("midi_jni_headers") {
     sources = [
-      "java/src/org/chromium/media/midi/MidiDeviceAndroid.java",
-      "java/src/org/chromium/media/midi/MidiInputPortAndroid.java",
-      "java/src/org/chromium/media/midi/MidiManagerAndroid.java",
-      "java/src/org/chromium/media/midi/MidiOutputPortAndroid.java",
-      "java/src/org/chromium/media/midi/UsbMidiDeviceAndroid.java",
-      "java/src/org/chromium/media/midi/UsbMidiDeviceFactoryAndroid.java",
+      "java/src/org/chromium/midi/MidiDeviceAndroid.java",
+      "java/src/org/chromium/midi/MidiInputPortAndroid.java",
+      "java/src/org/chromium/midi/MidiManagerAndroid.java",
+      "java/src/org/chromium/midi/MidiOutputPortAndroid.java",
+      "java/src/org/chromium/midi/UsbMidiDeviceAndroid.java",
+      "java/src/org/chromium/midi/UsbMidiDeviceFactoryAndroid.java",
     ]
-    jni_package = "media/midi"
+    jni_package = "midi"
   }
 }
 
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiDeviceAndroid.java b/media/midi/java/src/org/chromium/midi/MidiDeviceAndroid.java
similarity index 95%
rename from media/midi/java/src/org/chromium/media/midi/MidiDeviceAndroid.java
rename to media/midi/java/src/org/chromium/midi/MidiDeviceAndroid.java
index 92657e5..62601ce 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiDeviceAndroid.java
+++ b/media/midi/java/src/org/chromium/midi/MidiDeviceAndroid.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.media.midi;
+package org.chromium.midi;
 
 import android.annotation.TargetApi;
 import android.media.midi.MidiDevice;
@@ -12,9 +12,9 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 
-@JNINamespace("media::midi")
+@JNINamespace("midi")
 /**
- * A class implementing media::midi::MidiDeviceAndroid functionality.
+ * A class implementing midi::MidiDeviceAndroid functionality.
  */
 @TargetApi(Build.VERSION_CODES.M)
 class MidiDeviceAndroid {
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiInputPortAndroid.java b/media/midi/java/src/org/chromium/midi/MidiInputPortAndroid.java
similarity index 89%
rename from media/midi/java/src/org/chromium/media/midi/MidiInputPortAndroid.java
rename to media/midi/java/src/org/chromium/midi/MidiInputPortAndroid.java
index 60d9abb..2ca80b63 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiInputPortAndroid.java
+++ b/media/midi/java/src/org/chromium/midi/MidiInputPortAndroid.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.media.midi;
+package org.chromium.midi;
 
 import android.annotation.TargetApi;
 import android.media.midi.MidiDevice;
@@ -18,9 +18,9 @@
 // Note "InputPort" is named in the Web MIDI manner. It corresponds to MidiOutputPort class in the
 // Android API.
 /**
- * A MidiInputPortAndroid provides data to the associated media::midi::MidiInputPortAndroid object.
+ * A MidiInputPortAndroid provides data to the associated midi::MidiInputPortAndroid object.
  */
-@JNINamespace("media::midi")
+@JNINamespace("midi")
 @TargetApi(Build.VERSION_CODES.M)
 class MidiInputPortAndroid {
     /**
@@ -28,7 +28,7 @@
      */
     private MidiOutputPort mPort;
     /**
-     * A pointer to a media::midi::MidiInputPortAndroid object.
+     * A pointer to a midi::MidiInputPortAndroid object.
      */
     private long mNativeReceiverPointer;
     /**
@@ -53,7 +53,7 @@
     /**
      * Registers this object to the underlying port so as to the C++ function will be called with
      * the given C++ object when data arrives.
-     * @param nativeReceiverPointer a pointer to a media::midi::MidiInputPortAndroid object.
+     * @param nativeReceiverPointer a pointer to a midi::MidiInputPortAndroid object.
      * @return true if this operation succeeds or the port is already open.
      */
     @CalledByNative
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java b/media/midi/java/src/org/chromium/midi/MidiManagerAndroid.java
similarity index 93%
rename from media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java
rename to media/midi/java/src/org/chromium/midi/MidiManagerAndroid.java
index 32f0e86..410fbbd 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiManagerAndroid.java
+++ b/media/midi/java/src/org/chromium/midi/MidiManagerAndroid.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.media.midi;
+package org.chromium.midi;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -22,9 +22,9 @@
 import java.util.Set;
 
 /**
- * A Java class implementing media::midi::MidiManagerAndroid functionality.
+ * A Java class implementing midi::MidiManagerAndroid functionality.
  */
-@JNINamespace("media::midi")
+@JNINamespace("midi")
 @TargetApi(Build.VERSION_CODES.M)
 class MidiManagerAndroid {
     /**
@@ -48,14 +48,14 @@
      */
     private final Handler mHandler;
     /**
-     * The associated media::midi::MidiDeviceAndroid instance.
+     * The associated midi::MidiDeviceAndroid instance.
      */
     private final long mNativeManagerPointer;
 
     /**
      * A creation function called by C++.
      * @param context
-     * @param nativeManagerPointer The native pointer to a media::midi::MidiManagerAndroid object.
+     * @param nativeManagerPointer The native pointer to a midi::MidiManagerAndroid object.
      */
     @CalledByNative
     static MidiManagerAndroid create(Context context, long nativeManagerPointer) {
@@ -64,7 +64,7 @@
 
     /**
      * @param context
-     * @param nativeManagerPointer The native pointer to a media::midi::MidiManagerAndroid object.
+     * @param nativeManagerPointer The native pointer to a midi::MidiManagerAndroid object.
      */
     private MidiManagerAndroid(Context context, long nativeManagerPointer) {
         assert ThreadUtils.runningOnUiThread();
diff --git a/media/midi/java/src/org/chromium/media/midi/MidiOutputPortAndroid.java b/media/midi/java/src/org/chromium/midi/MidiOutputPortAndroid.java
similarity index 92%
rename from media/midi/java/src/org/chromium/media/midi/MidiOutputPortAndroid.java
rename to media/midi/java/src/org/chromium/midi/MidiOutputPortAndroid.java
index 00ff9a0..7baa7ea 100644
--- a/media/midi/java/src/org/chromium/media/midi/MidiOutputPortAndroid.java
+++ b/media/midi/java/src/org/chromium/midi/MidiOutputPortAndroid.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.media.midi;
+package org.chromium.midi;
 
 import android.annotation.TargetApi;
 import android.media.midi.MidiDevice;
@@ -16,11 +16,11 @@
 import java.io.IOException;
 
 /**
- * A class implementing media::midi::MidiOutputPortAndroid functionality.
+ * A class implementing midi::MidiOutputPortAndroid functionality.
  */
 // Note "OutputPort" is named in the Web MIDI manner. It corresponds to MidiInputPort class in the
 // Android API.
-@JNINamespace("media::midi")
+@JNINamespace("midi")
 @TargetApi(Build.VERSION_CODES.M)
 class MidiOutputPortAndroid {
     /**
@@ -36,7 +36,7 @@
      */
     private final int mIndex;
 
-    private static final String TAG = "media_midi";
+    private static final String TAG = "midi";
 
     /**
      * constructor
diff --git a/media/midi/java/src/org/chromium/media/midi/UsbMidiDeviceAndroid.java b/media/midi/java/src/org/chromium/midi/UsbMidiDeviceAndroid.java
similarity index 99%
rename from media/midi/java/src/org/chromium/media/midi/UsbMidiDeviceAndroid.java
rename to media/midi/java/src/org/chromium/midi/UsbMidiDeviceAndroid.java
index 8b41220..71d8f0a 100644
--- a/media/midi/java/src/org/chromium/media/midi/UsbMidiDeviceAndroid.java
+++ b/media/midi/java/src/org/chromium/midi/UsbMidiDeviceAndroid.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.media.midi;
+package org.chromium.midi;
 
 import android.annotation.TargetApi;
 import android.hardware.usb.UsbConstants;
@@ -28,7 +28,7 @@
  * Owned by its native counterpart declared in usb_midi_device_android.h.
  * Refer to that class for general comments.
  */
-@JNINamespace("media::midi")
+@JNINamespace("midi")
 class UsbMidiDeviceAndroid {
     /**
      * A connection handle for this device.
diff --git a/media/midi/java/src/org/chromium/media/midi/UsbMidiDeviceFactoryAndroid.java b/media/midi/java/src/org/chromium/midi/UsbMidiDeviceFactoryAndroid.java
similarity index 98%
rename from media/midi/java/src/org/chromium/media/midi/UsbMidiDeviceFactoryAndroid.java
rename to media/midi/java/src/org/chromium/midi/UsbMidiDeviceFactoryAndroid.java
index 0dc0c2c9..02e9013 100644
--- a/media/midi/java/src/org/chromium/media/midi/UsbMidiDeviceFactoryAndroid.java
+++ b/media/midi/java/src/org/chromium/midi/UsbMidiDeviceFactoryAndroid.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.media.midi;
+package org.chromium.midi;
 
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -28,7 +28,7 @@
  * Owned by its native counterpart declared in
  * usb_midi_device_factory_android.h. Refer to that class for general comments.
  */
-@JNINamespace("media::midi")
+@JNINamespace("midi")
 class UsbMidiDeviceFactoryAndroid {
     /**
      * The UsbManager of this system.
@@ -60,7 +60,7 @@
      */
     private long mNativePointer;
 
-    private static final String ACTION_USB_PERMISSION = "org.chromium.media.USB_PERMISSION";
+    private static final String ACTION_USB_PERMISSION = "org.chromium.midi.USB_PERMISSION";
 
     /**
      * Constructs a UsbMidiDeviceAndroid.
diff --git a/media/midi/midi_device_android.cc b/media/midi/midi_device_android.cc
index a9c7584..00fc99ad 100644
--- a/media/midi/midi_device_android.cc
+++ b/media/midi/midi_device_android.cc
@@ -12,7 +12,6 @@
 
 using base::android::ScopedJavaLocalRef;
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -68,4 +67,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_device_android.h b/media/midi/midi_device_android.h
index f3ebfdd..34575cfbea 100644
--- a/media/midi/midi_device_android.h
+++ b/media/midi/midi_device_android.h
@@ -12,7 +12,6 @@
 #include "base/memory/scoped_vector.h"
 #include "media/midi/midi_input_port_android.h"
 
-namespace media {
 namespace midi {
 
 class MidiOutputPortAndroid;
@@ -45,6 +44,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_DEVICE_ANDROID_H_
diff --git a/media/midi/midi_input_port_android.cc b/media/midi/midi_input_port_android.cc
index 59b355a..3d4ee4c 100644
--- a/media/midi/midi_input_port_android.cc
+++ b/media/midi/midi_input_port_android.cc
@@ -10,7 +10,6 @@
 
 using base::android::JavaParamRef;
 
-namespace media {
 namespace midi {
 
 MidiInputPortAndroid::MidiInputPortAndroid(JNIEnv* env,
@@ -58,4 +57,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_input_port_android.h b/media/midi/midi_input_port_android.h
index 684fcc6..6153d3a 100644
--- a/media/midi/midi_input_port_android.h
+++ b/media/midi/midi_input_port_android.h
@@ -12,7 +12,6 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/time/time.h"
 
-namespace media {
 namespace midi {
 
 class MidiInputPortAndroid final {
@@ -48,6 +47,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_INPUT_PORT_ANDROID_H_
diff --git a/media/midi/midi_jni_registrar.cc b/media/midi/midi_jni_registrar.cc
index 4f407dd5..d956e52 100644
--- a/media/midi/midi_jni_registrar.cc
+++ b/media/midi/midi_jni_registrar.cc
@@ -12,7 +12,6 @@
 #include "media/midi/usb_midi_device_android.h"
 #include "media/midi/usb_midi_device_factory_android.h"
 
-namespace media {
 namespace midi {
 
 static base::android::RegistrationMethod kMediaRegisteredMethods[] = {
@@ -29,4 +28,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_jni_registrar.h b/media/midi/midi_jni_registrar.h
index 6acad7d..633af5e7 100644
--- a/media/midi/midi_jni_registrar.h
+++ b/media/midi/midi_jni_registrar.h
@@ -9,13 +9,11 @@
 
 #include "media/midi/midi_export.h"
 
-namespace media {
 namespace midi {
 
 // Register all JNI bindings necessary for media/midi.
 MIDI_EXPORT bool RegisterJni(JNIEnv* env);
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_JNI_REGISTRAR_H_
diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc
index fcbaa55..ad9dfce 100644
--- a/media/midi/midi_manager.cc
+++ b/media/midi/midi_manager.cc
@@ -12,7 +12,6 @@
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -274,4 +273,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager.h b/media/midi/midi_manager.h
index dd8466f..c382528 100644
--- a/media/midi/midi_manager.h
+++ b/media/midi/midi_manager.h
@@ -23,7 +23,6 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
-namespace media {
 namespace midi {
 
 // A MidiManagerClient registers with the MidiManager to receive MIDI data.
@@ -210,6 +209,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MANAGER_H_
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc
index a5caf8c..c57a2ef2 100644
--- a/media/midi/midi_manager_alsa.cc
+++ b/media/midi/midi_manager_alsa.cc
@@ -28,7 +28,6 @@
 #include "crypto/sha2.h"
 #include "media/midi/midi_port_info.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -1404,4 +1403,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_alsa.h b/media/midi/midi_manager_alsa.h
index 66f427a..0ff58a7 100644
--- a/media/midi/midi_manager_alsa.h
+++ b/media/midi/midi_manager_alsa.h
@@ -27,7 +27,6 @@
 class ThreadChecker;
 }
 
-namespace media {
 namespace midi {
 
 class MIDI_EXPORT MidiManagerAlsa final : public MidiManager {
@@ -457,6 +456,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MANAGER_ALSA_H_
diff --git a/media/midi/midi_manager_alsa_unittest.cc b/media/midi/midi_manager_alsa_unittest.cc
index c026dc6..88baa75 100644
--- a/media/midi/midi_manager_alsa_unittest.cc
+++ b/media/midi/midi_manager_alsa_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 
 class MidiManagerAlsaTest : public ::testing::Test {
@@ -706,4 +705,3 @@
 // TODO(agoode): Test old -> new state event generation, using mocks.
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_android.cc b/media/midi/midi_manager_android.cc
index 3f422c3..9bc3032 100644
--- a/media/midi/midi_manager_android.cc
+++ b/media/midi/midi_manager_android.cc
@@ -18,7 +18,6 @@
 
 using base::android::JavaParamRef;
 
-namespace media {
 namespace midi {
 
 MidiManager* MidiManager::Create() {
@@ -187,4 +186,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_android.h b/media/midi/midi_manager_android.h
index 4ef1f6d..77ddf28c 100644
--- a/media/midi/midi_manager_android.h
+++ b/media/midi/midi_manager_android.h
@@ -21,7 +21,6 @@
 #include "media/midi/midi_manager.h"
 #include "media/midi/midi_scheduler.h"
 
-namespace media {
 namespace midi {
 
 class MidiDeviceAndroid;
@@ -94,6 +93,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MANAGER_ANDROID_H_
diff --git a/media/midi/midi_manager_mac.cc b/media/midi/midi_manager_mac.cc
index 1ad9f67a..2f94be3 100644
--- a/media/midi/midi_manager_mac.cc
+++ b/media/midi/midi_manager_mac.cc
@@ -23,7 +23,6 @@
 // 64-bit. Therefore, the initialization is the simplest one that satisfies both
 // (if possible).
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -387,4 +386,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_mac.h b/media/midi/midi_manager_mac.h
index 9b36f8c..85479e3 100644
--- a/media/midi/midi_manager_mac.h
+++ b/media/midi/midi_manager_mac.h
@@ -19,7 +19,6 @@
 #include "media/midi/midi_manager.h"
 #include "media/midi/midi_port_info.h"
 
-namespace media {
 namespace midi {
 
 class MIDI_EXPORT MidiManagerMac final : public MidiManager {
@@ -90,6 +89,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MANAGER_MAC_H_
diff --git a/media/midi/midi_manager_mac_unittest.cc b/media/midi/midi_manager_mac_unittest.cc
index c8d80e5..4ee525e 100644
--- a/media/midi/midi_manager_mac_unittest.cc
+++ b/media/midi/midi_manager_mac_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/synchronization/lock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -171,4 +170,3 @@
 }  // namespace
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_unittest.cc b/media/midi/midi_manager_unittest.cc
index 9ab33ce7..eed774d 100644
--- a/media/midi/midi_manager_unittest.cc
+++ b/media/midi/midi_manager_unittest.cc
@@ -20,7 +20,6 @@
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -297,4 +296,3 @@
 }  // namespace
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_usb.cc b/media/midi/midi_manager_usb.cc
index ddd54c2..b2d90c59 100644
--- a/media/midi/midi_manager_usb.cc
+++ b/media/midi/midi_manager_usb.cc
@@ -12,7 +12,6 @@
 #include "media/midi/midi_scheduler.h"
 #include "media/midi/usb_midi_descriptor_parser.h"
 
-namespace media {
 namespace midi {
 
 MidiManagerUsb::MidiManagerUsb(std::unique_ptr<UsbMidiDevice::Factory> factory)
@@ -167,4 +166,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_usb.h b/media/midi/midi_manager_usb.h
index d3e358d..bb99994 100644
--- a/media/midi/midi_manager_usb.h
+++ b/media/midi/midi_manager_usb.h
@@ -26,7 +26,6 @@
 #include "media/midi/usb_midi_jack.h"
 #include "media/midi/usb_midi_output_stream.h"
 
-namespace media {
 namespace midi {
 
 class MidiScheduler;
@@ -101,6 +100,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MANAGER_USB_H_
diff --git a/media/midi/midi_manager_usb_unittest.cc b/media/midi/midi_manager_usb_unittest.cc
index e4f44df..db49b3b 100644
--- a/media/midi/midi_manager_usb_unittest.cc
+++ b/media/midi/midi_manager_usb_unittest.cc
@@ -18,7 +18,6 @@
 #include "media/midi/usb_midi_device.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -574,4 +573,3 @@
 }  // namespace
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_win.cc b/media/midi/midi_manager_win.cc
index 752de0e..80c6366e 100644
--- a/media/midi/midi_manager_win.cc
+++ b/media/midi/midi_manager_win.cc
@@ -49,7 +49,6 @@
 #include "media/midi/midi_port_info.h"
 #include "media/midi/midi_switches.h"
 
-namespace media {
 namespace midi {
 namespace {
 
@@ -1201,4 +1200,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_win.h b/media/midi/midi_manager_win.h
index 83afbf10..8bebae29 100644
--- a/media/midi/midi_manager_win.h
+++ b/media/midi/midi_manager_win.h
@@ -15,7 +15,6 @@
 #include "base/time/time.h"
 #include "media/midi/midi_manager.h"
 
-namespace media {
 namespace midi {
 
 class MidiServiceWinDelegate {
@@ -73,6 +72,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MANAGER_WIN_H_
diff --git a/media/midi/midi_manager_winrt.cc b/media/midi/midi_manager_winrt.cc
index 9a510c7b..e8f4c02 100644
--- a/media/midi/midi_manager_winrt.cc
+++ b/media/midi/midi_manager_winrt.cc
@@ -31,7 +31,6 @@
 #include "base/win/scoped_comptr.h"
 #include "media/midi/midi_scheduler.h"
 
-namespace media {
 namespace midi {
 namespace {
 
@@ -1046,4 +1045,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_manager_winrt.h b/media/midi/midi_manager_winrt.h
index 3cc0a255..d199a6c 100644
--- a/media/midi/midi_manager_winrt.h
+++ b/media/midi/midi_manager_winrt.h
@@ -15,7 +15,6 @@
 class ThreadChecker;
 }
 
-namespace media {
 namespace midi {
 
 class MidiScheduler;
@@ -82,6 +81,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MANAGER_WINRT_H_
diff --git a/media/midi/midi_message_queue.cc b/media/midi/midi_message_queue.cc
index bfc05f1..9107a4b 100644
--- a/media/midi/midi_message_queue.cc
+++ b/media/midi/midi_message_queue.cc
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "media/midi/midi_message_util.h"
 
-namespace media {
 namespace midi {
 namespace {
 
@@ -124,4 +123,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_message_queue.h b/media/midi/midi_message_queue.h
index 999d877..1df24902 100644
--- a/media/midi/midi_message_queue.h
+++ b/media/midi/midi_message_queue.h
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "media/midi/midi_export.h"
 
-namespace media {
 namespace midi {
 
 // A simple message splitter for possibly unsafe/corrupted MIDI data stream.
@@ -72,6 +71,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MESSAGE_QUEUE_H_
diff --git a/media/midi/midi_message_queue_unittest.cc b/media/midi/midi_message_queue_unittest.cc
index 97c6e1c..11077e7 100644
--- a/media/midi/midi_message_queue_unittest.cc
+++ b/media/midi/midi_message_queue_unittest.cc
@@ -9,7 +9,6 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 namespace {
 
@@ -571,4 +570,3 @@
 
 }  // namespace
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_message_util.cc b/media/midi/midi_message_util.cc
index 82d16f7b..846b693 100644
--- a/media/midi/midi_message_util.cc
+++ b/media/midi/midi_message_util.cc
@@ -5,7 +5,6 @@
 #include "base/logging.h"
 #include "media/midi/midi_message_util.h"
 
-namespace media {
 namespace midi {
 
 size_t GetMidiMessageLength(uint8_t status_byte) {
@@ -50,4 +49,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_message_util.h b/media/midi/midi_message_util.h
index a2fc3174..768a2b7 100644
--- a/media/midi/midi_message_util.h
+++ b/media/midi/midi_message_util.h
@@ -13,7 +13,6 @@
 
 #include "media/midi/midi_export.h"
 
-namespace media {
 namespace midi {
 
 // Returns the length of a MIDI message in bytes. Never returns 4 or greater.
@@ -33,6 +32,5 @@
 const uint8_t kSysRTMessageBitPattern = 0xf8;
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_MESSAGE_UTIL_H_
diff --git a/media/midi/midi_message_util_unittest.cc b/media/midi/midi_message_util_unittest.cc
index 260a5a7..88719ff 100644
--- a/media/midi/midi_message_util_unittest.cc
+++ b/media/midi/midi_message_util_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 namespace {
 
@@ -45,4 +44,3 @@
 
 }  // namespace
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_output_port_android.cc b/media/midi/midi_output_port_android.cc
index bcb1e41..58696cb 100644
--- a/media/midi/midi_output_port_android.cc
+++ b/media/midi/midi_output_port_android.cc
@@ -9,7 +9,6 @@
 
 using base::android::ScopedJavaLocalRef;
 
-namespace media {
 namespace midi {
 
 MidiOutputPortAndroid::MidiOutputPortAndroid(JNIEnv* env, jobject raw)
@@ -41,4 +40,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_output_port_android.h b/media/midi/midi_output_port_android.h
index 353aa116..0574c276 100644
--- a/media/midi/midi_output_port_android.h
+++ b/media/midi/midi_output_port_android.h
@@ -12,7 +12,6 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/time/time.h"
 
-namespace media {
 namespace midi {
 
 class MidiOutputPortAndroid final {
@@ -30,6 +29,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_OUTPUT_PORT_ANDROID_H_
diff --git a/media/midi/midi_port_info.cc b/media/midi/midi_port_info.cc
index 112829a..29bae144 100644
--- a/media/midi/midi_port_info.cc
+++ b/media/midi/midi_port_info.cc
@@ -4,7 +4,6 @@
 
 #include "media/midi/midi_port_info.h"
 
-namespace media {
 namespace midi {
 
 MidiPortInfo::MidiPortInfo() {}
@@ -30,4 +29,3 @@
       state(info.state) {}
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_port_info.h b/media/midi/midi_port_info.h
index 99e1e67..3bd842c 100644
--- a/media/midi/midi_port_info.h
+++ b/media/midi/midi_port_info.h
@@ -10,7 +10,6 @@
 
 #include "media/midi/midi_export.h"
 
-namespace media {
 namespace midi {
 
 enum MidiPortState {
@@ -41,6 +40,5 @@
 using MidiPortInfoList = std::vector<MidiPortInfo>;
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_PORT_INFO_H_
diff --git a/media/midi/midi_scheduler.cc b/media/midi/midi_scheduler.cc
index 810b257d..ee8768f 100644
--- a/media/midi/midi_scheduler.cc
+++ b/media/midi/midi_scheduler.cc
@@ -12,7 +12,6 @@
 #include "base/time/time.h"
 #include "media/midi/midi_manager.h"
 
-namespace media {
 namespace midi {
 
 MidiScheduler::MidiScheduler(MidiManager* manager)
@@ -59,4 +58,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/midi_scheduler.h b/media/midi/midi_scheduler.h
index 2d79fc8..ebc4b58 100644
--- a/media/midi/midi_scheduler.h
+++ b/media/midi/midi_scheduler.h
@@ -14,7 +14,6 @@
 #include "base/threading/thread_checker.h"
 #include "media/midi/midi_export.h"
 
-namespace media {
 namespace midi {
 
 class MidiManager;
@@ -60,6 +59,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_MIDI_SCHEDULER_H_
diff --git a/media/midi/result.h b/media/midi/result.h
index 8214cd2..961adbc7 100644
--- a/media/midi/result.h
+++ b/media/midi/result.h
@@ -5,7 +5,6 @@
 #ifndef MEDIA_MIDI_RESULT_H_
 #define MEDIA_MIDI_RESULT_H_
 
-namespace media {
 namespace midi {
 
 // Result codes for MIDI.
@@ -25,6 +24,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_RESULT_H_
diff --git a/media/midi/usb_midi_descriptor_parser.cc b/media/midi/usb_midi_descriptor_parser.cc
index a3bc128..f473153 100644
--- a/media/midi/usb_midi_descriptor_parser.cc
+++ b/media/midi/usb_midi_descriptor_parser.cc
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -287,4 +286,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/usb_midi_descriptor_parser.h b/media/midi/usb_midi_descriptor_parser.h
index 97df43e..ebee1858 100644
--- a/media/midi/usb_midi_descriptor_parser.h
+++ b/media/midi/usb_midi_descriptor_parser.h
@@ -16,7 +16,6 @@
 #include "media/midi/usb_midi_export.h"
 #include "media/midi/usb_midi_jack.h"
 
-namespace media {
 namespace midi {
 
 class UsbMidiDevice;
@@ -84,6 +83,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_USB_MIDI_DESCRIPTOR_PARSER_H_
diff --git a/media/midi/usb_midi_descriptor_parser_unittest.cc b/media/midi/usb_midi_descriptor_parser_unittest.cc
index 93b0df4..ac66be1 100644
--- a/media/midi/usb_midi_descriptor_parser_unittest.cc
+++ b/media/midi/usb_midi_descriptor_parser_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -121,4 +120,3 @@
 }  // namespace
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/usb_midi_device.h b/media/midi/usb_midi_device.h
index 5220b80..e7d6c9a 100644
--- a/media/midi/usb_midi_device.h
+++ b/media/midi/usb_midi_device.h
@@ -16,7 +16,6 @@
 #include "base/time/time.h"
 #include "media/midi/usb_midi_export.h"
 
-namespace media {
 namespace midi {
 
 class MidiManagerUsb;
@@ -87,6 +86,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_USB_MIDI_DEVICE_H_
diff --git a/media/midi/usb_midi_device_android.cc b/media/midi/usb_midi_device_android.cc
index 6d6635a..b13ea19f 100644
--- a/media/midi/usb_midi_device_android.cc
+++ b/media/midi/usb_midi_device_android.cc
@@ -16,7 +16,6 @@
 using base::android::JavaParamRef;
 using base::android::ScopedJavaLocalRef;
 
-namespace media {
 namespace midi {
 
 UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(
@@ -146,4 +145,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/usb_midi_device_android.h b/media/midi/usb_midi_device_android.h
index 1c5e6968..93ee328 100644
--- a/media/midi/usb_midi_device_android.h
+++ b/media/midi/usb_midi_device_android.h
@@ -17,7 +17,6 @@
 #include "media/midi/usb_midi_device.h"
 #include "media/midi/usb_midi_export.h"
 
-namespace media {
 namespace midi {
 
 class USB_MIDI_EXPORT UsbMidiDeviceAndroid : public UsbMidiDevice {
@@ -62,6 +61,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_USB_MIDI_DEVICE_ANDROID_H_
diff --git a/media/midi/usb_midi_device_factory_android.cc b/media/midi/usb_midi_device_factory_android.cc
index 73fff0e..132e6fc6 100644
--- a/media/midi/usb_midi_device_factory_android.cc
+++ b/media/midi/usb_midi_device_factory_android.cc
@@ -18,7 +18,6 @@
 
 using base::android::JavaParamRef;
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -96,4 +95,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/usb_midi_device_factory_android.h b/media/midi/usb_midi_device_factory_android.h
index 1f8e435..cd25b00 100644
--- a/media/midi/usb_midi_device_factory_android.h
+++ b/media/midi/usb_midi_device_factory_android.h
@@ -15,7 +15,6 @@
 #include "media/midi/usb_midi_device.h"
 #include "media/midi/usb_midi_export.h"
 
-namespace media {
 namespace midi {
 
 // This class enumerates UsbMidiDevices.
@@ -54,6 +53,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_USB_MIDI_DEVICE_FACTORY_ANDROID_H_
diff --git a/media/midi/usb_midi_input_stream.cc b/media/midi/usb_midi_input_stream.cc
index 2eaa6e36..9eb24078 100644
--- a/media/midi/usb_midi_input_stream.cc
+++ b/media/midi/usb_midi_input_stream.cc
@@ -9,7 +9,6 @@
 #include "base/logging.h"
 #include "media/midi/usb_midi_device.h"
 
-namespace media {
 namespace midi {
 
 UsbMidiInputStream::JackUniqueKey::JackUniqueKey(UsbMidiDevice* device,
@@ -89,4 +88,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/usb_midi_input_stream.h b/media/midi/usb_midi_input_stream.h
index f933ef7..6d7a5f74 100644
--- a/media/midi/usb_midi_input_stream.h
+++ b/media/midi/usb_midi_input_stream.h
@@ -17,7 +17,6 @@
 #include "media/midi/usb_midi_export.h"
 #include "media/midi/usb_midi_jack.h"
 
-namespace media {
 namespace midi {
 
 class UsbMidiDevice;
@@ -86,6 +85,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_USB_MIDI_INPUT_STREAM_H_
diff --git a/media/midi/usb_midi_input_stream_unittest.cc b/media/midi/usb_midi_input_stream_unittest.cc
index f291fde..3ebd99ab 100644
--- a/media/midi/usb_midi_input_stream_unittest.cc
+++ b/media/midi/usb_midi_input_stream_unittest.cc
@@ -19,7 +19,6 @@
 
 using base::TimeTicks;
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -170,4 +169,3 @@
 }  // namespace
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/usb_midi_jack.h b/media/midi/usb_midi_jack.h
index 65cb189..48f3fa0e 100644
--- a/media/midi/usb_midi_jack.h
+++ b/media/midi/usb_midi_jack.h
@@ -9,7 +9,6 @@
 
 #include "media/midi/usb_midi_export.h"
 
-namespace media {
 namespace midi {
 
 class UsbMidiDevice;
@@ -47,6 +46,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_USB_MIDI_JACK_H_
diff --git a/media/midi/usb_midi_output_stream.cc b/media/midi/usb_midi_output_stream.cc
index 9f4fee8..da617d1 100644
--- a/media/midi/usb_midi_output_stream.cc
+++ b/media/midi/usb_midi_output_stream.cc
@@ -9,7 +9,6 @@
 #include "media/midi/midi_message_util.h"
 #include "media/midi/usb_midi_device.h"
 
-namespace media {
 namespace midi {
 
 UsbMidiOutputStream::UsbMidiOutputStream(const UsbMidiJack& jack)
@@ -195,4 +194,3 @@
 }
 
 }  // namespace midi
-}  // namespace media
diff --git a/media/midi/usb_midi_output_stream.h b/media/midi/usb_midi_output_stream.h
index 1d6b4da3..8391079 100644
--- a/media/midi/usb_midi_output_stream.h
+++ b/media/midi/usb_midi_output_stream.h
@@ -14,7 +14,6 @@
 #include "media/midi/usb_midi_export.h"
 #include "media/midi/usb_midi_jack.h"
 
-namespace media {
 namespace midi {
 
 // UsbMidiOutputStream converts MIDI data to USB-MIDI data.
@@ -57,6 +56,5 @@
 };
 
 }  // namespace midi
-}  // namespace media
 
 #endif  // MEDIA_MIDI_USB_MIDI_OUTPUT_STREAM_H_
diff --git a/media/midi/usb_midi_output_stream_unittest.cc b/media/midi/usb_midi_output_stream_unittest.cc
index c0489b9..0f1e2e8 100644
--- a/media/midi/usb_midi_output_stream_unittest.cc
+++ b/media/midi/usb_midi_output_stream_unittest.cc
@@ -16,7 +16,6 @@
 #include "media/midi/usb_midi_device.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace media {
 namespace midi {
 
 namespace {
@@ -327,4 +326,3 @@
 }  // namespace
 
 }  // namespace midi
-}  // namespace media
diff --git a/services/shell/public/cpp/interface_registry.h b/services/shell/public/cpp/interface_registry.h
index b917a868..9a3fa1e 100644
--- a/services/shell/public/cpp/interface_registry.h
+++ b/services/shell/public/cpp/interface_registry.h
@@ -81,7 +81,8 @@
 
   // Construct an InterfaceRegistry with filtering rules as specified in
   // |capability_request| applied.
-  InterfaceRegistry(const Identity& remote_identity,
+  InterfaceRegistry(const Identity& local_identity,
+                    const Identity& remote_identity,
                     const CapabilityRequest& capability_request);
   ~InterfaceRegistry() override;
 
@@ -162,6 +163,7 @@
   mojom::InterfaceProviderRequest pending_request_;
 
   mojo::Binding<mojom::InterfaceProvider> binding_;
+  const Identity local_identity_;
   const Identity remote_identity_;
   const CapabilityRequest capability_request_;
   const bool allow_all_interfaces_;
diff --git a/services/shell/public/cpp/lib/interface_registry.cc b/services/shell/public/cpp/lib/interface_registry.cc
index f992e7d..2169bac 100644
--- a/services/shell/public/cpp/lib/interface_registry.cc
+++ b/services/shell/public/cpp/lib/interface_registry.cc
@@ -15,9 +15,11 @@
     : binding_(this), allow_all_interfaces_(true), weak_factory_(this) {}
 
 InterfaceRegistry::InterfaceRegistry(
+    const Identity& local_identity,
     const Identity& remote_identity,
     const CapabilityRequest& capability_request)
     : binding_(this),
+      local_identity_(local_identity),
       remote_identity_(remote_identity),
       capability_request_(capability_request),
       allow_all_interfaces_(capability_request.interfaces.size() == 1 &&
@@ -95,13 +97,16 @@
   } else if (!CanBindRequestForInterface(interface_name)) {
     std::stringstream ss;
     ss << "Capability spec prevented service " << remote_identity_.name()
-       << " from binding interface: " << interface_name;
+       << " from binding interface: " << interface_name
+       << " exposed by: " << local_identity_.name();
     LOG(ERROR) << ss.str();
     mojo::ReportBadMessage(ss.str());
   } else if (!default_binder_.is_null()) {
     default_binder_.Run(interface_name, std::move(handle));
   } else {
-    LOG(ERROR) << "Failed to locate a binder for interface: " << interface_name;
+    LOG(ERROR) << "Failed to locate a binder for interface: " << interface_name
+               << " requested by: " << remote_identity_.name()
+               << " exposed by: " << local_identity_.name();
   }
 }
 
diff --git a/services/shell/public/cpp/lib/service_context.cc b/services/shell/public/cpp/lib/service_context.cc
index 6b7343b..dcf3085b 100644
--- a/services/shell/public/cpp/lib/service_context.cc
+++ b/services/shell/public/cpp/lib/service_context.cc
@@ -65,7 +65,7 @@
     mojom::InterfaceProviderRequest interfaces,
     const CapabilityRequest& allowed_capabilities) {
   std::unique_ptr<InterfaceRegistry> registry(
-      new InterfaceRegistry(source, allowed_capabilities));
+      new InterfaceRegistry(identity_, source, allowed_capabilities));
   registry->Bind(std::move(interfaces));
 
   if (!service_->OnConnect(source, registry.get()))
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 792fa878..fd48067 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -2824,106 +2824,972 @@
   "Lollipop Phone Tester": {
     "gtest_tests": [
       {
+        "override_isolate_target": "android_webview_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "android_webview_unittests"
       },
       {
+        "override_isolate_target": "base_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "base_unittests"
       },
       {
+        "override_isolate_target": "blimp_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "blimp_unittests"
       },
       {
         "override_compile_targets": [
           "breakpad_unittests_deps"
         ],
+        "override_isolate_target": "breakpad_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "breakpad_unittests"
       },
       {
+        "override_isolate_target": "capture_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "capture_unittests"
       },
       {
+        "override_isolate_target": "cc_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "cc_unittests"
       },
       {
+        "override_isolate_target": "components_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "components_browsertests"
       },
       {
+        "override_isolate_target": "components_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "components_unittests"
       },
       {
+        "override_isolate_target": "content_browsertests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "content_browsertests"
       },
       {
+        "override_isolate_target": "content_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "content_unittests"
       },
       {
+        "override_isolate_target": "device_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "device_unittests"
       },
       {
+        "override_isolate_target": "events_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "events_unittests"
       },
       {
+        "override_isolate_target": "gl_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "gl_tests"
       },
       {
+        "override_isolate_target": "gl_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "gl_unittests"
       },
       {
+        "override_isolate_target": "gpu_ipc_service_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "gpu_ipc_service_unittests"
       },
       {
+        "override_isolate_target": "gpu_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "gpu_unittests"
       },
       {
+        "override_isolate_target": "ipc_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "ipc_tests"
       },
       {
+        "override_isolate_target": "media_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "media_unittests"
       },
       {
+        "override_isolate_target": "net_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "net_unittests"
       },
       {
         "override_compile_targets": [
           "sandbox_linux_unittests_deps"
         ],
+        "override_isolate_target": "sandbox_linux_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "sandbox_linux_unittests"
       },
       {
+        "override_isolate_target": "sql_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "sql_unittests"
       },
       {
+        "override_isolate_target": "ui_android_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "ui_android_unittests"
       },
       {
+        "override_isolate_target": "ui_base_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "ui_base_unittests"
       },
       {
+        "override_isolate_target": "ui_touch_selection_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "ui_touch_selection_unittests"
       },
       {
+        "override_isolate_target": "unit_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "unit_tests"
-      }
-    ],
-    "instrumentation_tests": [
+      },
       {
+        "override_isolate_target": "android_webview_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "android_webview_test_apk"
       },
       {
-        "apk_under_test": "Blimp.apk",
         "override_compile_targets": [
           "blimp_test_apk"
         ],
-        "test": "blimp_test_apk",
-        "test_apk": "BlimpTest.apk"
+        "override_isolate_target": "blimp_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "blimp_test_apk"
       },
       {
+        "override_isolate_target": "chrome_public_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "chrome_public_test_apk"
       },
       {
+        "override_isolate_target": "chrome_sync_shell_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "chrome_sync_shell_test_apk"
       },
       {
+        "override_isolate_target": "content_shell_test_apk",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:3ff24775a900b675866fbcacf2a8f98a18b2a16a"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
         "test": "content_shell_test_apk"
       }
     ]
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 94cf312..542c94bc 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -9711,6 +9711,12 @@
         },
         "test": "headless_unittests"
       }
+    ],
+    "scripts": [
+      {
+        "name": "headless_python_unittests",
+        "script": "headless_python_unittests.py"
+      }
     ]
   },
   "LTO Linux": {
diff --git a/testing/scripts/headless_python_unittests.py b/testing/scripts/headless_python_unittests.py
new file mode 100755
index 0000000..8df9db06
--- /dev/null
+++ b/testing/scripts/headless_python_unittests.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import os
+import sys
+
+
+import common
+
+
+def main_run(args):
+  typ_path = os.path.abspath(os.path.join(
+      os.path.dirname(__file__), os.path.pardir, os.path.pardir,
+      'third_party', 'typ'))
+  _AddToPathIfNeeded(typ_path)
+  import typ
+
+  top_level_dir = os.path.join(common.SRC_DIR, 'headless', 'lib', 'browser')
+  with common.temporary_file() as tempfile_path:
+    rc = typ.main(
+        argv=[],
+        top_level_dir=top_level_dir,
+        write_full_results_to=tempfile_path,
+        coverage_source=[top_level_dir])
+
+    with open(tempfile_path) as f:
+      results = json.load(f)
+
+  parsed_results = common.parse_common_test_results(results, test_separator='.')
+  failures = parsed_results['unexpected_failures']
+
+  json.dump({
+      'valid': bool(rc <= common.MAX_FAILURES_EXIT_STATUS and
+                   ((rc == 0) or failures)),
+      'failures': failures.keys(),
+  }, args.output)
+
+  return rc
+
+
+def main_compile_targets(args):
+  json.dump([], args.output)
+
+
+def _AddToPathIfNeeded(path):
+  if path not in sys.path:
+    sys.path.insert(0, path)
+
+
+if __name__ == '__main__':
+  funcs = {
+    'run': main_run,
+    'compile_targets': main_compile_targets,
+  }
+  sys.exit(common.run_script(sys.argv[1:], funcs))
diff --git a/third_party/WebKit/LayoutTests/NeverFixTests b/third_party/WebKit/LayoutTests/NeverFixTests
index 05dd079..de73f35 100644
--- a/third_party/WebKit/LayoutTests/NeverFixTests
+++ b/third_party/WebKit/LayoutTests/NeverFixTests
@@ -119,9 +119,6 @@
 virtual/threaded/animations/transition-and-animation-2.html [ WontFix ]
 virtual/threaded/transitions/transition-end-event-multiple-04.html [ WontFix ]
 
-# This test only fails with an ASSERT in Debug build. But it's WontFix for Release, so something's wrong.
-crbug.com/655256 [ Release ] editing/input/orphan-set-selection-range.html [ WontFix ]
-
 # See crbug.com/522326
 imported/wpt/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-events.html [ WontFix ]
 # We don't allow to access external hosts in layout tests.
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 565916b..f4a6a8a 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1224,3 +1224,57 @@
 crbug.com/646323 [ Win Linux ] editing/selection/modify_move/move_backward_line_import_crash.html [ Crash ]
 
 crbug.com/645640 inspector/extensions/extensions-eval.html [ NeedsManualRebaseline ]
+
+crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/baseurl/alpha/worker.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/baseurl/alpha/importScripts.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/setting-port-members.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/baseurl/alpha/xhr.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/connect-event.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/xhr/001.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/interface-objects/003.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/constructors/Worker/unresolvable-url.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/interface-objects/004.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/Worker_ErrorEvent_error.htm [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/reporting-errors/002.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/encodings/004.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/reporting-errors/001.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/run-a-worker/003.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/Worker_cross_origin_security_err.htm [ Failure ]
+crbug.com/655458 imported/wpt/workers/semantics/encodings/003.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/baseurl/alpha/sharedworker.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/Worker_terminate_event_queue.htm [ Timeout ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/interface-objects.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html [ Failure ]
+crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/global-members.html [ Failure ]
+
+crbug.com/655458 imported/wpt/workers/constructors/SharedWorker/same-origin.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/constructors/Worker/same-origin.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/data-url-shared.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/003.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/004.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/005.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/006.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/007.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/multiple-workers/008.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/navigation/001.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/navigation/002.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/reporting-errors/004.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/xhr/002.html [ Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/xhr/004.html [ Timeout ]
+
+crbug.com/655458 imported/wpt/workers/semantics/structured-clone/dedicated.html [ Crash Timeout ]
+crbug.com/655458 imported/wpt/workers/semantics/structured-clone/shared.html [ Crash Timeout ]
+
+crbug.com/652187 [ Win7 Debug ] http/tests/inspector/network/network-disable-cache-preloads.php [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations
index 532a6fe5..cc61764b 100644
--- a/third_party/WebKit/LayoutTests/W3CImportExpectations
+++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -324,7 +324,8 @@
 ## Owners: michaeln@chromium.org,jsbell@chromium.org
 # imported/wpt/webstorage [ Pass ]
 imported/wpt/webvtt [ Skip ]
-imported/wpt/workers [ Skip ]
+## Owners: nhiroki@chromium.org
+# imported/wpt/workers [ Pass ]
 
 # Exceptions for individual files that fail due to bugs in the
 # upstream tests that we shouldn't bother importing until they are
diff --git a/third_party/WebKit/LayoutTests/WPTServeExpectations b/third_party/WebKit/LayoutTests/WPTServeExpectations
index 64b2eeb6..205c98a4 100644
--- a/third_party/WebKit/LayoutTests/WPTServeExpectations
+++ b/third_party/WebKit/LayoutTests/WPTServeExpectations
@@ -16,7 +16,6 @@
 crbug.com/508734 imported/wpt/html/browsers/history/the-location-interface/security_location_0.sub.htm [ Failure ]
 crbug.com/508734 imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html [ Failure ]
 crbug.com/508734 imported/wpt/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html [ Failure ]
-crbug.com/653859 imported/wpt/html/semantics/forms/constraints/form-validation-reportValidity.html [ Failure ]
 crbug.com/508734 imported/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/004.xhtml [ Failure ]
 crbug.com/508734 imported/wpt/webrtc/simplecall.html [ Failure ]
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-manually-fired-with-same-related-target-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-manually-fired-with-same-related-target-expected.txt
index de5b89ad..ba44ebf 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-manually-fired-with-same-related-target-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-manually-fired-with-same-related-target-expected.txt
@@ -10,6 +10,8 @@
   mouseout
 
   mouseover
+     @div1 (target: div1) (related: div1)
+     @shadow-root (target: div1) (related: div1)
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/mark-result-red.css b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/mark-result-red.css
new file mode 100644
index 0000000..3f3f95f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/mark-result-red.css
@@ -0,0 +1,3 @@
+#result {
+    color: red;
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/mark-result2-blue.css b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/mark-result2-blue.css
new file mode 100644
index 0000000..f384640
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/resources/mark-result2-blue.css
@@ -0,0 +1,3 @@
+#result2 {
+    color: blue;
+}
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/subresource-integrity-load-css-after-failed-integrity.html b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/subresource-integrity-load-css-after-failed-integrity.html
new file mode 100644
index 0000000..d31fc985
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/subresourceIntegrity/subresource-integrity-load-css-after-failed-integrity.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<link rel="stylesheet" type="text/css" href="resources/mark-result-red.css" integrity="sha256-deadbeef">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+function waitForLinkElementToLoad(linkElement) {
+  return new Promise(resolve => {
+    (function waitAgain() {
+      if (linkElement.sheet !== null) {
+        resolve(); 
+      } else {
+        setTimeout(waitAgain, 100);
+      }
+    })();
+  });
+}
+
+promise_test(() => {
+  let link = document.querySelector("link");
+
+  let divResult = document.createElement("div");
+  divResult.id = "result";
+  document.body.appendChild(divResult);
+
+  let divResult2 = document.createElement("div");
+  divResult2.id = "result2";
+  document.body.appendChild(divResult2);
+
+  return new Promise(resolve => {
+    window.addEventListener("load", resolve, {once: true});
+  })
+  .then(() => {
+    assert_equals(getComputedStyle(divResult).color.toString(), "rgb(0, 0, 0)", "bad integrity CSS should not be applied");
+
+    let linkElement = document.querySelector("link");
+    linkElement.removeAttribute("integrity");
+    linkElement.href = "resources/mark-result2-blue.css";
+    return waitForLinkElementToLoad(linkElement);
+  })
+  .then(() => {
+    assert_equals(getComputedStyle(divResult).color.toString(), "rgb(0, 0, 0)", "bad integrity CSS should not be applied");
+    assert_equals(getComputedStyle(divResult2).color.toString(), "rgb(0, 0, 255)", "CSS w/o integrity check disabled should load on the link element");
+  })
+  .then(() => {
+    document.body.removeChild(divResult);
+    document.body.removeChild(divResult2);
+  });
+}, 'Link element should still load another CSS after SRI check failed.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/event-composed-path-with-related-target-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/event-composed-path-with-related-target-expected.txt
deleted file mode 100644
index a5d0bbf..0000000
--- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/event-composed-path-with-related-target-expected.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-This is a testharness.js-based test.
-PASS Event path for an event with a relatedTarget. relatedTarget != target. 
-PASS Event path for an event with a relatedTarget. Event should be dispatched even when target and relatedTarget are same. 
-PASS Event path for an event with a relatedTarget. Event should stop at the shadow root 
-FAIL Event path for an event with a relatedTarget which is identical to target. Event should be dispatched and should stop at the shadow root. assert_equals: expected 2 but got 0
-PASS Event path for an event with a relatedTarget. target and relaterTarget do not share any shadow-including ancestor. target is in a shadow tree. 
-PASS Event path for an event with a relatedTarget. target and relaterTarget do not share any shadow-including ancestor. target is not in a shadow tree 
-PASS Event path for an event with a relatedTarget. target and relaterTarget share the same shadow-including ancestor. Both are in shadow trees. 
-PASS Event path for an event with a relatedTarget. relaterTarget is a shadow-including ancestor of target. 
-FAIL Event path for an event with a relatedTarget. target is a shadow-including ancestor of relatedTarget. assert_equals: expected 2 but got 0
-PASS Event path for an event with a relatedTarget. target is assigned to a slot. 
-PASS Event path for an event with a relatedTarget. relatedTarget is assigned to a slot. 
-PASS Event path for an event with a relatedTarget. Event should be dispatched at every slots. 
-PASS Event path for an event with a relatedTarget. Event should be dispatched at every slots. relatedTarget should be correctly retargeted. 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/README.md b/third_party/WebKit/LayoutTests/imported/wpt/workers/README.md
new file mode 100644
index 0000000..3a1c58f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/README.md
@@ -0,0 +1,8 @@
+This directory contains the Web Workers test suite.
+
+To run this test suite within a browser, go to: <http://w3c-test.org/web-platform-tests/master/workers/>.
+
+The latest Editor's Draft of Web Workers is: <http://dev.w3.org/html5/workers/>.
+
+The latest W3C Technical Report of Web Workers is <http://www.w3.org/TR/workers/>.
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_colno.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_colno.htm
new file mode 100644
index 0000000..793d6c1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_colno.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: col </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(typeof e.data.colno, "number");
+  });
+  worker.postMessage("Error Message");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_filename.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_filename.htm
new file mode 100644
index 0000000..e165a23
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_filename.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: location </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    var href = location.href;
+    var expected = href.substring(0, href.lastIndexOf('/')) + '/support/ErrorEvent.js';
+    assert_equals(e.data.filename, expected);
+  });
+  worker.postMessage("Error Message");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_lineno.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_lineno.htm
new file mode 100644
index 0000000..dfbc5146
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_lineno.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: line </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.lineno, 3);
+  });
+  worker.postMessage("Error Message");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_message.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_message.htm
new file mode 100644
index 0000000..bc1d2c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_ErrorEvent_message.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: message </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var message = 'Error Message';
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_greater_than(e.data.message.indexOf(message), -1);
+  });
+  worker.postMessage(message);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_close.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_close.htm
new file mode 100644
index 0000000..2ad5205
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_close.htm
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope close(): clear events queue </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerClose.js');
+  worker.onmessage = t.step_func(function(e) {
+    assert_equals(e.data, "ping");
+    worker.onmessage = t.unreached_func("Unexpected message event");
+    worker.postMessage("pong");
+    setTimeout(t.step_func_done(), 100);
+  });
+  worker.postMessage("ping");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts.htm
new file mode 100644
index 0000000..1a3616d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope API: importScripts() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/ImportScripts.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data, "Pass");
+  });
+  worker.postMessage("ping");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts_NetworkErr.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts_NetworkErr.htm
new file mode 100644
index 0000000..36fe6e0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_importScripts_NetworkErr.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> importScripts() with non-existent script file </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/ImportScriptsNetworkErr.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data, "Pass");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setInterval.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setInterval.htm
new file mode 100644
index 0000000..4e147fbf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setInterval.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope API: setInterval() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var result = [];
+  var worker = new Worker('./support/Timer.js');
+  worker.onmessage = t.step_func(function(e) {
+    result.push(e.data);
+    if (result.length == 3) {
+      assert_array_equals(result, ["hello", "worker", "worker"]);
+      worker.onmessage = t.unreached_func('Unexpected message event');
+      setTimeout(t.step_func_done(), 100);
+    }
+  });
+  worker.postMessage("IntervalHandler");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setTimeout.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setTimeout.htm
new file mode 100644
index 0000000..89fdf3d7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerGlobalScope_setTimeout.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope API: setTimeout() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var result = [];
+  var worker = new Worker('./support/Timer.js');
+  worker.onmessage = t.step_func(function(e) {
+    result.push(e.data);
+    if (result.length == 3) {
+      assert_array_equals(result, ["hello", "worker", "worker"]);
+      worker.onmessage = t.unreached_func('Unexpected message event');
+      setTimeout(t.step_func_done(), 100);
+    }
+  });
+  worker.postMessage("TimeoutHandler");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation.htm
new file mode 100644
index 0000000..a74f13a8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> WorkerLocation object </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    var href = window.location.href;
+    var ExpectedResult = href.substring(0, href.lastIndexOf('/')) + '/support/WorkerLocation.js';
+    assert_equals(e.data.location, ExpectedResult);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash.htm
new file mode 100644
index 0000000..74a424e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: hash </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerLocation.js#HashString");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.hash, "#HashString");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_encoding.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_encoding.htm
new file mode 100644
index 0000000..b2a171a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_encoding.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.hash with url encoding string </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerLocation.js#question%3f");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.hash, "#question%3f");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_nonexist.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_nonexist.htm
new file mode 100644
index 0000000..2d898c0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hash_nonexist.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.hash with no &lt;fragment&gt; component </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.hash, "");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_host.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_host.htm
new file mode 100644
index 0000000..53286ddf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_host.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: host </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.host, location.host);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hostname.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hostname.htm
new file mode 100644
index 0000000..9725080
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_hostname.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: hostname </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.hostname, location.hostname);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_href.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_href.htm
new file mode 100644
index 0000000..3ed1dbd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_href.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> WorkerLocation href attribute </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerLocation.js?srch%20#hash");
+  worker.onmessage = t.step_func_done(function(e) {
+    var href = location.href;
+    var expected = href.substring(0, href.lastIndexOf('/')) + "/support/WorkerLocation.js?srch%20#hash";
+    assert_equals(e.data.href, expected);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_pathname.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_pathname.htm
new file mode 100644
index 0000000..3469845
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_pathname.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: pathname </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    var pathname = location.pathname;
+    var expected = pathname.substring(0, pathname.lastIndexOf('/')) + '/support/WorkerLocation.js';
+    assert_equals(e.data.pathname, expected);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_port.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_port.htm
new file mode 100644
index 0000000..ef86cfa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_port.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.port, location.port);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_protocol.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_protocol.htm
new file mode 100644
index 0000000..f792dee5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_protocol.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: protocol </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.protocol, location.protocol);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search.htm
new file mode 100644
index 0000000..bc6add8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: search </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js?SearchString');
+  worker.onmessage = t.step_func_done(function(e) {
+      assert_equals(e.data.search, '?SearchString');
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_empty.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_empty.htm
new file mode 100644
index 0000000..a32d430
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_empty.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.search with empty &lt;query&gt; </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerLocation.js?");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.search, "");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_fragment.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_fragment.htm
new file mode 100644
index 0000000..3ec4cff
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_fragment.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.search with &lt;fragment&gt; in &lt;query&gt; </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js?test#');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.search, "?test");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_nonexist.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_nonexist.htm
new file mode 100644
index 0000000..9907e647
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerLocation_search_nonexist.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.search  with no &lt;query&gt; component </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerLocation.js');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.search, "");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appName.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appName.htm
new file mode 100644
index 0000000..832c46f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appName.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator appName </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerNavigator.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.appName, navigator.appName);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appVersion.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appVersion.htm
new file mode 100644
index 0000000..7deaa42
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_appVersion.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator appVersion </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerNavigator.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.appVersion, navigator.appVersion);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_onLine.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_onLine.htm
new file mode 100644
index 0000000..f9e819b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_onLine.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator.onLine </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerNavigator.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.onLine, navigator.onLine);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_platform.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_platform.htm
new file mode 100644
index 0000000..3a6de80
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_platform.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator.platform </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerNavigator.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.platform, navigator.platform);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_userAgent.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_userAgent.htm
new file mode 100644
index 0000000..8a34fb48
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/WorkerNavigator_userAgent.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator.userAgent </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerNavigator.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.userAgent, navigator.userAgent);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_bubbles_cancelable.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_bubbles_cancelable.htm
new file mode 100644
index 0000000..4619ee7b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_bubbles_cancelable.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Workers: Worker ErrorEvent - bubbles, cancelable</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onerror = t.step_func_done(function(e) {
+    assert_false(e.bubbles, "onerror on worker doesn't bubble");
+    assert_true(e.cancelable, "onerror on worker is cancelable");
+  });
+  worker.postMessage("Error Message");
+}, "ErrorEvent on worker doesn't bubble and is cancelable");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_error.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_error.htm
new file mode 100644
index 0000000..1c1257d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_error.htm
@@ -0,0 +1,29 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+var t1 = async_test("Error handler outside the worker should not see the error value");
+var t2 = async_test("Error handlers inside a worker should see the error value");
+
+test(function() {
+  var worker = new Worker("support/ErrorEvent-error.js");
+  worker.onerror = t1.step_func_done(function(e) {
+    assert_true(/hello/.test(e.message));
+    assert_equals(e.error, null);
+  });
+
+  var messages = 0;
+  worker.onmessage = t2.step_func(function(e) {
+    ++messages;
+    var data = e.data;
+    assert_true(data.source == "onerror" ||
+                data.source == "event listener");
+    assert_equals(data.value, "hello");
+    if (messages == 2) {
+      t2.done();
+    }
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_filename.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_filename.htm
new file mode 100644
index 0000000..0faef6fea
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_filename.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.filename </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onerror = t.step_func_done(function(e) {
+    var href = location.href;
+    var expected = href.substring(0, href.lastIndexOf('/')) + '/support/ErrorEvent.js';
+    assert_equals(e.filename, expected);
+  });
+  worker.postMessage("Error Message");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_lineno.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_lineno.htm
new file mode 100644
index 0000000..ad98172
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_lineno.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.lineno </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onerror = t.step_func_done(function(e) {
+    assert_equals(e.lineno, 3);
+  });
+  worker.postMessage("Error Message");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_message.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_message.htm
new file mode 100644
index 0000000..5602d9bc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_message.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.message </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var message = 'Error Message';
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onerror = t.step_func_done(function(e) {
+    assert_greater_than(e.message.indexOf(message), -1);
+  });
+  worker.postMessage(message);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_type.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_type.htm
new file mode 100644
index 0000000..3a0f85ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_ErrorEvent_type.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.type </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The worker events races with the window's load event; if the worker events
+// arrive first, the harness will detect the error event and fail the test.
+setup({ allow_uncaught_exception: true });
+
+async_test(function(t) {
+  var worker = new Worker('./support/ErrorEvent.js');
+  worker.onerror = t.step_func_done(function(e) {
+    assert_class_string(e, 'ErrorEvent');
+    assert_equals(e.type, 'error');
+  });
+  worker.postMessage("Error Message");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_basic.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_basic.htm
new file mode 100644
index 0000000..d2b57b49
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_basic.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title> Web Workers Basic Tests </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function create_worker() {
+  return new Worker('./support/WorkerBasic.js');
+}
+
+test(function() {
+  var worker = create_worker();
+  assert_class_string(worker, "Worker");
+}, "Worker constructor");
+
+async_test(function(t) {
+  var worker = create_worker();
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data, "Pass");
+  });
+  worker.postMessage("start");
+}, "MessageEvent.data");
+
+async_test(function(t) {
+  var worker = create_worker();
+  worker.addEventListener("message", t.step_func_done(function(e) {
+    assert_equals(e.type, "message");
+  }), true);
+  worker.postMessage("start");
+}, "MessageEvent.type");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_cross_origin_security_err.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_cross_origin_security_err.htm
new file mode 100644
index 0000000..647a8b81
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_cross_origin_security_err.htm
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title> Worker cross-origin URL </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  try {
+    var w = new Worker("ftp://example.org/support/WorkerBasic.js");
+    w.onerror = t.step_func_done(function(e) {
+      assert_true(e instanceof ErrorEvent);
+    });
+  } catch (e) {
+    t.step_func_done(function(e) { assert_true(true); });
+  }
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm
new file mode 100644
index 0000000..aea7e025
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_dispatchEvent_ErrorEvent.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title> ErrorEvent and Worker.dispatchEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var event = "error";
+  var filename = './support/ErrorEvent.js';
+  var message = 'Hello Worker';
+  var lineno = 5;
+  var colno = 6;
+  var error = new Error("test");
+  var worker = new Worker(filename);
+  worker.addEventListener(event, t.step_func_done(function(e) {
+    assert_equals(e.type, event, 'type');
+    assert_equals(e.message, message, 'message');
+    assert_equals(e.filename, filename, 'filename');
+    assert_equals(e.lineno, lineno, 'lineno');
+    assert_equals(e.colno, colno, 'colno');
+    assert_equals(e.error, error, 'error');
+  }), true);
+  var e = new ErrorEvent(event, {bubbles:true, cancelable:true, message:message, filename:filename, lineno:lineno, colno:colno, error:error});
+  worker.dispatchEvent(e);
+});
+
+test(function() {
+  var e = document.createEvent("ErrorEvent");
+  var eProto = Object.getPrototypeOf(e);
+  assert_equals(eProto, ErrorEvent.prototype);
+}, "document.createEvent('ErrorEvent')");
+
+test(function() {
+  var e = new ErrorEvent("error");
+  assert_false("initErrorEvent" in e, "should not be supported");
+}, "initErrorEvent");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_script_mimetype.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_script_mimetype.htm
new file mode 100644
index 0000000..04fe68e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_script_mimetype.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> Worker constructor with script inside text file </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker('./support/WorkerText.txt');
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data, "Pass");
+  });
+  worker.postMessage("start");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_terminate_event_queue.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_terminate_event_queue.htm
new file mode 100644
index 0000000..5d9472a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/Worker_terminate_event_queue.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title> AbstractWorker terminate(): clear event queue </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var testResult;
+  var worker = new Worker('./support/WorkerTerminate.js');
+  worker.onmessage = this.step_func(function(e) {
+    testResult = e.data;
+    if (testResult >= 10000) {
+      worker.terminate();
+      worker.onmessage = this.unreached_func('Unexpected message event');
+      setTimeout(this.step_func_done(function() {
+        assert_equals(testResult, 10000);
+      }), 100);
+    }
+  });
+  worker.postMessage("ping");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/importScripts.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/importScripts.html
new file mode 100644
index 0000000..0fbd35b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/importScripts.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Base URL in workers: importScripts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function() {
+  var worker = new Worker("../beta/importScripts.py");
+  worker.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, "gamma");
+  });
+  worker.onerror = this.unreached_func("Got error event");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/sharedworker.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/sharedworker.html
new file mode 100644
index 0000000..25d25823
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/sharedworker.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Base URL in workers: new SharedWorker()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function() {
+  var worker = new Worker("../beta/sharedworker.py");
+  worker.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, "gamma");
+  });
+  worker.onerror = this.unreached_func("Got error event");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/worker.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/worker.html
new file mode 100644
index 0000000..284425e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/worker.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Base URL in workers: new Worker()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function() {
+  var worker = new Worker("../beta/worker.py");
+  worker.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, "gamma");
+  });
+  worker.onerror = this.unreached_func("Got error event");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/xhr.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/xhr.html
new file mode 100644
index 0000000..9a1219b4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/alpha/xhr.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Base URL in workers: XHR</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function() {
+  var worker = new Worker("../beta/xhr.py");
+  worker.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, "gamma\n");
+  });
+  worker.onerror = this.unreached_func("Got error event");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/importScripts.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/importScripts.py
new file mode 100644
index 0000000..75dac19
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/importScripts.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    return (302, "Moved"), [("Location", "../gamma/importScripts.js")], "postMessage('executed redirecting script');"
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/script.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/script.js
new file mode 100644
index 0000000..8fe3dfc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/script.js
@@ -0,0 +1 @@
+postMessage('beta');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/sharedworker.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/sharedworker.py
new file mode 100644
index 0000000..875cc9a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/sharedworker.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    return (302, "Moved"), [("Location", "../gamma/sharedworker.js")], "postMessage('executed redirecting script');"
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subsharedworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subsharedworker.js
new file mode 100644
index 0000000..de6a8ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subsharedworker.js
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+  e.source.postMessage('beta');
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subworker.js
new file mode 100644
index 0000000..997cecd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/subworker.js
@@ -0,0 +1 @@
+postMessage("beta");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/test.txt b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/test.txt
new file mode 100644
index 0000000..65b2df87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/test.txt
@@ -0,0 +1 @@
+beta
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/worker.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/worker.py
new file mode 100644
index 0000000..44baf520
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/worker.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    return (302, "Moved"), [("Location", "../gamma/worker.js")], "postMessage('executed redirecting script');"
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/xhr.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/xhr.py
new file mode 100644
index 0000000..de3f04e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/beta/xhr.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    return (302, "Moved"), [("Location", "../gamma/xhr.js")], "postMessage('executed redirecting script');"
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/importScripts.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/importScripts.js
new file mode 100644
index 0000000..3f76856
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/importScripts.js
@@ -0,0 +1 @@
+importScripts("script.js");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/script.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/script.js
new file mode 100644
index 0000000..dddf224
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/script.js
@@ -0,0 +1 @@
+postMessage('gamma');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/sharedworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/sharedworker.js
new file mode 100644
index 0000000..d0718cfd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/sharedworker.js
@@ -0,0 +1,4 @@
+var worker = new SharedWorker("subsharedworker.js");
+worker.port.onmessage = function(e) {
+  postMessage(e.data);
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subsharedworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subsharedworker.js
new file mode 100644
index 0000000..e23602f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subsharedworker.js
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+  e.source.postMessage('gamma');
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subworker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subworker.js
new file mode 100644
index 0000000..44407358
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/subworker.js
@@ -0,0 +1 @@
+postMessage("gamma");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/test.txt b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/test.txt
new file mode 100644
index 0000000..af17f6c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/test.txt
@@ -0,0 +1 @@
+gamma
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/worker.js
new file mode 100644
index 0000000..8cfbcae
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/worker.js
@@ -0,0 +1,4 @@
+var worker = new Worker("subworker.js");
+worker.onmessage = function(e) {
+  postMessage(e.data);
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/xhr.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/xhr.js
new file mode 100644
index 0000000..70f3315
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/baseurl/gamma/xhr.js
@@ -0,0 +1,4 @@
+var x = new XMLHttpRequest();
+x.open("GET", "test.txt", false);
+x.send();
+postMessage(x.response);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/1 b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/1
new file mode 100644
index 0000000..c3f67be
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/1
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+  e.ports[0].postMessage(['1', self.name]);
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/URLMismatchError.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/URLMismatchError.htm
new file mode 100644
index 0000000..e74e660
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/URLMismatchError.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Workers: SharedWorker - throw URLMismatchError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+  test(function() {
+    var worker = new SharedWorker('shared-worker.js', 'name');
+
+    assert_throws("URLMismatchError", function() {
+      new SharedWorker('some-other-url.js', 'name');
+    });
+
+  }, "Create SharedWorker with different URLs but same name");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/connect-event.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/connect-event.html
new file mode 100644
index 0000000..a9719d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/connect-event.html
@@ -0,0 +1,26 @@
+<!--
+onconnect = function(e) {
+  e.ports[0].postMessage([e.data === '', e instanceof MessageEvent, e.ports.length == 1]);
+};
+/*
+-->
+<!doctype html>
+<title>connect event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker('#');
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_true(e.data[0], "e.data === ''");
+    assert_true(e.data[1], "e instanceof MessageEvent");
+    assert_true(e.data[2], "e.ports.length == 1");
+    this.done();
+  }), false);
+  worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-name.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-name.html
new file mode 100644
index 0000000..9e27329
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-name.html
@@ -0,0 +1,17 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>creating a dummy shared worker with name "foo"</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var worker = new SharedWorker('#', 'foo');
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-shared-worker.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-shared-worker.html
new file mode 100644
index 0000000..e9aff9c5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/dummy-shared-worker.html
@@ -0,0 +1,17 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>creating a dummy shared worker</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var worker = new SharedWorker('#');
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/empty-name.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/empty-name.html
new file mode 100644
index 0000000..95ff6d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/empty-name.html
@@ -0,0 +1,17 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>creating a dummy shared worker with explicit name ""</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var worker = new SharedWorker('#', '');
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/global-members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/global-members.html
new file mode 100644
index 0000000..af4eb1d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/global-members.html
@@ -0,0 +1,34 @@
+<!--
+var expected = 'self location close onerror importScripts navigator addEventListener removeEventListener dispatchEvent name applicationCache onconnect setTimeout clearTimeout setInterval clearInterval'.split(' ');
+var log = '';
+for (var i = 0; i < expected.length; ++i) {
+  if (!(expected[i] in self))
+    log += expected[i] + ' did not exist\n';
+}
+onconnect = function(e) {
+  e.ports[0].postMessage(log);
+};
+/*
+-->
+<!doctype html>
+<title>members of SharedWorkerGlobalScope</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker('#');
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  }), false);
+  worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
+
+
+
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/interface-objects.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/interface-objects.html
new file mode 100644
index 0000000..e91b2dc6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/interface-objects.html
@@ -0,0 +1,41 @@
+<!--
+var prt;
+function handleCall(e) {
+  var log = [];
+  for (var i = 0; i < e.data.length; ++i) {
+    if (!(e.data[i] in self))
+      log.push(e.data[i]);
+  }
+  prt.postMessage('These were missing: '+log.join(', '));
+}
+onconnect = function(e) {
+  prt = e.ports[0];
+  prt.onmessage = handleCall;
+};
+/*
+-->
+<!doctype html>
+<title>expected interface objects/constructors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var expected = 'XMLHttpRequest WebSocket EventSource MessageChannel Worker SharedWorker ApplicationCache'.split(' ');
+  var supported = [];
+  for (var i = 0; i < expected.length; ++i) {
+  if (expected[i] in window)
+     supported.push(expected[i]);
+  }
+  var worker = new SharedWorker('#');
+  worker.port.start();
+  worker.port.postMessage(supported);
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/name.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/name.html
new file mode 100644
index 0000000..823e16c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/name.html
@@ -0,0 +1,24 @@
+<!--
+onconnect = function(e) {
+  e.ports[0].postMessage(self.name);
+}
+/*
+-->
+<!doctype html>
+<title>self.name</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker('#', 'hello');
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data, 'hello');
+    this.done();
+  }), false);
+  worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/no-arguments-ctor.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/no-arguments-ctor.html
new file mode 100644
index 0000000..eaee870d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/no-arguments-ctor.html
@@ -0,0 +1,20 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>no arguments</title>
+<link rel=help href="http://www.whatwg.org/html/#sharedworker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  assert_throws(new TypeError(), function() {
+    var worker = new SharedWorker();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null
new file mode 100644
index 0000000..5c38505b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+  e.ports[0].postMessage(['null', self.name]);
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null-arguments.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null-arguments.html
new file mode 100644
index 0000000..c711b2c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/null-arguments.html
@@ -0,0 +1,25 @@
+<!--
+onconnect = function(e) {
+  e.ports[0].postMessage(['FAIL', self.name]);
+}
+/*
+-->
+<!doctype html>
+<title>null as arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker(null, null);
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data[0], 'null', 'first arg');
+    assert_equals(e.data[1], 'null', 'second arg');
+    this.done();
+  }), false);
+  worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/number-arguments.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/number-arguments.html
new file mode 100644
index 0000000..1a4cfb2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/number-arguments.html
@@ -0,0 +1,25 @@
+<!--
+onconnect = function(e) {
+  e.ports[0].postMessage(['FAIL', self.name]);
+}
+/*
+-->
+<!doctype html>
+<title>1 as arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker(1, 1);
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data[0], '1', 'first arg');
+    assert_equals(e.data[1], '1', 'second arg');
+    this.done();
+  }), false);
+  worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-onmessage.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-onmessage.html
new file mode 100644
index 0000000..a2f4df0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-onmessage.html
@@ -0,0 +1,23 @@
+<!--
+onconnect = function(e) {
+  e.ports[0].postMessage(true);
+}
+/*
+-->
+<!doctype html>
+<title>worker.port.onmessage</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker('#', '');
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-properties.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-properties.html
new file mode 100644
index 0000000..f8a676d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-properties.html
@@ -0,0 +1,26 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>worker.port</title>
+<link rel=help href="http://www.whatwg.org/html/#sharedworker">
+<link rel=help href="http://www.whatwg.org/html/#messageport">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var worker = new SharedWorker('#', '');
+  assert_true('port' in worker, "port");
+  assert_true('postMessage' in worker.port, "postMessage");
+  assert_true('start' in worker.port, "start");
+  assert_true('close' in worker.port, "close");
+  assert_true('onmessage' in worker.port, "onmessage");
+  assert_true('addEventListener' in worker.port, "addEventListener");
+  assert_true('removeEventListener' in worker.port, "removeEventListener");
+  assert_true('dispatchEvent' in worker.port, "dispatchEvent");
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-readonly.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-readonly.html
new file mode 100644
index 0000000..f087ab0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/port-readonly.html
@@ -0,0 +1,21 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>setting worker.port</title>
+<link rel=help href="http://www.whatwg.org/html/#sharedworker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#dfn-attribute-setter">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  var worker = new SharedWorker('#', '');
+  var x = worker.port;
+  worker.port = 1;
+  assert_equals(worker.port, x);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/same-origin.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/same-origin.html
new file mode 100644
index 0000000..2e0dd8d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/same-origin.html
@@ -0,0 +1,67 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>same-origin checks</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Needed to prevent a race condition if a worker throws an exception that may or may
+// not propogate to the window before the tests finish
+setup({allow_uncaught_exception: true});
+
+function testSharedWorkerHelper(t, script) {
+  try {
+    var worker = new SharedWorker(script, '');
+    worker.onerror = t.step_func_done(function(e) {
+      assert_true(e instanceof ErrorEvent);
+    });
+  } catch (e) {
+    t.step_func_done(function(e) { assert_true(true); });
+  }
+}
+
+test(function() {
+  assert_throws("SecurityError", function() { new SharedWorker('unsupported:', ''); });
+}, "unsupported_scheme");
+
+async_test(function() {
+  var worker = new SharedWorker('data:,onconnect = function(e) { e.ports[0].postMessage(1); }', '');
+  worker.port.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, 1);
+  });
+}, "data_url");
+
+async_test(function(t) {
+  testSharedWorkerHelper(this, 'javascript:""');
+}, "javascript_url");
+
+async_test(function(t) {
+  testSharedWorkerHelper(this, 'about:blank');
+}, "about_blank");
+
+async_test(function(t) {
+  testSharedWorkerHelper(this, 'http://www.opera.com/');
+}, "opera_com");
+
+async_test(function(t) {
+  testSharedWorkerHelper(this, location.protocol+'//'+location.hostname+':81/');
+}, "port_81");
+
+async_test(function(t) {
+  testSharedWorkerHelper(this, 'https://'+location.hostname+':80/');
+}, "https_port_80");
+
+async_test(function(t) {
+  testSharedWorkerHelper(this, 'https://'+location.hostname+':8000/');
+}, "https_port_8000");
+
+async_test(function(t) {
+  testSharedWorkerHelper(this, 'http://'+location.hostname+':8012/');
+}, "http_port_8012");
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/setting-port-members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/setting-port-members.html
new file mode 100644
index 0000000..8c79ff2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/setting-port-members.html
@@ -0,0 +1,59 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>setting members of worker.port</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup(function() {
+  window.worker = new SharedWorker('#', '');
+});
+test(function() {
+  worker.port.postMessage = 1;
+  assert_equals(worker.port.postMessage, 1);
+}, 'postMessage');
+test(function() {
+  worker.port.start = 1;
+  assert_equals(worker.port.start, 1);
+}, 'start');
+test(function() {
+  worker.port.close = 1;
+  assert_equals(worker.port.close, 1);
+}, 'close');
+test(function() {
+  var f = function(){};
+  worker.port.onmessage = f;
+  assert_equals(worker.port.onmessage, f, 'function(){}');
+  worker.port.onmessage = 1;
+  assert_equals(worker.port.onmessage, null, '1');
+  worker.port.onmessage = f;
+  worker.port.onmessage = ';';
+  assert_equals(worker.port.onmessage, null, '";"');
+  worker.port.onmessage = f;
+  worker.port.onmessage = {handleEvent:function(){}};
+  assert_equals(worker.port.onmessage, null, '{handleEvent:function(){}}');
+  worker.port.onmessage = f;
+  worker.port.onmessage = null;
+  assert_equals(worker.port.onmessage, null, 'null');
+  worker.port.onmessage = f;
+  worker.port.onmessage = undefined;
+  assert_equals(worker.port.onmessage, null, 'undefined');
+}, 'onmessage');
+test(function() {
+  worker.port.addEventListener = 1;
+  assert_equals(worker.port.addEventListener, 1);
+}, 'addEventListener');
+test(function() {
+  worker.port.removeEventListener = 1;
+  assert_equals(worker.port.removeEventListener, 1);
+}, 'removeEventListener');
+test(function() {
+  worker.port.despatchEvent = 1;
+  assert_equals(worker.port.despatchEvent, 1);
+}, 'despatchEvent');
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/shared-worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/shared-worker.js
new file mode 100644
index 0000000..babebb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/shared-worker.js
@@ -0,0 +1,6 @@
+onconnect = function(e) {
+  var port = e.ports[0];
+  port.onmessage = function(e) {
+    port.postMessage('ping');
+  }
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined
new file mode 100644
index 0000000..3fe840d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+  e.ports[0].postMessage(['undefined', self.name]);
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html
new file mode 100644
index 0000000..b9a3b369
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/undefined-arguments.html
@@ -0,0 +1,25 @@
+<!--
+onconnect = function(e) {
+  e.ports[0].postMessage(['FAIL', self.name]);
+}
+/*
+-->
+<!doctype html>
+<title>undefined as arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker(undefined, undefined);
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data[0], 'undefined', 'first arg');
+    assert_equals(e.data[1], 'undefined', 'second arg');
+    this.done();
+  }), false);
+  worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unexpected-global-properties.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unexpected-global-properties.html
new file mode 100644
index 0000000..39739022
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unexpected-global-properties.html
@@ -0,0 +1,30 @@
+<!--
+var unexpected = 'open print stop getComputedStyle getSelection releaseEvents captureEvents alert confirm prompt addEventStream removeEventStream back forward attachEvent detachEvent navigate DOMParser XMLSerializer XPathEvaluator XSLTProcessor opera Image Option frames Audio SVGUnitTypes SVGZoomAndPan java netscape sun Packages ByteArray closed defaultStatus document event frameElement history innerHeight innerWidth opener outerHeight outerWidth pageXOffset pageYOffset parent screen screenLeft screenTop screenX screenY status top window length'.split(' '); // iterated window in opera and removed expected ones
+var log = '';
+for (var i = 0; i < unexpected.length; ++i) {
+  if (unexpected[i] in self)
+    log += unexpected[i] + ' ';
+}
+onconnect = function(e) {
+  e.ports[0].postMessage(log);
+};
+/*
+-->
+<!doctype html>
+<title>unexpected members/interface objects/constructors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new SharedWorker('#');
+  worker.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  }), false);
+  worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html
new file mode 100644
index 0000000..2ca3d93d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/SharedWorker/unresolvable-url.html
@@ -0,0 +1,19 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>resolving broken url</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  assert_throws("SyntaxError", function() {
+    var worker = new SharedWorker('http://foo bar');
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/1 b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/1
new file mode 100644
index 0000000..ea0b7c8f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/1
@@ -0,0 +1 @@
+postMessage('1');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html
new file mode 100644
index 0000000..c40424d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/AbstractWorker.onerror.html
@@ -0,0 +1,48 @@
+<!--
+for (;) // should cause onerror to be invoked, but onerror is null, so
+        // the error is "not handled". should fire an ErrorEvent on the
+        // worker.
+  break;
+postMessage(1); // shouldn't do anything since the script doesn't compile
+/*
+-->
+<!doctype html>
+<title>AbstractWorker.onerror</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#runtime-script-errors-2">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#report-the-error">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-event-handler-processing-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup({allow_uncaught_exception:true});
+async_test(function() {
+  var worker = new Worker('#');
+  var error;
+  worker.onerror = this.step_func(function(a, b, c) {
+    error = a;
+    assert_equals('' + a, '[object ErrorEvent]');
+    assert_true("message" in a, 'ErrorEvent.message');
+    assert_equals(typeof a.message, "string", 'ErrorEvent.message');
+    assert_equals(a.filename, document.URL + '#', 'ErrorEvent.filename');
+    assert_true("lineno" in a, 'ErrorEvent.lineno');
+    assert_equals(typeof a.lineno, "number", 'ErrorEvent.lineno');
+    assert_equals(b, undefined, 'unexpected second argument to onerror');
+    assert_equals(c, undefined, 'unexpected third argument to onerror');
+  });
+  worker.onmessage = this.step_func(function(e) {
+    assert_unreached('onmessage was invoked but worker script shouldn\'t have compiled');
+  });
+  window.onerror = this.step_func_done(function(a, b, c, d, e, f) {
+    assert_equals(a, error.message, 'message');
+    assert_equals(b, error.filename, 'filename');
+    assert_equals(c, error.lineno, 'lineno');
+    assert_equals(d, error.colno, 'colno');
+    assert_equals(e, error.error, 'error');
+    assert_equals(f, undefined, 'unexpected sixth argument to onerror');
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/Blob-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/Blob-url.html
new file mode 100644
index 0000000..168fc91
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/Blob-url.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Workers: Worker - Blob url</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+  async_test(function(t) {
+    var blob = new Blob(["onmessage = function(event) { postMessage(event.data); }"], {type: "text/plain"});
+    var worker = new Worker(window.URL.createObjectURL(blob));
+    var data = "Blob URL";
+    worker.postMessage(data);
+    worker.onmessage = t.step_func(function(event) {
+      assert_equals(event.data, data, "event.data");
+      t.done();
+    });
+  }, "Worker supports Blob url");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker.js
new file mode 100644
index 0000000..2ef466c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.worker.js
@@ -0,0 +1,18 @@
+importScripts("/resources/testharness.js");
+
+var expected = [
+  'postMessage', 'onmessage', /* DedicatedWorkerGlobalScope */
+  'self', 'location', 'close', 'onerror', 'onoffline', 'ononline', /* WorkerGlobalScope */
+  'addEventListener', 'removeEventListener', 'dispatchEvent', /* EventListener */
+  'importScripts', 'navigator', /* WorkerUtils */
+  'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', /* WindowTimers */
+  'btoa', 'atob' /* WindowBase64 */
+];
+for (var i = 0; i < expected.length; ++i) {
+  var property = expected[i];
+  test(function() {
+    assert_true(property in self);
+  }, "existence of " + property);
+}
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-1.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-1.html
new file mode 100644
index 0000000..bd865261
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-1.html
@@ -0,0 +1,23 @@
+<!--
+postMessage('FAIL');
+/*
+-->
+<!doctype html>
+<title>1 as argument</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+  var worker = new Worker(1);
+  worker.addEventListener('message', t.step_func_done(function(e) {
+    assert_equals(e.data, '1')
+  }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-null.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-null.html
new file mode 100644
index 0000000..94ab71a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-null.html
@@ -0,0 +1,23 @@
+<!--
+postMessage('FAIL');
+/*
+-->
+<!doctype html>
+<title>null as argument</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+  var worker = new Worker(null);
+  worker.addEventListener('message', t.step_func_done(function(e) {
+    assert_equals(e.data, 'null')
+  }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-undefined.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-undefined.html
new file mode 100644
index 0000000..2d9eb6e6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/ctor-undefined.html
@@ -0,0 +1,23 @@
+<!--
+postMessage('FAIL');
+/*
+-->
+<!doctype html>
+<title>undefined as argument</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+  var worker = new Worker(undefined);
+  worker.addEventListener('message', t.step_func_done(function(e) {
+    assert_equals(e.data, 'undefined')
+  }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/expected-self-properties.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/expected-self-properties.worker.js
new file mode 100644
index 0000000..0ce41b59
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/expected-self-properties.worker.js
@@ -0,0 +1,11 @@
+importScripts("/resources/testharness.js");
+
+var expected = ['XMLHttpRequest', 'WebSocket', 'EventSource', 'MessageChannel', 'Worker', 'SharedWorker'];
+for (var i = 0; i < expected.length; ++i) {
+  var property = expected[i];
+  test(function() {
+    assert_true(property in self);
+  }, "existence of " + property);
+}
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/no-arguments-ctor.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/no-arguments-ctor.html
new file mode 100644
index 0000000..770c7cc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/no-arguments-ctor.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>without arguments</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call">
+<link rel=help href="http://www.whatwg.org/html/#dedicated-workers-and-the-worker-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  assert_throws(new TypeError(), function() { new Worker(); });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/null b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/null
new file mode 100644
index 0000000..6d079b5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/null
@@ -0,0 +1 @@
+postMessage('null');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/resolve-empty-string.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/resolve-empty-string.html
new file mode 100644
index 0000000..0426223
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/resolve-empty-string.html
@@ -0,0 +1,22 @@
+<!--
+postMessage('ok');
+/*
+-->
+<!doctype html>
+<meta charset=utf-8>
+<title>resolve the empty string</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+  var worker = new Worker('');
+  worker.addEventListener('message', t.step_func_done(function(e) {
+    assert_equals(e.data, 'ok');
+  }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/same-origin.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/same-origin.html
new file mode 100644
index 0000000..9b0148d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/same-origin.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>same-origin checks; the script is in a script element</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Needed to prevent a race condition if a worker throws an exception that may or may
+// not propogate to the window before the tests finish
+setup({allow_uncaught_exception: true});
+
+function testSharedWorkerHelper(t, script) {
+  try {
+    var worker = new SharedWorker(script, '');
+    worker.onerror = t.step_func_done(function(e) {
+      assert_true(e instanceof ErrorEvent);
+    });
+  } catch (e) {
+    t.step_func_done(function(e) { assert_true(true); });
+  }
+}
+
+test(function() {
+  assert_throws("SecurityError", function() { new Worker('unsupported:'); });
+}, "unsupported_scheme");
+
+async_test(function() {
+  var worker = new Worker('data:,postMessage(1);');
+  worker.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, 1);
+  });
+}, "data_url");
+
+async_test(function(t) {
+  testSharedWorkerHelper(t, 'about:blank');
+}, "about_blank");
+
+async_test(function(t) {
+  testSharedWorkerHelper(t, 'http://www.example.invalid/');
+}, "example_invalid");
+
+async_test(function(t) {
+  testSharedWorkerHelper(t, location.protocol+'//'+location.hostname+':81/');
+}, "port_81");
+
+async_test(function(t) {
+  testSharedWorkerHelper(t, 'https://'+location.hostname+':80/');
+}, "https_port_80");
+
+async_test(function(t) {
+  testSharedWorkerHelper(t, 'https://'+location.hostname+':8000/');
+}, "https_port_8000");
+
+async_test(function(t) {
+  testSharedWorkerHelper(t, 'http://'+location.hostname+':8012/');
+}, "http_post_8012");
+
+async_test(function(t) {
+  testSharedWorkerHelper(t,'javascript:""');
+}, "javascript_url");
+
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/sample_worker/worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/sample_worker/worker.js
new file mode 100644
index 0000000..19bbea58
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/sample_worker/worker.js
@@ -0,0 +1 @@
+onmessage = function(event) { postMessage(event.data); }
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/terminate.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/terminate.html
new file mode 100644
index 0000000..52f9707d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/terminate.html
@@ -0,0 +1,44 @@
+<!--
+(function f() {
+  postMessage(1);
+  setTimeout(f, 0);
+})();
+/*
+-->
+<!doctype html>
+<title>terminate()</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker-terminate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+  var worker = new Worker('#');
+  var i = 0;
+  var expected;
+
+  worker.onmessage = t.step_func(function() {
+    i++;
+  });
+
+  setTimeout(t.step_func(function() {
+    expected = i;
+    start_time = Date.now();
+    //Hang the main thread for a bit to give the worker the chance to post some more messages
+    while(Date.now() - start_time < 500) {
+      //pass
+    }
+    worker.terminate();
+
+    setTimeout(t.step_func(function() {
+      assert_equals(i, expected);
+      t.done();
+    }), 100);
+
+  }), 100);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/undefined b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/undefined
new file mode 100644
index 0000000..bc7f482
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/undefined
@@ -0,0 +1 @@
+postMessage('undefined');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unexpected-self-properties.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unexpected-self-properties.worker.js
new file mode 100644
index 0000000..aba85011
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unexpected-self-properties.worker.js
@@ -0,0 +1,11 @@
+importScripts("/resources/testharness.js");
+
+var unexpected = ['open', 'print', 'stop', 'getComputedStyle', 'getSelection', 'releaseEvents', 'captureEvents', 'alert', 'confirm', 'prompt', 'addEventStream', 'removeEventStream', 'back', 'forward', 'attachEvent', 'detachEvent', 'navigate', 'DOMParser', 'XMLSerializer', 'XPathEvaluator', 'XSLTProcessor', 'opera', 'Image', 'Option', 'frames', 'Audio', 'SVGUnitTypes', 'SVGZoomAndPan', 'java', 'netscape', 'sun', 'Packages', 'ByteArray', 'closed', 'defaultStatus', 'document', 'event', 'frameElement', 'history', 'innerHeight', 'innerWidth', 'name', 'opener', 'outerHeight', 'outerWidth', 'pageXOffset', 'pageYOffset', 'parent', 'screen', 'screenLeft', 'screenTop', 'screenX', 'screenY', 'status', 'top', 'window', 'length']; // iterated window in opera and removed expected ones
+for (var i = 0; i < unexpected.length; ++i) {
+  var property = unexpected[i];
+  test(function() {
+    assert_false(property in self);
+  }, "existence of " + property);
+}
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unresolvable-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unresolvable-url.html
new file mode 100644
index 0000000..8c04b00
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/unresolvable-url.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>unresolvable url</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+  assert_throws("SyntaxError", function() { new Worker('http://invalid url/'); });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/use-base-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/use-base-url.html
new file mode 100644
index 0000000..94ce2a7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/constructors/Worker/use-base-url.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Use the document base url when resolving worker URLs</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<base href="/workers/constructors/Worker/sample_worker/">
+<script>
+    async_test(function(t) {
+        var worker = new Worker('worker.js');
+        var data = "foo";
+        worker.postMessage(data);
+        worker.onmessage = t.step_func_done(function(event) {
+            assert_equals(event.data, data, "event.data does not match expected data");
+        });
+        worker.onerror = t.unreached_func("received error event");
+    }, "Use the document base url when resolving worker URLs");
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url-shared.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url-shared.html
new file mode 100644
index 0000000..64aacf2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url-shared.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>data URL shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(t => {
+  var worker = new SharedWorker("data:,onconnect = (e) => { fetch('/').then(() => e.ports[0].postMessage('fail'), () => e.ports[0].postMessage('pass')) }") // not same-origin
+  worker.port.onmessage = t.step_func_done(e => {
+    assert_equals(e.data, "pass")
+  })
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url.html
new file mode 100644
index 0000000..c212a69
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/data-url.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>data URL worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(t => {
+  var worker = new Worker("data:,fetch('/').then(() => self.postMessage('fail'), () => self.postMessage('pass'))") // not same-origin
+  worker.onmessage = t.step_func_done(e => {
+    assert_equals(e.data, "pass")
+  })
+})
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.idl b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.idl
new file mode 100644
index 0000000..228efba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.idl
@@ -0,0 +1,106 @@
+// -----------------------------------------------------------------------------
+// DOM
+// -----------------------------------------------------------------------------
+[Exposed=(Window,Worker)]
+interface EventTarget {
+  void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+  void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+  boolean dispatchEvent(Event event);
+};
+
+callback interface EventListener {
+  void handleEvent(Event event);
+};
+
+// -----------------------------------------------------------------------------
+// HTML
+// -----------------------------------------------------------------------------
+[TreatNonCallableAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+
+[TreatNonCallableAsNull]
+callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error);
+typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
+
+[Exposed=Worker]
+interface WorkerGlobalScope : EventTarget {
+  readonly attribute WorkerGlobalScope self;
+  readonly attribute WorkerLocation location;
+
+  void close();
+  attribute OnErrorEventHandler onerror;
+  attribute EventHandler onlanguagechange;
+  attribute EventHandler onoffline;
+  attribute EventHandler ononline;
+};
+
+[Global=(Worker,DedicatedWorker),Exposed=DedicatedWorker]
+/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
+  void postMessage(any message, optional sequence<Transferable> transfer);
+  attribute EventHandler onmessage;
+};
+
+//[Exposed=Worker]
+partial interface WorkerGlobalScope { // not obsolete
+  void importScripts(DOMString... urls);
+  readonly attribute WorkerNavigator navigator;
+};
+WorkerGlobalScope implements WindowTimers;
+WorkerGlobalScope implements WindowBase64;
+
+[NoInterfaceObject, Exposed=(Window,Worker)]
+interface WindowTimers {
+  long setTimeout(Function handler, optional long timeout = 0, any... arguments);
+  long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
+  void clearTimeout(optional long handle = 0);
+  long setInterval(Function handler, optional long timeout = 0, any... arguments);
+  long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
+  void clearInterval(optional long handle = 0);
+};
+
+[NoInterfaceObject, Exposed=(Window,Worker)]
+interface WindowBase64 {
+  DOMString btoa(DOMString btoa);
+  DOMString atob(DOMString atob);
+};
+
+[Exposed=Worker]
+interface WorkerNavigator {};
+WorkerNavigator implements NavigatorID;
+WorkerNavigator implements NavigatorLanguage;
+WorkerNavigator implements NavigatorOnLine;
+
+[NoInterfaceObject, Exposed=(Window,Worker)]
+interface NavigatorID {
+  readonly attribute DOMString appCodeName; // constant "Mozilla"
+  readonly attribute DOMString appName;
+  readonly attribute DOMString appVersion;
+  readonly attribute DOMString platform;
+  readonly attribute DOMString product; // constant "Gecko"
+  readonly attribute DOMString userAgent;
+};
+
+[NoInterfaceObject, Exposed=(Window,Worker)]
+interface NavigatorLanguage {
+  readonly attribute DOMString? language;
+  readonly attribute DOMString[] languages;
+};
+
+[NoInterfaceObject, Exposed=(Window,Worker)]
+interface NavigatorOnLine {
+  readonly attribute boolean onLine;
+};
+
+[Exposed=Worker]
+interface WorkerLocation {
+  stringifier readonly attribute USVString href;
+  readonly attribute USVString origin;
+  readonly attribute USVString protocol;
+  readonly attribute USVString host;
+  readonly attribute USVString hostname;
+  readonly attribute USVString port;
+  readonly attribute USVString pathname;
+  readonly attribute USVString search;
+  readonly attribute USVString hash;
+};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.worker.js
new file mode 100644
index 0000000..f07669b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces.worker.js
@@ -0,0 +1,20 @@
+"use strict";
+
+importScripts("/resources/testharness.js");
+importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js");
+
+var request = new XMLHttpRequest();
+request.onload = function() {
+  var idlArray = new IdlArray();
+  var idls = request.responseText;
+  idlArray.add_idls(idls);
+  idlArray.add_objects({
+    DedicatedWorkerGlobalScope: ['self'],
+    WorkerNavigator: ['self.navigator'],
+    WorkerLocation: ['self.location'],
+  });
+  idlArray.test();
+  done();
+};
+request.open("GET", "interfaces.idl");
+request.send();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js
new file mode 100644
index 0000000..954c46c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js
@@ -0,0 +1,23 @@
+importScripts("/resources/testharness.js");
+
+test(function(t) {
+    var i = 0;
+    addEventListener("message", function listener(evt) {
+        t.step(function() {
+            ++i;
+            removeEventListener("message", listener, true);
+        });
+    }, true);
+    self.dispatchEvent(new Event("message"));
+    self.dispatchEvent(new Event("message"));
+    assert_equals(i, 1);
+}, "removeEventListener");
+
+test(function() {
+    addEventListener("message", this.step_func(function(evt) {
+        assert_equals(evt.target, self);
+    }), true);
+    self.dispatchEvent(new Event("message"));
+}, "target");
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js
new file mode 100644
index 0000000..6f285ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js
@@ -0,0 +1,40 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+  self.onmessage = 1;
+  assert_equals(self.onmessage, null,
+                "attribute should return null after being set to a primitive");
+}, "Setting onmessage to 1");
+
+test(function() {
+  var object = {
+    handleEvent: this.unreached_func()
+  };
+  self.onmessage = object;
+  assert_equals(self.onmessage, object,
+                "attribute should return the object it was set to.");
+
+  self.dispatchEvent(new Event("message"));
+}, "Setting onmessage to an object");
+
+test(function() {
+  var triggered = false;
+  var f = function(e) { triggered = true; };
+  self.onmessage = f;
+  assert_equals(self.onmessage, f,
+                "attribute should return the function it was set to.");
+
+  self.dispatchEvent(new Event("message"));
+  assert_true(triggered, "event handler should have been triggered");
+}, "Setting onmessage to a function");
+
+
+test(function() {
+  assert_not_equals(self.onmessage, null,
+                    "attribute should not return null after being set to a function");
+  self.onmessage = 1;
+  assert_equals(self.onmessage, null,
+                "attribute should return null after being set to a primitive");
+}, "Setting onmessage to 1 (again)");
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html
new file mode 100644
index 0000000..7ae4b07
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html
@@ -0,0 +1,25 @@
+<!--
+onmessage = function(e) {
+  postMessage(e.ports instanceof Array && e.ports.length === 0);
+}
+/*
+-->
+<!doctype html>
+<title>e.ports in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new Worker('#');
+  worker.postMessage(1);
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html
new file mode 100644
index 0000000..2041301
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html
@@ -0,0 +1,39 @@
+<!--
+onmessage = function(e) {
+  function processPixels(imagedata) {
+    var pixeldata = imagedata.data;
+    for (var i = 0; i < pixeldata.length; i = i+4) {
+      pixeldata[i] = 128;
+    }
+    postMessage(imagedata);
+  }
+  processPixels(e.data[0]);
+}
+
+/*
+-->
+<!doctype html>
+<title>posting an imagedata (from a cloned canvas) in an array</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new Worker('#');
+  var canvas = document.createElement('canvas');
+  var clone = canvas.cloneNode(true);
+  var ctx = clone.getContext('2d');
+  var imagedata = ctx.getImageData(0, 0, 300, 150);
+  worker.postMessage([imagedata]);
+  worker.onmessage = this.step_func(function(e) {
+    var pixeldata = e.data.data;
+    for (var i = 0; i < pixeldata.length; i++) {
+      assert_equals(pixeldata[i], (i % 4 == 0) ? 128 : 0);
+    }
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html
new file mode 100644
index 0000000..91ec632
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>'message' event properties</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-dedicatedworkerglobalscope-postmessage">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+async_test("Properties of the 'message' event").step(function() {
+  var worker = new Worker("message-event.js");
+  worker.onmessage = this.step_func_done(function (evt) {
+    assert_class_string(evt, "MessageEvent");
+    assert_equals(evt.type, "message");
+    assert_false(evt.bubbles, "bubbles should be false");
+    assert_false(evt.cancelable, "cancelable should be false");
+    assert_equals(evt.data, "test");
+    assert_equals(evt.origin, "", "origin");
+    assert_equals(evt.lastEventId, "", "lastEventId");
+    assert_equals(evt.source, null, "source");
+    assert_array_equals(evt.ports, [], "ports");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js
new file mode 100644
index 0000000..54a2500
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js
@@ -0,0 +1 @@
+postMessage("test");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js
new file mode 100644
index 0000000..52125169
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js
@@ -0,0 +1,8 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+  var rv = postMessage(1);
+  assert_equals(rv, undefined);
+}, "return value of postMessage");
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html
new file mode 100644
index 0000000..df4c9f83
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html
@@ -0,0 +1,26 @@
+<!--
+try {
+  postMessage(false, [null]);
+} catch(e) {
+  postMessage(e instanceof TypeError);
+}
+/*
+-->
+<!doctype html>
+<title>Using [null] in postMessage's second argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html
new file mode 100644
index 0000000..e81a56ba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html
@@ -0,0 +1,25 @@
+<!--
+try {
+  postMessage(1, null);
+} catch(e) {
+  postMessage(e instanceof TypeError);
+}
+/*
+-->
+<!doctype html>
+<title>Using null in postMessage's second argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html
new file mode 100644
index 0000000..7d01eba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html
@@ -0,0 +1,25 @@
+<!--
+try {
+  postMessage(1, undefined);
+} catch(e) {
+  postMessage(''+e);
+}
+/*
+-->
+<!doctype html>
+<title>Using undefined in postMessage's second argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 1);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html
new file mode 100644
index 0000000..d1a3f0f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html
@@ -0,0 +1,24 @@
+<!--
+var x = postMessage;
+postMessage = 1;
+x(postMessage == 1);
+
+/*
+-->
+<!doctype html>
+<title>setting postMessage</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html
new file mode 100644
index 0000000..c0ded6a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html
@@ -0,0 +1,30 @@
+<!--
+onmessage = function(e) {
+  var imagedata = e.data;
+  imagedata.data[0] = 128;
+  postMessage(imagedata);
+}
+
+/*
+-->
+<!doctype html>
+<title>structured clone of ImageData</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+  var worker = new Worker('#');
+  var ctx = document.createElement('canvas').getContext('2d');
+  var imagedata = ctx.getImageData(0, 0, 300, 150);
+  worker.postMessage(imagedata);
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(''+e.data, '[object ImageData]');
+    assert_equals(e.data.data[0], 128);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html
new file mode 100644
index 0000000..ba357421f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html
@@ -0,0 +1,58 @@
+<!--
+var err = new Error('foo');
+var date = new Date();
+// commented out bits are either tested elsewhere or not supported yet. or uncloneable.
+var tests = [undefined, null, false, true, 1, NaN, Infinity, 'foo', date, /foo/, /* ImageData, File, FileData, FileList,*/ null/*self*/,
+              [undefined, null, false, true, 1, NaN, Infinity, 'foo', /*date, /foo/,*/ null/*self*/, /*[], {},*/ null/*err*/],
+              {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', /*i:date, j:/foo/,*/ k:null/*self*/, /*l:[], m:{},*/ n:null/*err*/},
+            null/*err*/];
+for (var i = 0; i < tests.length; ++i) {
+  try {
+    postMessage(tests[i]);
+  } catch(e) {
+    postMessage(''+e);
+  }
+}
+/*
+-->
+<!doctype html>
+<title>structured clone of message</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var wrapper_test = async_test();
+var tests = [
+      {test:async_test('undefined'), check:function(e) { assert_equals(e.data, undefined); }},
+      {test:async_test('null'), check:function(e) { assert_equals(e.data, null); }},
+      {test:async_test('false'), check:function(e) { assert_false(e.data); }},
+      {test:async_test('true'), check:function(e) { assert_true(e.data); }},
+      {test:async_test('1'), check:function(e) { assert_equals(e.data, 1); }},
+      {test:async_test('NaN'), check:function(e) { assert_equals(e.data, NaN); }},
+      {test:async_test('Infinity'), check:function(e) { assert_equals(e.data, Infinity); }},
+      {test:async_test('string'), check:function(e) { assert_equals(e.data, 'foo'); }},
+      {test:async_test('date'), check:function(e) { assert_equals(e.data instanceof Date, true); }},
+      {test:async_test('regexp'), check:function(e) { assert_equals('' + e.data, '/foo/'); assert_equals(e.data instanceof RegExp, true, 'e.data instanceof RegExp'); }},
+      {test:async_test('self'), check:function(e) { assert_equals(e.data, null); }},
+      {test:async_test('array'), check:function(e) { assert_array_equals(e.data, [undefined, null, false, true, 1, NaN, Infinity, 'foo', null, null]); }},
+      {test:async_test('object'), check:function(e) { assert_object_equals(e.data, {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', k:null, n:null}); }},
+      {test:async_test('error'), check:function(e) { assert_equals(e.data, null, 'new Error()'); }},
+      {test:wrapper_test, check:function(e) { assert_unreached(); }}
+];
+// make wrapper_test pass after 500ms
+setTimeout(tests[tests.length-1].test.step_func(function() {
+  this.done();
+}), 500);
+
+wrapper_test.step(function() {
+  var worker = new Worker('#');
+  var i = 0;
+  worker.onmessage = function(e) {
+    tests[i].test.step(function() { tests[i].check(e); this.done(); });
+    i++;
+  };
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/getting.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/getting.html
new file mode 100644
index 0000000..bfe81a8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/getting.html
@@ -0,0 +1,34 @@
+<!--
+addEventListener('connect', function(e) {
+  var passed;
+  switch (location.hash) {
+    case '#1': passed = name == ''; break;
+    case '#2': passed = name == 'a'; break;
+    case '#3': passed = name == '0'; break;
+  }
+  e.ports[0].postMessage(passed);
+}, false);
+/*
+-->
+<!doctype html>
+<title>getting name</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var tests = [['#1', ''], ['#2', 'a'], ['#3', -0]];
+tests.forEach(function(t) {
+  async_test(function() {
+    var w = new SharedWorker(t[0], t[1]);
+    w.port.onmessage = this.step_func(function(e) {
+      assert_true(e.data);
+      this.done();
+    });
+  });
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html
new file mode 100644
index 0000000..39cdf7b6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/name/setting.html
@@ -0,0 +1,25 @@
+<!--
+addEventListener('connect', function(e) {
+  name = 1;
+  e.ports[0].postMessage(name);
+}, false);
+/*
+-->
+<!doctype html>
+<title>setting name</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var w1 = new SharedWorker('#1', 'x');
+  w1.port.addEventListener('message', this.step_func(function(e) {
+    assert_equals(e.data, 'x');
+    this.done();
+  }), false);
+  w1.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html
new file mode 100644
index 0000000..2ad155b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/SharedWorkerGlobalScope/onconnect.html
@@ -0,0 +1,39 @@
+<!--
+var results = [];
+try {
+  self.onconnect = 1;
+  results.push(String(onconnect));
+} catch(e) {
+  results.push(''+e);
+}
+try {
+  self.onconnect = {handleEvent:function(){}};
+  results.push(String(onconnect));
+} catch(e) {
+  results.push(''+e);
+}
+var f = function(e) {
+  results.push(e.data);
+  e.ports[0].postMessage(results);
+};
+onconnect = f;
+results.push(typeof onconnect);
+/*
+-->
+<!doctype html>
+<title>onconnect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var w1 = new SharedWorker('#', '');
+  w1.port.addEventListener('message', this.step_func(function(e) {
+    assert_array_equals(e.data, ['null', 'null', 'function', '']);
+  }), false);
+  w1.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/incoming-message.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/incoming-message.html
new file mode 100644
index 0000000..d656956
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/incoming-message.html
@@ -0,0 +1,29 @@
+<!--
+onmessage = function(e) {
+  postMessage(1);
+  throw new Error();
+}
+close();
+/*
+-->
+<!doctype html>
+<title>close() and incoming message</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var worker = new Worker('#');
+worker.onmessage = function(e) {
+  assert_unreached("Got message");
+};
+worker.onerror = function(e) {
+  assert_unreached("Got error");
+};
+worker.postMessage(1);
+setTimeout(done, 2000);
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/sending-messages.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/sending-messages.html
new file mode 100644
index 0000000..983c422
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/sending-messages.html
@@ -0,0 +1,27 @@
+<!--
+postMessage(1);
+close();
+postMessage(2);
+/*
+-->
+<!doctype html>
+<title>close() and sending messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  var i = 0;
+  worker.onmessage = this.step_func(function(e) {
+    i++;
+    assert_equals(e.data, i);
+    if (i == 2) {
+      this.done();
+    }
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setInterval.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setInterval.html
new file mode 100644
index 0000000..1d7d178d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setInterval.html
@@ -0,0 +1,34 @@
+<!--
+var interval1 = setInterval(function() {
+  clearInterval(interval1);
+  postMessage(1);
+  throw new Error();
+}, 10);
+close();
+var interval2 = setInterval(function() {
+  clearInterval(interval2);
+  postMessage(1);
+  throw new Error();
+}, 10);
+/*
+-->
+<!doctype html>
+<title>close() and setInterval</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var worker = new Worker('#');
+worker.onmessage = function(e) {
+  assert_unreached("Got message");
+};
+worker.onerror = function(e) {
+  assert_unreached("Got error");
+};
+setTimeout(done, 2000);
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setTimeout.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setTimeout.html
new file mode 100644
index 0000000..c2fa10df
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/close/setTimeout.html
@@ -0,0 +1,28 @@
+<!--
+function x() {
+  postMessage(1);
+  throw new Error();
+}
+setTimeout(x, 0);
+close();
+setTimeout(x, 0);
+/*
+-->
+<!doctype html>
+<title>close() and setTimeout</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var worker = new Worker('#');
+worker.onmessage = function(e) {
+  assert_unreached("Got message");
+};
+worker.onerror = function(e) {
+  assert_unreached("Got error");
+};
+setTimeout(done, 2000);
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py
new file mode 100644
index 0000000..eb1599a5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py
@@ -0,0 +1,3 @@
+def main(request, response):
+    response.status = 302
+    response.headers.append("Location", "post-location-members.js?a")
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/members.html
new file mode 100644
index 0000000..31ddf37
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/members.html
@@ -0,0 +1,31 @@
+<!--
+postMessage([null, location.href, location.protocol, location.host,
+             location.hostname, location.port, location.pathname,
+             location.search, location.hash]);
+/*
+-->
+<!doctype html>
+<title>members of WorkerLocation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data[0], null);
+    assert_equals(e.data[1], location.href + '#', 'href');
+    assert_equals(e.data[2], location.protocol, 'protocol');
+    assert_equals(e.data[3], location.host, 'host');
+    assert_equals(e.data[4], location.hostname, 'hostname');
+    assert_equals(e.data[5], location.port, 'port');
+    assert_equals(e.data[6], location.pathname, 'pathname');
+    assert_equals(e.data[7], location.search, 'search');
+    assert_equals(e.data[8], '', 'hash');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/post-location-members.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/post-location-members.js
new file mode 100644
index 0000000..e850b76
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/post-location-members.js
@@ -0,0 +1,8 @@
+postMessage([location.href,
+             location.protocol,
+             location.host,
+             location.hostname,
+             location.port,
+             location.pathname,
+             location.search,
+             location.hash]);
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html
new file mode 100644
index 0000000..2fd16a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/redirect.html
@@ -0,0 +1,28 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>location with a worker in separate file that redirects</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('helper-redirect.py?fail');
+  worker.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data[0], location.href.replace(/\/[^\/]+$/, '/post-location-members.js?a'));
+    assert_equals(e.data[1], location.protocol);
+    assert_equals(e.data[2], location.host);
+    assert_equals(e.data[3], location.hostname);
+    assert_equals(e.data[4], location.port);
+    assert_equals(e.data[5], location.pathname.replace(/\/[^\/]+$/, '/post-location-members.js'));
+    assert_equals(e.data[6], '?a');
+    assert_equals(e.data[7], '');
+  });
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html
new file mode 100644
index 0000000..40559c16
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(location === location);
+/*
+-->
+<!doctype html>
+<title>location === location</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/setting-members.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/setting-members.html
new file mode 100644
index 0000000..d2f470f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/setting-members.html
@@ -0,0 +1,43 @@
+<!--
+var exceptions = [];
+try { location.href = 1; } catch(e) { exceptions.push('href'); }
+try { location.protocol = 1; } catch(e) { exceptions.push('protocol'); }
+try { location.host = 1; } catch(e) { exceptions.push('host'); }
+try { location.hostname = 1; } catch(e) { exceptions.push('hostname');}
+try { location.port = 1; } catch(e) { exceptions.push('port'); }
+try { location.pathname = 1; } catch(e) { exceptions.push('pathname'); }
+try { location.search = 1; } catch(e) { exceptions.push('search'); }
+try { location.hash = 1; } catch(e) { exceptions.push('hash'); }
+
+postMessage([null, location.href, location.protocol, location.host,
+             location.hostname, location.port, location.pathname,
+             location.search, location.hash, exceptions]);
+/*
+-->
+<!doctype html>
+<title>setting members of WorkerLocation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data[0], null);
+    assert_equals(e.data[1], location.href + '#', 'href');
+    assert_equals(e.data[2], location.protocol, 'protocol');
+    assert_equals(e.data[3], location.host, 'host');
+    assert_equals(e.data[4], location.hostname, 'hostname');
+    assert_equals(e.data[5], location.port, 'port');
+    assert_equals(e.data[6], location.pathname, 'pathname');
+    assert_equals(e.data[7], location.search, 'search');
+    assert_equals(e.data[8], '', 'hash');
+    assert_array_equals(e.data[9], [], 'number of exceptions');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html
new file mode 100644
index 0000000..ac8e64d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html
@@ -0,0 +1,28 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>location with a worker in separate file</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('post-location-members.js?a#b?c');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data[0], location.href.replace(/\/[^\/]+$/, '/post-location-members.js?a#b?c'));
+    assert_equals(e.data[1], location.protocol);
+    assert_equals(e.data[2], location.host);
+    assert_equals(e.data[3], location.hostname);
+    assert_equals(e.data[4], location.port);
+    assert_equals(e.data[5], location.pathname.replace(/\/[^\/]+$/, '/post-location-members.js'));
+    assert_equals(e.data[6], '?a');
+    assert_equals(e.data[7], '#b?c');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html
new file mode 100644
index 0000000..4b5af71
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html
@@ -0,0 +1,32 @@
+<!--
+onerror = function(a, b, c, d) {
+  y(); // the error is "not handled"
+}
+function x() {
+  y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "not handled" with an error in the onerror function</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onerror = this.step_func(function(e) {
+    assert_true(e instanceof ErrorEvent, 'e instanceof ErrorEvent');
+    assert_equals(typeof e.message, 'string', 'typeof e.message');
+    assert_equals(e.filename, document.URL+'#', 'e.filename');
+    assert_equals(typeof e.lineno, 'number', 'typeof e.lineno');
+    assert_equals(typeof e.colno, 'number', 'typeof e.column');
+    e.preventDefault(); // "handled"
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html
new file mode 100644
index 0000000..56fee8e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/handled.html
@@ -0,0 +1,36 @@
+<!--
+onerror = function(a, b, c, d) {
+  postMessage([a, b, c, d]);
+  return true; // the error is "handled"
+}
+function x() {
+  y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "handled"</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(typeof e.data[0], 'string', 'first argument');
+    assert_equals(e.data[1], document.URL+'#', 'second argument');
+    assert_equals(typeof e.data[2], 'number', 'third argument');
+    assert_equals(typeof e.data[3], 'number', 'fourth argument');
+    setTimeout(this.step_func(function() {
+      this.done();
+    }), 100);
+  });
+  worker.onerror = this.step_func(function(e) {
+    assert_unreached();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html
new file mode 100644
index 0000000..f6107ad
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html
@@ -0,0 +1,32 @@
+<!--
+onerror = function(a, b, c, d) {
+  return false; // the error is "not handled"
+}
+function x() {
+  y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "not handled"</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onerror = this.step_func(function(e) {
+    assert_true(e instanceof ErrorEvent, 'e instanceof ErrorEvent');
+    assert_equals(typeof e.message, 'string', 'typeof e.message');
+    assert_equals(e.filename, document.URL+'#', 'e.filename');
+    assert_equals(typeof e.lineno, 'number', 'typeof e.lineno');
+    assert_equals(typeof e.colno, 'number', 'typeof e.column');
+    e.preventDefault(); // "handled"
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html
new file mode 100644
index 0000000..b6a61e2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html
@@ -0,0 +1,31 @@
+<!--
+function x() {
+  y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "not handled" with only window.onerror defined</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup({
+  allow_uncaught_exception: true,
+});
+async_test(function() {
+  var worker = new Worker('#');
+  window.onerror = this.step_func(function(a, b, c, d) {
+    assert_equals(typeof a, 'string', 'first argument');
+    assert_equals(b, document.URL+'#', 'second argument');
+    assert_equals(typeof c, 'number', 'third argument');
+    assert_equals(typeof d, 'number', 'fourth argument');
+    this.done();
+    return true; // "handled"
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/self.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/self.html
new file mode 100644
index 0000000..39c2c36
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerGlobalScope/self.html
@@ -0,0 +1,39 @@
+<!--
+var results = [];
+function check(func, msg) {
+  try {
+    results.push([func(), msg]);
+  } catch(ex) {
+    results.push([String(ex), msg]);
+  }
+}
+check(function() { return self === self; }, 'self === self');
+check(function() { return self instanceof WorkerGlobalScope; }, 'self instanceof WorkerGlobalScope');
+check(function() { return 'self' in self; }, '\'self\' in self');
+check(function() {
+  var x = self;
+  self = 1;
+  return x === self;
+}, 'self = 1');
+postMessage(results);
+/*
+-->
+<!doctype html>
+<title>self</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    for (var i = 0; i < e.data.length; ++i) {
+      assert_true(e.data[i][0], e.data[i][1]);
+    }
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/001.html
new file mode 100644
index 0000000..a808975
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/001.html
@@ -0,0 +1,23 @@
+<!--
+setTimeout(function() { postMessage(1) }, 10);
+/*
+-->
+<!doctype html>
+<title>setTimeout</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 1);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/002.html
new file mode 100644
index 0000000..06685a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/002.html
@@ -0,0 +1,21 @@
+<!--
+var t = setTimeout(function() { postMessage(1); }, 10);
+clearTimeout(t);
+/*
+-->
+<!doctype html>
+<title>clearTimeout</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  var gotMessage = false;
+  worker.onmessage = function() { gotMessage = true; };
+  setTimeout(this.step_func(function() { assert_false(gotMessage); this.done(); }), 100);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/003.html
new file mode 100644
index 0000000..942f139
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/003.html
@@ -0,0 +1,22 @@
+<!--
+setInterval(function() { postMessage(1); }, 10);
+/*
+-->
+<!doctype html>
+<title>setInterval</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 1);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/004.html
new file mode 100644
index 0000000..5548eec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/WindowTimers/004.html
@@ -0,0 +1,23 @@
+<!--
+var t = setInterval(function() {
+  postMessage(1);
+}, 10);
+clearInterval(t);
+/*
+-->
+<!doctype html>
+<title>clearInterval</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  var i = 0;
+  worker.onmessage = function() { i++; }
+  setTimeout(this.step_func(function() { assert_equals(i, 0); this.done(); }), 100);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/001.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/001.worker.js
new file mode 100644
index 0000000..aa86c8ef
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/001.worker.js
@@ -0,0 +1,7 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+  importScripts();
+});
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker.js
new file mode 100644
index 0000000..2cecbcb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/002.worker.js
@@ -0,0 +1,11 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+  var ran = false;
+  assert_throws("SyntaxError", function() {
+    importScripts('data:text/javascript,ran=true','http://foo bar');
+  });
+  assert_false(ran, 'first argument to importScripts ran');
+});
+
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/003.html
new file mode 100644
index 0000000..7ff30ae2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/003.html
@@ -0,0 +1,28 @@
+<!--
+var x = 'a';
+try {
+  importScripts('data:text/javascript,x+="b"',
+                'data:text/javascript,x+="c"');
+} catch(e) {
+  x += "d"
+}
+postMessage(x);
+/*
+-->
+<!doctype html>
+<title>importScripts running scripts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, "abc");
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html
new file mode 100644
index 0000000..2d39d3ce
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/004.html
@@ -0,0 +1,34 @@
+<!--
+var x = '';
+var exception;
+try {
+  importScripts('data:text/javascript,x+="first script successful. "',
+                'data:text/javascript,x+="FAIL (second script). "; for(;) break;', // doesn't compile
+                'data:text/javascript,x+="FAIL (third script)"');
+} catch(ex) {
+  if (ex instanceof SyntaxError)
+    exception = true;
+  else
+    exception = String(ex);
+}
+postMessage([x, exception]);
+/*
+-->
+<!doctype html>
+<title>importScripts broken script</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data[0], "first script successful. ");
+    assert_true(e.data[1], 'expected SyntaxError');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/005.html
new file mode 100644
index 0000000..f8abe14
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/005.html
@@ -0,0 +1,30 @@
+<!--
+var x;
+var y;
+try {
+  importScripts('data:text/javascript,x={',
+                'data:text/javascript,}');
+} catch(e) {
+  y = true;
+}
+postMessage([x, y]);
+/*
+-->
+<!doctype html>
+<title>importScripts separate scripts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data[0], undefined);
+    assert_true(e.data[1]);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html
new file mode 100644
index 0000000..06aea96
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/006.html
@@ -0,0 +1,33 @@
+<!--
+var x;
+var y;
+var z;
+try {
+  importScripts('data:text/javascript,x=1',
+                'data:text/javascript,throw 2',
+                'data:text/javascript,z=3');
+} catch(e) {
+  y = e;
+}
+postMessage([x, y, z]);
+/*
+-->
+<!doctype html>
+<title>importScripts uncaught exception</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data[0], 1);
+    assert_equals(e.data[1], 2);
+    assert_equals(e.data[2], undefined);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/007.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/007.html
new file mode 100644
index 0000000..128fb1b6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/007.html
@@ -0,0 +1,25 @@
+<!--
+importScripts('data:text/javascript,postMessage(1)');
+postMessage(2);
+/*
+-->
+<!doctype html>
+<title>postMessage in importScripts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  var i = 0;
+  worker.onmessage = this.step_func(function(e) {
+    i++;
+    assert_equals(e.data, i);
+    if (i == 2)
+      this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/008.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/008.html
new file mode 100644
index 0000000..07b800eb
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/008.html
@@ -0,0 +1,23 @@
+<!--
+var log = postMessage;
+importScripts('data:text/javascript,function run() { log(true) }');
+run();
+/*
+-->
+<!doctype html>
+<title>variables and functions crossing importScripts boundary</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/009.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/009.html
new file mode 100644
index 0000000..95d3839d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/009.html
@@ -0,0 +1,29 @@
+<!--
+var log = postMessage;
+importScripts('data:text/javascript,function run() { for(var i = 0; i < 1000; ++i) { if (i == 500) log(true); } return 1; }');
+postMessage(run());
+/*
+-->
+<!doctype html>
+<title>variables and functions crossing importScripts boundary, take 2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  var i = 0;
+  worker.onmessage = this.step_func(function(e) {
+    i++;
+    if (i == 1) {
+      assert_true(e.data);
+    } else {
+      assert_equals(e.data, 1);
+      this.done();
+    }
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/010.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/010.html
new file mode 100644
index 0000000..9c76e7d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/010.html
@@ -0,0 +1,34 @@
+<!--
+// prevent recursion
+if ('beenThere' in self) {
+  throw 'undefined stringified to the empty string';
+}
+beenThere = true;
+try {
+  importScripts(undefined);
+  postMessage(got);
+} catch(ex) {
+  postMessage(String(ex));
+}
+/*
+-->
+<!doctype html>
+<title>importScripts(undefined)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 'undefined');
+    this.done();
+  })
+  worker.onerror = this.step_func(function(e) {
+    assert_unreached(e.message);
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/011.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/011.html
new file mode 100644
index 0000000..46499318
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/011.html
@@ -0,0 +1,34 @@
+<!--
+// prevent recursion
+if ('beenThere' in self) {
+  throw 'null stringified to the empty string';
+}
+beenThere = true;
+try {
+  importScripts(null);
+  postMessage(got);
+} catch(ex) {
+  postMessage(String(ex));
+}
+/*
+-->
+<!doctype html>
+<title>importScripts(null)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 'null');
+    this.done();
+  });
+  worker.onerror = this.step_func(function(e) {
+    assert_unreached(e.message);
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/012.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/012.html
new file mode 100644
index 0000000..f7622bd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/012.html
@@ -0,0 +1,34 @@
+<!--
+// prevent recursion
+if ('beenThere' in self) {
+  throw '1 stringified to the empty string';
+}
+beenThere = true;
+try {
+  importScripts(1);
+  postMessage(got);
+} catch(ex) {
+  postMessage(String(ex));
+}
+/*
+-->
+<!doctype html>
+<title>importScripts(1)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '1');
+    this.done();
+  });
+  worker.onerror = this.step_func(function(e) {
+    assert_unreached(e.message);
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/1 b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/1
new file mode 100644
index 0000000..18cea4f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/1
@@ -0,0 +1 @@
+var got = '1';
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/null b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/null
new file mode 100644
index 0000000..8e54b66c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/null
@@ -0,0 +1 @@
+var got = 'null';
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/undefined b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/undefined
new file mode 100644
index 0000000..f99ba4b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/importScripts/undefined
@@ -0,0 +1 @@
+var got = 'undefined';
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/002.html
new file mode 100644
index 0000000..d3aa2ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/002.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.appName);
+/*
+-->
+<!doctype html>
+<title>navigator.appName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, navigator.appName);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/003.html
new file mode 100644
index 0000000..a2e5c948
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/003.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.appVersion);
+/*
+-->
+<!doctype html>
+<title>navigator.appVersion</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, navigator.appVersion);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/004.html
new file mode 100644
index 0000000..2231c4ab
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/004.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.platform);
+/*
+-->
+<!doctype html>
+<title>navigator.platform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, navigator.platform);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/005.html
new file mode 100644
index 0000000..b3d99588
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/005.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.userAgent);
+/*
+-->
+<!doctype html>
+<title>navigator.userAgent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, navigator.userAgent);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/006.html
new file mode 100644
index 0000000..c027d63
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/006.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.onLine);
+/*
+-->
+<!doctype html>
+<title>navigator.onLine</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, navigator.onLine);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/007.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/007.html
new file mode 100644
index 0000000..a6afc56
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/007.html
@@ -0,0 +1,30 @@
+<!--
+var log = [];
+var neverEncounteredValue = "This is not the value you are looking for.";
+for (x in navigator) {
+  // this should silently fail and not throw per webidl
+  navigator[x] = neverEncounteredValue;
+  if (navigator[x] === neverEncounteredValue)
+    log.push(x);
+}
+postMessage(log.join(', '));
+/*
+-->
+<!doctype html>
+<title>readonlyness of members of Navigator</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html
new file mode 100644
index 0000000..f1aa446c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/interfaces/WorkerUtils/navigator/language.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.language);
+/*
+-->
+<!doctype html>
+<title>navigator.language</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, navigator.language);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/nested_worker.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/nested_worker.worker.js
new file mode 100644
index 0000000..8848fa2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/nested_worker.worker.js
@@ -0,0 +1,11 @@
+importScripts("/resources/testharness.js");
+
+async_test(function() {
+    var worker1 = new Worker("support/WorkerBasic.js");
+    worker1.postMessage("ping");
+    worker1.onmessage = this.step_func_done(function(evt) {
+        assert_equals(evt.data, "Pass");
+        worker1.terminate();
+        done();
+    });
+}, "Nested worker");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/application-cache-dedicated.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/application-cache-dedicated.js
new file mode 100644
index 0000000..2318c2e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/application-cache-dedicated.js
@@ -0,0 +1 @@
+postMessage(1);
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/cache.manifest b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/cache.manifest
new file mode 100644
index 0000000..8d80e03
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/cache.manifest
@@ -0,0 +1,3 @@
+CACHE MANIFEST
+application-cache-dedicated.html
+application-cache-dedicated.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-nested.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-nested.js
new file mode 100644
index 0000000..137dd0a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-nested.js
@@ -0,0 +1,5 @@
+postMessage(1);
+var w = new Worker('infinite-nested.js');
+w.onmessage = function(e) {
+  postMessage(e.data);
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling-and-nested.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling-and-nested.js
new file mode 100644
index 0000000..cf7b794
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling-and-nested.js
@@ -0,0 +1,8 @@
+function createWorker() {
+  var worker = new Worker('infinite-nested.js?' + Math.random());
+  worker.onmessage = function(e) {
+    postMessage(e.data);
+    createWorker();
+  }
+}
+createWorker();
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling.js
new file mode 100644
index 0000000..6424f70
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/infinite-sibling.js
@@ -0,0 +1,8 @@
+function createWorker() {
+  var worker = new Worker('post-a-1.js?' + Math.random());
+  worker.onmessage = function(e) {
+    postMessage(e.data);
+    createWorker();
+  }
+}
+createWorker();
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/post-a-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/post-a-1.js
new file mode 100644
index 0000000..2318c2e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/non-automated/post-a-1.js
@@ -0,0 +1 @@
+postMessage(1);
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_DataCloneErr.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_DataCloneErr.htm
new file mode 100644
index 0000000..24093ce4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_DataCloneErr.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> postMessage() with WorkerNavigator </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var worker = new Worker("./support/WorkerDataCloneErr.js");
+  worker.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data, "Pass");
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port.htm
new file mode 100644
index 0000000..b1d7b84e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title> postMessage(): clone a port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var channelA = new MessageChannel();
+  var channelB = new MessageChannel();
+  var originalPort = channelB.port2;
+  channelA.port2.onmessage = t.step_func(function(e) {
+    assert_equals(e.data, "ports");
+    var clonedPort = e.ports[0];
+    assert_not_equals(clonedPort, originalPort, "new cloned port object should not equal to the original port!");
+    clonedPort.onmessage = t.step_func_done(function(e) {
+      assert_equals(e.data, "ping", "Data sent through remote port is received by the new cloned port");
+    });
+  });
+  channelA.port1.postMessage("ports", [channelB.port2]);
+  channelB.port1.postMessage("ping");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port_error.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port_error.htm
new file mode 100644
index 0000000..3001296
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_clone_port_error.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> postMessage(): cloning source port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+  var channel = new MessageChannel();
+  channel.port1.start();
+  assert_throws("DataCloneError", function() {
+    channel.port1.postMessage("ports", [channel.port1]);
+  });
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_event_properties.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_event_properties.htm
new file mode 100644
index 0000000..8122413
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_event_properties.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title> postMessage(): MessageEvent properties </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var channel = new MessageChannel();
+  var targetPort = channel.port2;
+  targetPort.start();
+  targetPort.addEventListener("message", t.step_func_done(function (evt) {
+    assert_class_string(evt, "MessageEvent");
+    assert_equals(evt.type, "message");
+    assert_false(evt.bubbles, "bubbles should be false");
+    assert_false(evt.cancelable, "cancelable should be false");
+    assert_equals(evt.data, "ping", "data");
+    assert_equals(evt.origin, "", "origin");
+    assert_equals(evt.lastEventId, "", "lastEventId");
+    assert_equals(evt.source, null, "source");
+    assert_array_equals(evt.ports, [], "ports");
+  }), true);
+  channel.port1.postMessage("ping");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_ports_readonly_array.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_ports_readonly_array.htm
new file mode 100644
index 0000000..5e2b905
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_ports_readonly_array.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> postMessage(): read-only ports array </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var channel = new MessageChannel();
+  var targetPort = channel.port2;
+  targetPort.start();
+  targetPort.addEventListener("message", t.step_func_done(function(e) {
+    var channel3 = new MessageChannel();
+    e.ports.push(channel3.port1);
+    e.ports.push(channel3.port1);
+    assert_equals(e.ports.length, 1, "ports is a read only array with length == 1.");
+  }), true);
+  var channel2 = new MessageChannel();
+  channel.port1.postMessage("ports", [channel2.port1]);
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_target_source.htm b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_target_source.htm
new file mode 100644
index 0000000..7d684916
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/postMessage_target_source.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title> postMessage(): target port and source port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var channel = new MessageChannel();
+  var source = channel.port1;
+  var target = channel.port2;
+  target.start();
+  target.addEventListener("message", t.step_func_done(function(e) {
+    assert_equals(e.target, target);
+    assert_not_equals(e.target, source);
+  }), true);
+  source.postMessage("ping");
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html
new file mode 100644
index 0000000..0ebec0b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html
@@ -0,0 +1,21 @@
+<!--
+postMessage('å');
+/*
+-->
+<!doctype html>
+<title>encoding, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '\u00e5');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html.headers b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html.headers
new file mode 100644
index 0000000..2340a89c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/001.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=windows-1252
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html
new file mode 100644
index 0000000..fdcc4f0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html
@@ -0,0 +1,23 @@
+<!--
+onconnect = function(e) {
+  e.ports[0].postMessage('å');
+}
+/*
+-->
+<!doctype html>
+<title>encoding, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new SharedWorker('#', '');
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '\u00e5');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html.headers b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html.headers
new file mode 100644
index 0000000..2340a89c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/002.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=windows-1252
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003-1.py b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003-1.py
new file mode 100644
index 0000000..1e899aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003-1.py
@@ -0,0 +1,4 @@
+ # -*- coding: utf-8 -*-
+
+def main(request, response):
+    return "PASS" if request.GET.first('x') == 'å' else "FAIL"
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003.html
new file mode 100644
index 0000000..a0f964c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/003.html
@@ -0,0 +1,26 @@
+<!--
+var xhr = new XMLHttpRequest();
+xhr.open('GET', '003-1.py?x=å', false);
+xhr.send();
+var passed = xhr.responseText == 'PASS';
+postMessage(passed);
+
+/*
+-->
+<!doctype html>
+<title>URL encoding, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.html
new file mode 100644
index 0000000..bb144263
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.html
@@ -0,0 +1,27 @@
+<!--
+onconnect = function(e) {
+  var xhr = new XMLHttpRequest();
+  xhr.open('GET', '003-1.py?x=å', false);
+  xhr.send();
+  var passed = xhr.responseText == 'PASS';
+  e.ports[0].postMessage(passed);
+}
+/*
+-->
+<!doctype html>
+<title>URL encoding, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new SharedWorker('#');
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.worker.js
new file mode 100644
index 0000000..323d1c93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/encodings/004.worker.js
@@ -0,0 +1,5 @@
+importScripts("/resources/testharness.js");
+test(function() {
+  assert_equals("ÿ", "\ufffd");
+}, "Decoding invalid utf-8");
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/001.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/001.worker.js
new file mode 100644
index 0000000..23df42036
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/001.worker.js
@@ -0,0 +1,79 @@
+importScripts("/resources/testharness.js");
+var expected = [
+  // https://html.spec.whatwg.org/
+  "WorkerGlobalScope",
+  "DedicatedWorkerGlobalScope",
+  "Worker",
+  "SharedWorker",
+  "MessagePort",
+  "MessageEvent",
+  "WorkerNavigator",
+  "MessageChannel",
+  "WorkerLocation",
+  "ImageData",
+  "ImageBitmap",
+  "CanvasPath",
+  "Path2D",
+  "PromiseRejectionEvent",
+  "EventSource",
+  "WebSocket",
+  "CloseEvent",
+  "BroadcastChannel",
+  // https://tc39.github.io/ecma262/
+  "ArrayBuffer",
+  "Int8Array",
+  "Uint8Array",
+  "Uint8ClampedArray",
+  "Int16Array",
+  "Uint16Array",
+  "Int32Array",
+  "Uint32Array",
+  "Float32Array",
+  "Float64Array",
+  "DataView",
+  // https://xhr.spec.whatwg.org/
+  "XMLHttpRequestEventTarget",
+  "XMLHttpRequestUpload",
+  "XMLHttpRequest",
+  "ProgressEvent",
+  "FormData",
+  // https://url.spec.whatwg.org/
+  "URL",
+  "URLSearchParams",
+  // https://w3c.github.io/FileAPI/
+  "File",
+  "Blob",
+  "FileList",
+  "FileReader",
+  "FileReaderSync",
+  // https://dom.spec.whatwg.org/
+  "EventTarget",
+  "ErrorEvent",
+  "Event",
+  "CustomEvent",
+  // http://heycam.github.io/webidl/
+  "DOMException",
+  // https://streams.spec.whatwg.org/
+  "ReadableStream",
+  "WritableStream",
+  "ByteLengthQueuingStrategy",
+  "CountQueuingStrategy",
+  // http://w3c.github.io/IndexedDB/
+  "IDBRequest",
+  "IDBOpenDBRequest",
+  "IDBVersionChangeEvent",
+  "IDBFactory",
+  "IDBDatabase",
+  "IDBObjectStore",
+  "IDBIndex",
+  "IDBKeyRange",
+  "IDBCursor",
+  "IDBCursorWithValue",
+  "IDBTransaction",
+];
+for (var i = 0; i < expected.length; ++i) {
+  test(function () {
+    assert_own_property(self, expected[i]);
+  }, "The " + expected[i] + " interface object should be exposed.");
+}
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/002.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/002.worker.js
new file mode 100644
index 0000000..0f51498
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/002.worker.js
@@ -0,0 +1,49 @@
+importScripts("/resources/testharness.js");
+var unexpected = [
+  // https://html.spec.whatwg.org/
+  "SharedWorkerGlobalScope",
+  "AbstractView",
+  "AbstractWorker",
+  "ApplicationCache",
+  "Location",
+  "Navigator",
+  "Audio",
+  "HTMLCanvasElement",
+  "Path",
+  "TextMetrics",
+  "CanvasProxy",
+  "CanvasRenderingContext2D",
+  "DrawingStyle",
+  "CanvasGradient",
+  "CanvasPattern",
+  "PopStateEvent",
+  "HashChangeEvent",
+  "PageTransitionEvent",
+  // https://dom.spec.whatwg.org/
+  "DOMImplementation",
+  // https://streams.spec.whatwg.org/
+  "ReadableStreamDefaultReader",
+  "ReadableStreamBYOBReader",
+  "ReadableStreamDefaultController",
+  "ReadableByteStreamController",
+  "WritableStreamDefaultWriter",
+  "WritableStreamDefaultController",
+  // http://w3c.github.io/IndexedDB/
+  "IDBEnvironment",
+  // https://www.w3.org/TR/2010/NOTE-webdatabase-20101118/
+  "Database",
+  // https://w3c.github.io/uievents/
+  "UIEvent",
+  "FocusEvent",
+  "MouseEvent",
+  "WheelEvent",
+  "InputEvent",
+  "KeyboardEvent",
+  "CompositionEvent",
+];
+for (var i = 0; i < unexpected.length; ++i) {
+  test(function () {
+    assert_false(unexpected[i] in self);
+  }, "The " + unexpected[i] + " interface object should not be exposed.");
+}
+done();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/003.html
new file mode 100644
index 0000000..5277825d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/003.html
@@ -0,0 +1,106 @@
+<!--
+onconnect = function(e) {
+  var expected = [
+    // https://html.spec.whatwg.org/
+    "ApplicationCache",
+    "WorkerGlobalScope",
+    "SharedWorkerGlobalScope",
+    "Worker",
+    "SharedWorker",
+    "MessagePort",
+    "MessageEvent",
+    "WorkerNavigator",
+    "MessageChannel",
+    "WorkerLocation",
+    "ImageData",
+    "ImageBitmap",
+    "CanvasPath",
+    "Path2D",
+    "PromiseRejectionEvent",
+    "EventSource",
+    "WebSocket",
+    "CloseEvent",
+    "BroadcastChannel",
+    // https://tc39.github.io/ecma262/
+    "ArrayBuffer",
+    "Int8Array",
+    "Uint8Array",
+    "Uint8ClampedArray",
+    "Int16Array",
+    "Uint16Array",
+    "Int32Array",
+    "Uint32Array",
+    "Float32Array",
+    "Float64Array",
+    "DataView",
+    // https://xhr.spec.whatwg.org/
+    "XMLHttpRequestEventTarget",
+    "XMLHttpRequestUpload",
+    "XMLHttpRequest",
+    "ProgressEvent",
+    "FormData",
+    // https://url.spec.whatwg.org/
+    "URL",
+    "URLSearchParams",
+    // https://w3c.github.io/FileAPI/
+    "File",
+    "Blob",
+    "FileList",
+    "FileReader",
+    "FileReaderSync",
+    // https://dom.spec.whatwg.org/
+    "EventTarget",
+    "ErrorEvent",
+    "Event",
+    "CustomEvent",
+    // http://heycam.github.io/webidl/
+    "DOMException",
+    // https://streams.spec.whatwg.org/
+    "ReadableStream",
+    "WritableStream",
+    "ByteLengthQueuingStrategy",
+    "CountQueuingStrategy",
+    // http://w3c.github.io/IndexedDB/
+    "IDBRequest",
+    "IDBOpenDBRequest",
+    "IDBVersionChangeEvent",
+    "IDBFactory",
+    "IDBDatabase",
+    "IDBObjectStore",
+    "IDBIndex",
+    "IDBKeyRange",
+    "IDBCursor",
+    "IDBCursorWithValue",
+    "IDBTransaction",
+  ];
+  var result = [];
+  for (var i = 0; i < expected.length; ++i) {
+    result.push([expected[i], expected[i] in self]);
+  }
+  e.ports[0].postMessage(result);
+}
+/*
+-->
+<!doctype html>
+<title>available interface objects in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup(function() {
+  window.worker = new SharedWorker('#');
+  worker.port.onmessage = function(e) {
+    var result = e.data;
+    for (var i = 0; i < result.length; ++i) {
+      test(function() {
+        assert_true(result[i][1]);
+      }, "The " + result[i][0] + " interface object should be exposed");
+    }
+    done();
+  }
+}, {explicit_done: true});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/004.html
new file mode 100644
index 0000000..2e4387e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/interface-objects/004.html
@@ -0,0 +1,73 @@
+<!--
+onconnect = function(e) {
+  var unexpected = [
+    // https://html.spec.whatwg.org/
+    "DedicatedWorkerGlobalScope",
+    "AbstractView",
+    "AbstractWorker",
+    "Location",
+    "Navigator",
+    "DOMImplementation",
+    "Audio",
+    "HTMLCanvasElement",
+    "Path",
+    "TextMetrics",
+    "CanvasProxy",
+    "CanvasRenderingContext2D",
+    "DrawingStyle",
+    "CanvasGradient",
+    "CanvasPattern",
+    "PopStateEvent",
+    "HashChangeEvent",
+    "PageTransitionEvent",
+    // https://streams.spec.whatwg.org/
+    "ReadableStreamDefaultReader",
+    "ReadableStreamBYOBReader",
+    "ReadableStreamDefaultController",
+    "ReadableByteStreamController",
+    "WritableStreamDefaultWriter",
+    "WritableStreamDefaultController",
+    // http://w3c.github.io/IndexedDB/
+    "IDBEnvironment",
+    // https://www.w3.org/TR/2010/NOTE-webdatabase-20101118/
+    "Database",
+    // https://w3c.github.io/uievents/
+    "UIEvent",
+    "FocusEvent",
+    "MouseEvent",
+    "WheelEvent",
+    "InputEvent",
+    "KeyboardEvent",
+    "CompositionEvent",
+  ];
+  var result = [];
+  for (var i = 0; i < unexpected.length; ++i) {
+    result.push([unexpected[i], unexpected[i] in self]);
+  }
+  e.ports[0].postMessage(result);
+}
+/*
+-->
+<!doctype html>
+<title>unavailable interface objects in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup(function() {
+  window.worker = new SharedWorker('#');
+  worker.port.onmessage = function(e) {
+    var result = e.data;
+    for (var i = 0; i < result.length; ++i) {
+      test(function() {
+        assert_false(result[i][1]);
+      }, "The " + result[i][0] + " interface object should not be exposed");
+    }
+    done();
+  }
+}, {explicit_done: true});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/001.html
new file mode 100644
index 0000000..82ddcc3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/001.html
@@ -0,0 +1,41 @@
+<!--
+if ('onmessage' in self) { // dedicated worker
+  onmessage = function(e) {
+    postMessage(e.data);
+  }
+} else { // shared worker
+  onconnect = function(e) {
+    e.ports[0].onmessage = function(e) {
+      this.postMessage(e.data);
+    }
+  }
+}
+/*
+-->
+<!doctype html>
+<title>dedicated and shared worker in same page</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 'dedicated');
+    this.done();
+  });
+  worker.postMessage('dedicated');
+}, 'dedicated');
+async_test(function() {
+  var shared = new SharedWorker('#', '');
+  shared.port.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 'shared');
+    this.done();
+  });
+  shared.port.postMessage('shared');
+}, 'shared');
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/002.html
new file mode 100644
index 0000000..9ab1f54f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/002.html
@@ -0,0 +1,28 @@
+<!--
+postMessage(1);
+/*
+-->
+<!doctype html>
+<title>creating 3 sibling dedicated workers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+  var w1 = new Worker('#');
+  var w2 = new Worker('#');
+  var w3 = new Worker('#');
+  var got = [false, false, false];
+  var check_done = t.step_func(function() {
+                       if (got.every(function(x) {return x})) {
+                           t.done();
+                       }
+                   });
+  w1.onmessage = t.step_func(function(e) {got[0] = true; check_done()});
+  w2.onmessage = t.step_func(function(e) {got[1] = true; check_done()});
+  w3.onmessage = t.step_func(function(e) {got[2] = true; check_done()});
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/003.html
new file mode 100644
index 0000000..85c688bc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/003.html
@@ -0,0 +1,34 @@
+<!--
+if (location.hash == '#1') {
+  var w2 = new Worker('#2');
+  w2.onmessage = function(e) {
+    postMessage('1'+e.data);
+  }
+} else if (location.hash == '#2') {
+  var w3 = new Worker('#3');
+  w3.onmessage = function(e) {
+    postMessage('2'+e.data);
+  }
+} else {
+  postMessage('3');
+}
+
+/*
+-->
+<!doctype html>
+<title>creating 3 nested dedicated workers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var w1 = new Worker('#1');
+  w1.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '123');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004-2.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004-2.js
new file mode 100644
index 0000000..e59cd692
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004-2.js
@@ -0,0 +1,6 @@
+var port;
+onconnect = function(e) {
+  if (!port)
+    port = e.ports[0];
+  port.postMessage(1);
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004.html
new file mode 100644
index 0000000..c473370
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/004.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>shared worker with multiple documents</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var i = 0;
+var load_count = 0;
+
+var w1 = new SharedWorker('004-2.js', 'x');
+w1.port.onmessage = function(e) {
+  i++;
+  check_result();
+};
+
+
+function iframe_loaded() {
+  load_count++;
+  check_result();
+}
+
+function check_result() {
+  //timeout to allow for extra, unexpected, messages to arrive
+  if (i == 3 && load_count == 2) {
+    setTimeout(function() {
+      assert_equals(load_count, 2);
+      assert_equals(i, 3);
+      done();
+    }, 500);
+  }
+}
+</script>
+<iframe src=004-1.html onload="iframe_loaded()"></iframe>
+<iframe src=004-1.html onload="iframe_loaded()"></iframe>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/005.html
new file mode 100644
index 0000000..289c25ec
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/005.html
@@ -0,0 +1,37 @@
+<!--
+if (location.hash == '#1') {
+  var w2 = new SharedWorker('#2');
+  w2.port.onmessage = function(e) {
+    postMessage('1'+e.data);
+  }
+} else if (location.hash == '#2') {
+  onconnect = function(e) {
+    var port = e.ports[0];
+    var w3 = new Worker('#3');
+    w3.onmessage = function(e) {
+      port.postMessage('2'+e.data);
+    }
+  }
+} else {
+  postMessage('3');
+}
+
+/*
+-->
+<!doctype html>
+<title>dedicated worker in shared worker in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var w1 = new Worker('#1');
+  w1.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '123');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006-1.js
new file mode 100644
index 0000000..6c1ed93
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006-1.js
@@ -0,0 +1,3 @@
+  onconnect = function(e) {
+    e.ports[0].postMessage('3');
+  }
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006.html
new file mode 100644
index 0000000..ef212425
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/006.html
@@ -0,0 +1,35 @@
+<!--
+if (location.hash == '#1') {
+  onconnect = function(e) {
+    var port = e.ports[0];
+    var w2 = new Worker('#2');
+    w2.onmessage = function(e) {
+      port.postMessage('1'+e.data);
+    }
+  }
+} else if (location.hash == '#2') {
+  var w3 = new SharedWorker('006-1.js');
+  w3.port.onmessage = function(e) {
+    postMessage('2'+e.data);
+  }
+}
+
+/*
+-->
+<!doctype html>
+<title>shared worker in dedicated worker in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var w1 = new SharedWorker('#1');
+  w1.port.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '123');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/007.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/007.html
new file mode 100644
index 0000000..e9934507
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/007.html
@@ -0,0 +1,39 @@
+<!--
+if (location.hash == '#1') {
+  onconnect = function(e) {
+    var port = e.ports[0];
+    var w2 = new Worker('#2');
+    w2.onmessage = function(e) {
+      port.postMessage('1'+e.data);
+    }
+  }
+} else if (location.hash == '#2') {
+  var w3 = new SharedWorker('#3');
+  w3.port.onmessage = function(e) {
+    postMessage('2'+e.data);
+  }
+} else {
+  onconnect = function(e) {
+    e.ports[0].postMessage('3');
+  }
+}
+
+/*
+-->
+<!doctype html>
+<title>shared worker in dedicated worker in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var w1 = new SharedWorker('#1');
+  w1.port.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '123');
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/008.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/008.html
new file mode 100644
index 0000000..fbb41e0d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/multiple-workers/008.html
@@ -0,0 +1,31 @@
+<!--
+var channel = new MessageChannel();
+var i = 0;
+onconnect = function(e) {
+  i++;
+  e.ports[0].postMessage(1, [channel['port' + i]]);
+}
+
+/*
+-->
+<!doctype html>
+<title>messagechannel in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe src=008-1.html></iframe>
+<script>
+var t = async_test();
+onload = t.step_func(function() {
+  var w1 = new SharedWorker('#');
+  w1.port.onmessage = this.step_func(function(e) {
+    e.ports[0].onmessage = this.step_func(function(e) {
+      assert_equals(e.data, 2);
+      this.done();
+    });
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/001.html
new file mode 100644
index 0000000..658df06
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/001.html
@@ -0,0 +1,36 @@
+<!--
+
+/*
+-->
+<!doctype html>
+<title>navigating</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var date;
+var newDate;
+</script>
+<iframe></iframe>
+<script>
+var iframe = document.querySelector('iframe');
+onload = function() {
+  iframe.src = "001-1.html?" + Math.random();
+};
+var start_test = function() {
+  window[0].document.links[0].click();
+};
+var after_load = function() {
+  history.back();
+  newDate = new Date();
+  setTimeout(function() {
+    assert_greater_than(Number(date), Number(newDate));
+    assert_equals(window[0].document.title, '001-1');
+    done();
+  }, 2000);
+};
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/002.html
new file mode 100644
index 0000000..c0d5eb5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/navigation/002.html
@@ -0,0 +1,36 @@
+<!--
+
+/*
+-->
+<!doctype html>
+<title>navigating 2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var date;
+var newDate;
+</script>
+<iframe></iframe>
+<script>
+var t = async_test();
+var iframe = document.querySelector('iframe');
+onload = t.step_func(function() {
+  iframe.src = "001-1.html?" + Math.random();
+});
+var start_test = t.step_func(function() {
+  window[0].document.links[0].click();
+});
+var after_load = t.step_func(function() {
+  newDate = new Date();
+  setTimeout(this.step_func(function() {
+    assert_less_than(Number(date), Number(newDate));
+    assert_equals(window[0].document.title, 'foo');
+    this.done();
+  }), 500);
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/001.html
new file mode 100644
index 0000000..adba81f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/001.html
@@ -0,0 +1,53 @@
+<!--
+var port;
+var timeout;
+onerror = function(a,b,c,d,e) {
+  // will return undefined, thus the error is "not handled"
+  // so error should be reported to the user, but this test doesn't check
+  // that.
+  // just make sure that this method is invoked with five arguments
+  clearTimeout(timeout);
+  var log = '';
+  if (arguments.length != 5)
+    log += 'got ' + arguments.length + ' arguments, expected 5. ';
+  if (typeof a != 'string')
+    log += 'first argument wasn\'t a string. ';
+  if (b != location.href)
+    log += 'second argument was ' + b + ', expected ' + location.href + '. ';
+  if (typeof c != 'number')
+    log += 'third argument wasn\'t a number. ';
+  if (typeof d != 'number')
+    log += 'fourth argument wasn\'t a number. ';
+  if (e != 42)
+    log += 'fifth argument wasn\'t the thrown exception. ';
+  port.postMessage(log);
+}
+onconnect = function (e) {
+  port = e.ports[0];
+  timeout = setTimeout(function() { port.postMessage('self.onerror was not invoked'); }, 250);
+  throw 42; // will "report the error"
+}
+
+
+/*
+-->
+<!doctype html>
+<title>shared worker, not handled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+async_test(function() {
+  window.onerror = this.step_func(function(a) {
+    assert_unreached('window.onerror invoked: ' + a);
+  });
+  var worker = new SharedWorker('#', '');
+  worker.port.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, '');
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/002.html
new file mode 100644
index 0000000..c2cd377
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/002.html
@@ -0,0 +1,59 @@
+<!--
+var port;
+var timeout;
+addEventListener('error', function(e) {
+  // event is not canceled, thus the error is "not handled"
+  // so error should be reported to the user, but this test doesn't check
+  // that.
+  // just make sure that this event has the right properties
+  clearTimeout(timeout);
+  var log = '';
+  if (!self.ErrorEvent || Object.getPrototypeOf(e) != ErrorEvent.prototype)
+    log += 'event should be an ErrorEvent. ';
+  if (e.bubbles)
+    log += 'event should not bubble. ';
+  if (!e.cancelable)
+    log += 'event should be cancelable. ';
+  if (!e.isTrusted)
+    log += 'event should be trusted. ';
+  if (typeof e.message != 'string')
+    log += 'message wasn\'t a string. ';
+  if (e.filename != location.href)
+    log += 'filename was ' + e.filename + ', expected ' + location.href + '. ';
+  if (typeof e.lineno != 'number')
+    log += 'lineno wasn\'t a number. ';
+  if (typeof e.colno != 'number')
+    log += 'colno argument wasn\'t a number. ';
+  if (e.error != 42)
+    log += 'fifth argument wasn\'t the thrown exception. ';
+  port.postMessage(log);
+}, false);
+onconnect = function (e) {
+  port = e.ports[0];
+  timeout = setTimeout(function() { port.postMessage('No error event fired'); }, 250);
+  throw 42; // will "report the error"
+}
+
+
+/*
+-->
+<!doctype html>
+<title>shared worker, addEventListener</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+async_test(function() {
+  window.onerror = this.step_func(function(a) {
+    assert_unreached('window.onerror invoked: ' + a);
+  });
+  var worker = new SharedWorker('#', '');
+  worker.port.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, '');
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/003.html
new file mode 100644
index 0000000..1b01c7c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/003.html
@@ -0,0 +1,39 @@
+<!--
+onconnect = function (e) {
+  setTimeout(function() { e.ports[0].postMessage(''); }, 250);
+  y(); // will "report the error"
+  // onerror is null so it'll be "not handled", and the error should be
+  // reported to the user, although we don't test that here
+  // make sure we don't fire an error event on the message port or the
+  // SharedWorker object
+}
+
+
+/*
+-->
+<!doctype html>
+<title>shared worker, no error event on worker or port</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+async_test(function() {
+  window.onerror = this.step_func(function(a) {
+    assert_unreached('window.onerror invoked: ' + a);
+  });
+  var worker = new SharedWorker('#', '');
+  worker.addEventListener('error', this.step_func(function(e) {
+    assert_unreached('error on worker');
+  }), false);
+  worker.port.addEventListener('error', this.step_func(function(e) {
+    assert_unreached('error on port');
+  }), false);
+  worker.port.onmessage = this.step_func_done(function(e) {
+    assert_equals(e.data, '');
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/004.html
new file mode 100644
index 0000000..1dd1eb3b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/reporting-errors/004.html
@@ -0,0 +1,39 @@
+<!--
+var i = 0;
+onconnect = function (e) {
+  i++;
+  setTimeout(function() { e.ports[0].postMessage(i); }, 250);
+  y(); // will "report the error"
+}
+
+/*
+-->
+<!doctype html>
+<title>shared worker in two documents and window.onerror</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+var t = async_test(function() {
+  window.onerror = this.step_func(function(a) {
+    assert_unreached('(outer) window.onerror invoked: ' + a);
+  });
+  var worker = new SharedWorker('#', '');
+  worker.addEventListener('error', this.step_func(function(e) {
+    assert_unreached('(outer) error on worker');
+  }), false);
+  worker.port.addEventListener('error', this.step_func(function(e) {
+    assert_unreached('(outer) error on port');
+  }), false);
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, 1);
+    var iframe = document.createElement('iframe');
+    iframe.src = '004-1.html';
+    document.body.appendChild(iframe);
+  });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/001.html
new file mode 100644
index 0000000..aa0fc67
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/001.html
@@ -0,0 +1,22 @@
+<!--
+postMessage(this === self);
+
+/*
+-->
+<!doctype html>
+<title>worker global scope, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/002.html
new file mode 100644
index 0000000..3617ad72
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/002.html
@@ -0,0 +1,24 @@
+<!--
+var passed = this === self;
+onconnect = function(e) {
+  e.ports[0].postMessage(passed);
+}
+/*
+-->
+<!doctype html>
+<title>worker global scope, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+  var worker = new SharedWorker('#');
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+});
+</script>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/003.html
new file mode 100644
index 0000000..8c2f07e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/run-a-worker/003.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>handling for 404 response</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception: true});
+
+async_test(function() {
+  var worker = new Worker('404_worker');
+  worker.onerror = this.step_func(function(e) { this.done(); });
+}, 'worker');
+
+async_test(function() {
+  var shared = new SharedWorker('404_shared');
+  // NOTE: this handler will not fire, as runtime scripting errors
+  // are not forwarded to SharedWorker objects, but instead reported to the user directly.
+  shared.onerror = this.step_func(function(e) { assert_unreached(); }, shared, 'error');
+  step_timeout(this.step_func(function() { this.done(); }), 5000);
+}, 'shared');
+</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/common.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/common.js
new file mode 100644
index 0000000..56c2a30
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/common.js
@@ -0,0 +1,596 @@
+function createWorker(msg) {
+  // `type` is defined in the test case itself
+  if (type == 'dedicated')
+    return new Worker('dedicated.js#'+encodeURIComponent(msg));
+  else if (type == 'shared')
+    return (new SharedWorker('shared.js#'+encodeURIComponent(msg))).port;
+  else
+    assert_unreached('invalid or missing `type`');
+}
+
+function check(msg, input, callback, test_obj) {
+  if (!test_obj)
+    test_obj = async_test(msg);
+  test_obj.step(function() {
+    var w = createWorker(msg);
+    if (typeof input === 'function')
+      input = this.step(input);
+    w.postMessage(input);
+    w.onmessage = this.step_func(function(ev) { callback(ev.data, input, this); });
+  });
+}
+
+function compare_primitive(actual, input, test_obj) {
+  assert_equals(actual, input);
+  if (test_obj)
+    test_obj.done();
+}
+function compare_Array(callback, callback_is_async) {
+  return function(actual, input, test_obj) {
+    if (typeof actual === 'string')
+      assert_unreached(actual);
+    assert_true(actual instanceof Array, 'instanceof Array');
+    assert_not_equals(actual, input);
+    assert_equals(actual.length, input.length, 'length');
+    callback(actual, input);
+    if (test_obj && !callback_is_async)
+      test_obj.done();
+  }
+}
+
+function compare_Object(callback, callback_is_async) {
+  return function(actual, input, test_obj) {
+    if (typeof actual === 'string')
+      assert_unreached(actual);
+    assert_true(actual instanceof Object, 'instanceof Object');
+    assert_false(actual instanceof Array, 'instanceof Array');
+    assert_not_equals(actual, input);
+    callback(actual, input);
+    if (test_obj && !callback_is_async)
+      test_obj.done();
+  }
+}
+
+function enumerate_props(compare_func, test_obj) {
+  return function(actual, input) {
+    for (var x in input) {
+      compare_func(actual[x], input[x], test_obj);
+    }
+  };
+}
+
+check('primitive undefined', undefined, compare_primitive);
+check('primitive null', null, compare_primitive);
+check('primitive true', true, compare_primitive);
+check('primitive false', false, compare_primitive);
+check('primitive string, empty string', '', compare_primitive);
+check('primitive string, lone high surrogate', '\uD800', compare_primitive);
+check('primitive string, lone low surrogate', '\uDC00', compare_primitive);
+check('primitive string, NUL', '\u0000', compare_primitive);
+check('primitive string, astral character', '\uDBFF\uDFFD', compare_primitive);
+check('primitive number, 0.2', 0.2, compare_primitive);
+check('primitive number, 0', 0, compare_primitive);
+check('primitive number, -0', -0, compare_primitive);
+check('primitive number, NaN', NaN, compare_primitive);
+check('primitive number, Infinity', Infinity, compare_primitive);
+check('primitive number, -Infinity', -Infinity, compare_primitive);
+check('primitive number, 9007199254740992', 9007199254740992, compare_primitive);
+check('primitive number, -9007199254740992', -9007199254740992, compare_primitive);
+check('primitive number, 9007199254740994', 9007199254740994, compare_primitive);
+check('primitive number, -9007199254740994', -9007199254740994, compare_primitive);
+
+check('Array primitives', [undefined,
+                           null,
+                           true,
+                           false,
+                           '',
+                           '\uD800',
+                           '\uDC00',
+                           '\u0000',
+                           '\uDBFF\uDFFD',
+                           0.2,
+                           0,
+                           -0,
+                           NaN,
+                           Infinity,
+                           -Infinity,
+                           9007199254740992,
+                           -9007199254740992,
+                           9007199254740994,
+                           -9007199254740994], compare_Array(enumerate_props(compare_primitive)));
+check('Object primitives', {'undefined':undefined,
+                           'null':null,
+                           'true':true,
+                           'false':false,
+                           'empty':'',
+                           'high surrogate':'\uD800',
+                           'low surrogate':'\uDC00',
+                           'nul':'\u0000',
+                           'astral':'\uDBFF\uDFFD',
+                           '0.2':0.2,
+                           '0':0,
+                           '-0':-0,
+                           'NaN':NaN,
+                           'Infinity':Infinity,
+                           '-Infinity':-Infinity,
+                           '9007199254740992':9007199254740992,
+                           '-9007199254740992':-9007199254740992,
+                           '9007199254740994':9007199254740994,
+                           '-9007199254740994':-9007199254740994}, compare_Object(enumerate_props(compare_primitive)));
+
+function compare_Boolean(actual, input, test_obj) {
+  if (typeof actual === 'string')
+    assert_unreached(actual);
+  assert_true(actual instanceof Boolean, 'instanceof Boolean');
+  assert_equals(String(actual), String(input), 'converted to primitive');
+  assert_not_equals(actual, input);
+  if (test_obj)
+    test_obj.done();
+}
+check('Boolean true', new Boolean(true), compare_Boolean);
+check('Boolean false', new Boolean(false), compare_Boolean);
+check('Array Boolean objects', [new Boolean(true), new Boolean(false)], compare_Array(enumerate_props(compare_Boolean)));
+check('Object Boolean objects', {'true':new Boolean(true), 'false':new Boolean(false)}, compare_Object(enumerate_props(compare_Boolean)));
+
+function compare_obj(what) {
+  var Type = window[what];
+  return function(actual, input, test_obj) {
+    if (typeof actual === 'string')
+      assert_unreached(actual);
+    assert_true(actual instanceof Type, 'instanceof '+what);
+    assert_equals(Type(actual), Type(input), 'converted to primitive');
+    assert_not_equals(actual, input);
+    if (test_obj)
+      test_obj.done();
+  };
+}
+check('String empty string', new String(''), compare_obj('String'));
+check('String lone high surrogate', new String('\uD800'), compare_obj('String'));
+check('String lone low surrogate', new String('\uDC00'), compare_obj('String'));
+check('String NUL', new String('\u0000'), compare_obj('String'));
+check('String astral character', new String('\uDBFF\uDFFD'), compare_obj('String'));
+check('Array String objects', [new String(''),
+                               new String('\uD800'),
+                               new String('\uDC00'),
+                               new String('\u0000'),
+                               new String('\uDBFF\uDFFD')], compare_Array(enumerate_props(compare_obj('String'))));
+check('Object String objects', {'empty':new String(''),
+                               'high surrogate':new String('\uD800'),
+                               'low surrogate':new String('\uDC00'),
+                               'nul':new String('\u0000'),
+                               'astral':new String('\uDBFF\uDFFD')}, compare_Object(enumerate_props(compare_obj('String'))));
+
+check('Number 0.2', new Number(0.2), compare_obj('Number'));
+check('Number 0', new Number(0), compare_obj('Number'));
+check('Number -0', new Number(-0), compare_obj('Number'));
+check('Number NaN', new Number(NaN), compare_obj('Number'));
+check('Number Infinity', new Number(Infinity), compare_obj('Number'));
+check('Number -Infinity', new Number(-Infinity), compare_obj('Number'));
+check('Number 9007199254740992', new Number(9007199254740992), compare_obj('Number'));
+check('Number -9007199254740992', new Number(-9007199254740992), compare_obj('Number'));
+check('Number 9007199254740994', new Number(9007199254740994), compare_obj('Number'));
+check('Number -9007199254740994', new Number(-9007199254740994), compare_obj('Number'));
+check('Array Number objects', [new Number(0.2),
+                               new Number(0),
+                               new Number(-0),
+                               new Number(NaN),
+                               new Number(Infinity),
+                               new Number(-Infinity),
+                               new Number(9007199254740992),
+                               new Number(-9007199254740992),
+                               new Number(9007199254740994),
+                               new Number(-9007199254740994)], compare_Array(enumerate_props(compare_obj('Number'))));
+check('Object Number objects', {'0.2':new Number(0.2),
+                               '0':new Number(0),
+                               '-0':new Number(-0),
+                               'NaN':new Number(NaN),
+                               'Infinity':new Number(Infinity),
+                               '-Infinity':new Number(-Infinity),
+                               '9007199254740992':new Number(9007199254740992),
+                               '-9007199254740992':new Number(-9007199254740992),
+                               '9007199254740994':new Number(9007199254740994),
+                               '-9007199254740994':new Number(-9007199254740994)}, compare_Object(enumerate_props(compare_obj('Number'))));
+
+function compare_Date(actual, input, test_obj) {
+  if (typeof actual === 'string')
+    assert_unreached(actual);
+  assert_true(actual instanceof Date, 'instanceof Date');
+  assert_equals(Number(actual), Number(input), 'converted to primitive');
+  assert_not_equals(actual, input);
+  if (test_obj)
+    test_obj.done();
+}
+check('Date 0', new Date(0), compare_Date);
+check('Date -0', new Date(-0), compare_Date);
+check('Date -8.64e15', new Date(-8.64e15), compare_Date);
+check('Date 8.64e15', new Date(8.64e15), compare_Date);
+check('Array Date objects', [new Date(0),
+                             new Date(-0),
+                             new Date(-8.64e15),
+                             new Date(8.64e15)], compare_Array(enumerate_props(compare_Date)));
+check('Object Date objects', {'0':new Date(0),
+                              '-0':new Date(-0),
+                              '-8.64e15':new Date(-8.64e15),
+                              '8.64e15':new Date(8.64e15)}, compare_Object(enumerate_props(compare_Date)));
+
+function compare_RegExp(expected_source) {
+  // XXX ES6 spec doesn't define exact serialization for `source` (it allows several ways to escape)
+  return function(actual, input, test_obj) {
+    if (typeof actual === 'string')
+      assert_unreached(actual);
+    assert_true(actual instanceof RegExp, 'instanceof RegExp');
+    assert_equals(actual.global, input.global, 'global');
+    assert_equals(actual.ignoreCase, input.ignoreCase, 'ignoreCase');
+    assert_equals(actual.multiline, input.multiline, 'multiline');
+    assert_equals(actual.source, expected_source, 'source');
+    assert_equals(actual.sticky, input.sticky, 'sticky');
+    assert_equals(actual.unicode, input.unicode, 'unicode');
+    assert_equals(actual.lastIndex, 0, 'lastIndex');
+    assert_not_equals(actual, input);
+    if (test_obj)
+      test_obj.done();
+  }
+}
+function func_RegExp_flags_lastIndex() {
+  var r = /foo/gim;
+  r.lastIndex = 2;
+  return r;
+}
+function func_RegExp_sticky() {
+  return new RegExp('foo', 'y');
+}
+function func_RegExp_unicode() {
+  return new RegExp('foo', 'u');
+}
+check('RegExp flags and lastIndex', func_RegExp_flags_lastIndex, compare_RegExp('foo'));
+check('RegExp sticky flag', func_RegExp_sticky, compare_RegExp('foo'));
+check('RegExp unicode flag', func_RegExp_unicode, compare_RegExp('foo'));
+check('RegExp empty', new RegExp(''), compare_RegExp('(?:)'));
+check('RegExp slash', new RegExp('/'), compare_RegExp('\\/'));
+check('RegExp new line', new RegExp('\n'), compare_RegExp('\\n'));
+check('Array RegExp object, RegExp flags and lastIndex', [func_RegExp_flags_lastIndex()], compare_Array(enumerate_props(compare_RegExp('foo'))));
+check('Array RegExp object, RegExp sticky flag', function() { return [func_RegExp_sticky()]; }, compare_Array(enumerate_props(compare_RegExp('foo'))));
+check('Array RegExp object, RegExp unicode flag', function() { return [func_RegExp_unicode()]; }, compare_Array(enumerate_props(compare_RegExp('foo'))));
+check('Array RegExp object, RegExp empty', [new RegExp('')], compare_Array(enumerate_props(compare_RegExp('(?:)'))));
+check('Array RegExp object, RegExp slash', [new RegExp('/')], compare_Array(enumerate_props(compare_RegExp('\\/'))));
+check('Array RegExp object, RegExp new line', [new RegExp('\n')], compare_Array(enumerate_props(compare_RegExp('\\n'))));
+check('Object RegExp object, RegExp flags and lastIndex', {'x':func_RegExp_flags_lastIndex()}, compare_Object(enumerate_props(compare_RegExp('foo'))));
+check('Object RegExp object, RegExp sticky flag', function() { return {'x':func_RegExp_sticky()}; }, compare_Object(enumerate_props(compare_RegExp('foo'))));
+check('Object RegExp object, RegExp unicode flag', function() { return {'x':func_RegExp_unicode()}; }, compare_Object(enumerate_props(compare_RegExp('foo'))));
+check('Object RegExp object, RegExp empty', {'x':new RegExp('')}, compare_Object(enumerate_props(compare_RegExp('(?:)'))));
+check('Object RegExp object, RegExp slash', {'x':new RegExp('/')}, compare_Object(enumerate_props(compare_RegExp('\\/'))));
+check('Object RegExp object, RegExp new line', {'x':new RegExp('\n')}, compare_Object(enumerate_props(compare_RegExp('\\n'))));
+
+function compare_Blob(actual, input, test_obj, expect_File) {
+  if (typeof actual === 'string')
+    assert_unreached(actual);
+  assert_true(actual instanceof Blob, 'instanceof Blob');
+  if (!expect_File)
+    assert_false(actual instanceof File, 'instanceof File');
+  assert_equals(actual.size, input.size, 'size');
+  assert_equals(actual.type, input.type, 'type');
+  assert_not_equals(actual, input);
+  var ev_reader = new FileReader();
+  var input_reader = new FileReader();
+  var read_count = 0;
+  var read_done = test_obj.step_func(function() {
+    read_count++;
+    if (read_count == 2) {
+      var ev_result = ev_reader.result;
+      var input_result = input_reader.result;
+      assert_equals(ev_result.byteLength, input_result.byteLength, 'byteLength');
+      var ev_view = new DataView(ev_result);
+      var input_view = new DataView(input_result);
+      for (var i = 0; i < ev_result.byteLength; ++i) {
+        assert_equals(ev_view.getUint8(i), input_view.getUint8(i), 'getUint8('+i+')');
+      }
+      if (test_obj)
+        test_obj.done();
+    }
+  });
+  var read_error = test_obj.step_func(function() { assert_unreached('FileReader error'); });
+  ev_reader.readAsArrayBuffer(actual);
+  ev_reader.onload = read_done;
+  ev_reader.onabort = ev_reader.onerror = read_error;
+  input_reader.readAsArrayBuffer(input);
+  input_reader.onload = read_done;
+  input_reader.onabort = input_reader.onerror = read_error;
+}
+function func_Blob_basic() {
+  return new Blob(['foo'], {type:'text/x-bar'});
+}
+check('Blob basic', func_Blob_basic, compare_Blob);
+
+function b(str) {
+  return parseInt(str, 2);
+}
+function encode_cesu8(codeunits) {
+  // http://www.unicode.org/reports/tr26/ section 2.2
+  // only the 3-byte form is supported
+  var rv = [];
+  codeunits.forEach(function(codeunit) {
+    rv.push(b('11100000') + ((codeunit & b('1111000000000000')) >> 12));
+    rv.push(b('10000000') + ((codeunit & b('0000111111000000')) >> 6));
+    rv.push(b('10000000') +  (codeunit & b('0000000000111111')));
+  });
+  return rv;
+}
+function func_Blob_bytes(arr) {
+  return function() {
+    var buffer = new ArrayBuffer(arr.length);
+    var view = new DataView(buffer);
+    for (var i = 0; i < arr.length; ++i) {
+      view.setUint8(i, arr[i]);
+    }
+    return new Blob([view]);
+  };
+}
+check('Blob unpaired high surrogate (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xD800])), compare_Blob);
+check('Blob unpaired low surrogate (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xDC00])), compare_Blob);
+check('Blob paired surrogates (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xD800, 0xDC00])), compare_Blob);
+
+function func_Blob_empty() {
+  return new Blob(['']);
+}
+check('Blob empty', func_Blob_empty , compare_Blob);
+function func_Blob_NUL() {
+  return new Blob(['\u0000']);
+}
+check('Blob NUL', func_Blob_NUL, compare_Blob);
+
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob basic');
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob paired surrogates (invalid utf-8)');
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob empty');
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob NUL');
+
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob basic');
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob paired surrogates (invalid utf-8)');
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob empty');
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob NUL');
+
+function compare_File(actual, input, test_obj) {
+  assert_true(actual instanceof File, 'instanceof File');
+  assert_equals(actual.name, input.name, 'name');
+  assert_equals(actual.lastModified, input.lastModified, 'lastModified');
+  compare_Blob(actual, input, test_obj, true);
+}
+function func_File_basic() {
+  return new File(['foo'], 'bar', {type:'text/x-bar', lastModified:42});
+}
+check('File basic', func_File_basic, compare_File);
+
+function compare_FileList(actual, input, test_obj) {
+  if (typeof actual === 'string')
+    assert_unreached(actual);
+  assert_true(actual instanceof FileList, 'instanceof FileList');
+  assert_equals(actual.length, input.length, 'length');
+  assert_not_equals(actual, input);
+  // XXX when there's a way to populate or construct a FileList,
+  // check the items in the FileList
+  if (test_obj)
+    test_obj.done();
+}
+function func_FileList_empty() {
+  var input = document.createElement('input');
+  input.type = 'file';
+  return input.files;
+}
+check('FileList empty', func_FileList_empty, compare_FileList);
+check('Array FileList object, FileList empty', [func_FileList_empty], compare_Array(enumerate_props(compare_FileList)));
+check('Object FileList object, FileList empty', {'x':func_FileList_empty}, compare_Object(enumerate_props(compare_FileList)));
+
+function compare_ArrayBufferView(view) {
+  var Type = window[view];
+  return function(actual, input, test_obj) {
+    if (typeof actual === 'string')
+      assert_unreached(actual);
+    assert_true(actual instanceof Type, 'instanceof '+view);
+    assert_equals(actual.length, input.length, 'length');
+    assert_not_equals(actual.buffer, input.buffer, 'buffer');
+    for (var i = 0; i < actual.length; ++i) {
+      assert_equals(actual[i], input[i], 'actual['+i+']');
+    }
+    if (test_obj)
+      test_obj.done();
+  };
+}
+function compare_ImageData(actual, input, test_obj) {
+  if (typeof actual === 'string')
+    assert_unreached(actual);
+  assert_equals(actual.width, input.width, 'width');
+  assert_equals(actual.height, input.height, 'height');
+  assert_not_equals(actual.data, input.data, 'data');
+  compare_ArrayBufferView('Uint8ClampedArray')(actual.data, input.data, null);
+  if (test_obj)
+    test_obj.done();
+}
+function func_ImageData_1x1_transparent_black() {
+  var canvas = document.createElement('canvas');
+  var ctx = canvas.getContext('2d');
+  return ctx.createImageData(1, 1);
+}
+check('ImageData 1x1 transparent black', func_ImageData_1x1_transparent_black, compare_ImageData);
+function func_ImageData_1x1_non_transparent_non_black() {
+  var canvas = document.createElement('canvas');
+  var ctx = canvas.getContext('2d');
+  var imagedata = ctx.createImageData(1, 1);
+  imagedata.data[0] = 100;
+  imagedata.data[1] = 101;
+  imagedata.data[2] = 102;
+  imagedata.data[3] = 103;
+  return imagedata;
+}
+check('ImageData 1x1 non-transparent non-black', func_ImageData_1x1_non_transparent_non_black, compare_ImageData);
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_ImageData_1x1_transparent_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj);
+}, 'Array ImageData object, ImageData 1x1 transparent black');
+async_test(function(test_obj) {
+  check(test_obj.name, [test_obj.step(func_ImageData_1x1_non_transparent_non_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj);
+}, 'Array ImageData object, ImageData 1x1 non-transparent non-black');
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_transparent_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj);
+}, 'Object ImageData object, ImageData 1x1 transparent black');
+async_test(function(test_obj) {
+  check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_non_transparent_non_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj);
+}, 'Object ImageData object, ImageData 1x1 non-transparent non-black');
+
+function compare_ImageBitmap(actual, input, test_obj) {
+  if (typeof actual === 'string')
+    assert_unreached(actual);
+  assert_equals(actual instanceof ImageBitmap, 'instanceof ImageBitmap');
+  assert_not_equals(actual, input);
+  // XXX paint the ImageBitmap on a canvas and check the data
+  if (test_obj)
+    test_obj.done();
+}
+function get_canvas_1x1_transparent_black() {
+  var canvas = document.createElement('canvas');
+  canvas.width = 1;
+  canvas.height = 1;
+  return canvas;
+}
+async_test(function(test_obj) {
+  var canvas = get_canvas_1x1_transparent_black();
+  createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); });
+}, 'ImageBitmap 1x1 transparent black');
+function get_canvas_1x1_non_transparent_non_black() {
+  var canvas = document.createElement('canvas');
+  canvas.width = 1;
+  canvas.height = 1;
+  var ctx = canvas.getContext('2d');
+  var imagedata = ctx.getImageData(0, 0, 1, 1);
+  imagedata.data[0] = 100;
+  imagedata.data[1] = 101;
+  imagedata.data[2] = 102;
+  imagedata.data[3] = 103;
+  return canvas;
+}
+async_test(function(test_obj) {
+  var canvas = get_canvas_1x1_non_transparent_non_black();
+  createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); });
+}, 'ImageBitmap 1x1 non-transparent non-black');
+
+async_test(function(test_obj) {
+  var canvas = get_canvas_1x1_transparent_black();
+  createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Array ImageBitmap object, ImageBitmap 1x1 transparent black');
+async_test(function(test_obj) {
+  var canvas = get_canvas_1x1_non_transparent_non_black();
+  createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black');
+
+async_test(function(test_obj) {
+  var canvas = get_canvas_1x1_transparent_black();
+  createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Object ImageBitmap object, ImageBitmap 1x1 transparent black');
+async_test(function(test_obj) {
+  var canvas = get_canvas_1x1_non_transparent_non_black();
+  createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black');
+
+check('Array sparse', new Array(10), compare_Array(enumerate_props(compare_primitive)));
+check('Array with non-index property', function() {
+  var rv = [];
+  rv.foo = 'bar';
+  return rv;
+}, compare_Array(enumerate_props(compare_primitive)));
+check('Object with index property and length', {'0':'foo', 'length':1}, compare_Object(enumerate_props(compare_primitive)));
+function check_circular_property(prop) {
+  return function(actual) {
+    assert_equals(actual[prop], actual);
+  };
+}
+check('Array with circular reference', function() {
+  var rv = [];
+  rv[0] = rv;
+  return rv;
+}, compare_Array(check_circular_property('0')));
+check('Object with circular reference', function() {
+  var rv = {};
+  rv['x'] = rv;
+  return rv;
+}, compare_Object(check_circular_property('x')));
+function check_identical_property_values(prop1, prop2) {
+  return function(actual) {
+    assert_equals(actual[prop1], actual[prop2]);
+  };
+}
+check('Array with identical property values', function() {
+  var obj = {}
+  return [obj, obj];
+}, compare_Array(check_identical_property_values('0', '1')));
+check('Object with identical property values', function() {
+  var obj = {}
+  return {'x':obj, 'y':obj};
+}, compare_Object(check_identical_property_values('x', 'y')));
+
+function check_absent_property(prop) {
+  return function(actual) {
+    assert_false(prop in actual);
+  };
+}
+check('Object with property on prototype', function() {
+  var Foo = function() {};
+  Foo.prototype = {'foo':'bar'};
+  return new Foo();
+}, compare_Object(check_absent_property('foo')));
+
+check('Object with non-enumerable property', function() {
+  var rv = {};
+  Object.defineProperty(rv, 'foo', {value:'bar', enumerable:false, writable:true, configurable:true});
+  return rv;
+}, compare_Object(check_absent_property('foo')));
+
+function check_writable_property(prop) {
+  return function(actual, input) {
+    assert_equals(actual[prop], input[prop]);
+    actual[prop] += ' baz';
+    assert_equals(actual[prop], input[prop] + ' baz');
+  };
+}
+check('Object with non-writable property', function() {
+  var rv = {};
+  Object.defineProperty(rv, 'foo', {value:'bar', enumerable:true, writable:false, configurable:true});
+  return rv;
+}, compare_Object(check_writable_property('foo')));
+
+function check_configurable_property(prop) {
+  return function(actual, input) {
+    assert_equals(actual[prop], input[prop]);
+    delete actual[prop];
+    assert_false('prop' in actual);
+  };
+}
+check('Object with non-configurable property', function() {
+  var rv = {};
+  Object.defineProperty(rv, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false});
+  return rv;
+}, compare_Object(check_configurable_property('foo')));
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.html
new file mode 100644
index 0000000..5dd8c356
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>structured clone to dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var type = 'dedicated';
+</script>
+<script src="common.js"></script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.js
new file mode 100644
index 0000000..4744578
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/dedicated.js
@@ -0,0 +1,4 @@
+importScripts('worker-common.js');
+onmessage = function(ev) {
+  check(ev.data, self);
+};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.html
new file mode 100644
index 0000000..6f74354
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>structured clone to shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var type = 'shared';
+</script>
+<script src="common.js"></script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.js
new file mode 100644
index 0000000..372a9ec9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/shared.js
@@ -0,0 +1,6 @@
+importScripts('worker-common.js');
+onconnect = function(connect_ev) {
+  connect_ev.ports[0].onmessage = function(message_ev) {
+    check(message_ev.data, this);
+  };
+};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/worker-common.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/worker-common.js
new file mode 100644
index 0000000..fd63ff5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/structured-clone/worker-common.js
@@ -0,0 +1,1018 @@
+var msg = decodeURIComponent(location.hash.substr(1));
+
+var log = [];
+function check_true(actual, msg) {
+  if (actual !== true) {
+    log.push(msg);
+    return false;
+  }
+  return true;
+}
+
+function check_Blob(msg, input, port, expect_File, orig_input) {
+  expect_File = !!expect_File;
+  orig_input = orig_input || input;
+  try {
+    var expected;
+    switch (msg) {
+      case 'Blob basic':
+      case 'File basic':
+        expected = [0x66, 0x6F, 0x6F];
+        expected.type = 'text/x-bar';
+        if (expect_File) {
+          expected.name = 'bar';
+          expected.lastModified = 42;
+        }
+        break;
+      case 'Blob unpaired high surrogate (invalid utf-8)':
+        expected = [0xED, 0xA0, 0x80];
+        expected.type = '';
+        break;
+      case 'Blob unpaired low surrogate (invalid utf-8)':
+        expected = [0xED, 0xB0, 0x80];
+        expected.type = '';
+        break;
+      case 'Blob paired surrogates (invalid utf-8)':
+        expected = [0xED, 0xA0, 0x80, 0xED, 0xB0, 0x80];
+        expected.type = '';
+        break;
+      case 'Blob empty':
+        expected = [];
+        expected.type = '';
+        break;
+      case 'Blob NUL':
+        var expected = [0x00];
+        expected.type = '';
+        break;
+      default:
+        check_true(false, 'check_Blob: unknown test');
+        return;
+        break;
+    }
+    if (check_true(input instanceof Blob, 'input instanceof Blob') &&
+        check_true((input instanceof File) == expect_File, '(input instanceof File) == expect_File') &&
+        check_true(input.size === expected.length, 'input.size === expected.length') &&
+        check_true(input.type === expected.type, 'input.type === expected.type')) {
+      if (!expect_File || (check_true(input.name === expected.name, 'input.name === expected.name') &&
+                           check_true(input.lastModified === expected.lastModified))) {
+        var reader = new FileReader();
+        var read_done = function() {
+          try {
+            var result = reader.result;
+            check_true(result.byteLength === expected.length, 'result.byteLength === expected.length')
+            var view = new DataView(result);
+            for (var i = 0; i < result.byteLength; ++i) {
+              check_true(view.getUint8(i) === expected[i], 'view.getUint8('+i+') === expected['+i+']')
+            }
+            if (log.length === 0) {
+              port.postMessage(orig_input);
+            } else {
+              port.postMessage('FAIL '+log);
+            }
+            close();
+          } catch(ex) {
+            postMessage('FAIL '+ex);
+            close();
+          }
+        }
+        var read_error = function() { port.postMessage('FAIL (got FileReader error)'); close(); };
+        reader.readAsArrayBuffer(input);
+        reader.onload = read_done;
+        reader.onabort = reader.onerror = read_error;
+      }
+    } else {
+      port.postMessage('FAIL '+log);
+      close();
+    }
+  } catch(ex) {
+    postMessage('FAIL '+ex);
+    close();
+  }
+}
+
+function check_ImageData(input, expected) {
+  if (check_true(input instanceof ImageData, 'input instanceof ImageData') &&
+      check_true(input.width === expected.width, 'input.width === '+expected.width) &&
+      check_true(input.height === expected.height, 'input.height === '+expected.height) &&
+      check_true(input.data instanceof Uint8ClampedArray, 'input.data instanceof Uint8ClampedArray') &&
+      check_true(input.data.length === expected.data.length, 'input.data.length === '+expected.data.length) &&
+      check_true(!('CanvasPixelArray' in self), "!('CanvasPixelArray' in self)")) {
+    for (var i = 0; i < input.length; ++i) {
+      if (!(check_true(input.data[i] === expected.data[i], 'input.data['+i+'] === '+expected.data[i]))) {
+        return false;
+      }
+    }
+    return true;
+  }
+  return false;
+}
+
+function check_ImageBitmap(input, expected) {
+  return check_true(input instanceof ImageBitmap, 'input instanceof ImageBitmap');
+  // XXX paint it on a proxy canvas and check the data
+}
+
+function check_RegExp(msg, input) {
+  // XXX ES6 spec doesn't define exact serialization for `source` (it allows several ways to escape)
+  switch (msg) {
+    case 'RegExp flags and lastIndex':
+      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+             check_true(input.source === 'foo', "input.source === 'foo'") &&
+             check_true(input.global === true, "input.global === true") &&
+             check_true(input.ignoreCase === true, "input.ignoreCase === true") &&
+             check_true(input.multiline === true, "input.multiline === true") &&
+             check_true(input.lastIndex === 0, "input.lastIndex === 0");
+      break;
+    case 'RegExp sticky flag':
+      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+             check_true(input.source === 'foo', "input.source === 'foo'") &&
+             check_true(input.global === false, "input.global === false") &&
+             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+             check_true(input.multiline === false, "input.multiline === false") &&
+             check_true(input.sticky === true, "input.sticky === true") &&
+             check_true(input.unicode === false, "input.unicode === false") &&
+             check_true(input.lastIndex === 0, "input.lastIndex === 0");
+      break;
+    case 'RegExp unicode flag':
+      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+             check_true(input.source === 'foo', "input.source === 'foo'") &&
+             check_true(input.global === false, "input.global === false") &&
+             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+             check_true(input.multiline === false, "input.multiline === false") &&
+             check_true(input.sticky === false, "input.sticky === false") &&
+             check_true(input.unicode === true, "input.unicode === true") &&
+             check_true(input.lastIndex === 0, "input.lastIndex === 0");
+      break;
+    case 'RegExp empty':
+      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+             check_true(input.source === '(?:)', "input.source === '(?:)'") &&
+             check_true(input.global === false, "input.global === false") &&
+             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+             check_true(input.multiline === false, "input.multiline === false") &&
+             check_true(input.lastIndex === 0, "input.lastIndex === 0");
+      break;
+    case 'RegExp slash':
+      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+             check_true(input.source === '\\/', "input.source === '\\\\/'") &&
+             check_true(input.global === false, "input.global === false") &&
+             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+             check_true(input.multiline === false, "input.multiline === false") &&
+             check_true(input.lastIndex === 0, "input.lastIndex === 0");
+      break;
+    case 'RegExp new line':
+      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+             check_true(input.source === '\\n', "input.source === '\\\\n'") &&
+             check_true(input.global === false, "input.global === false") &&
+             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+             check_true(input.multiline === false, "input.multiline === false") &&
+             check_true(input.lastIndex === 0, "input.lastIndex === 0");
+      break;
+    default:
+      check_true(false, 'check_RegExp: unknown test');
+      return false;
+      break;
+  }
+}
+
+function check_FileList(msg, input) {
+  try {
+    return check_true(input instanceof FileList, 'input instanceof FileList') &&
+           check_true(input.length === 0, 'input.length === 0');
+  } catch(ex) {
+    return check_true(false, ex);
+  }
+}
+
+function check(input, port) {
+  try {
+    switch (msg) {
+      case 'primitive undefined':
+        if (check_true(input === undefined, 'input === undefined')) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive null':
+        if (check_true(input === null, 'input === null')) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive true':
+        if (check_true(input === true, 'input === true')) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive false':
+        if (check_true(input === false, 'input === false')) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive string, empty string':
+        if (check_true(input === '', "input === ''")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive string, lone high surrogate':
+        if (check_true(input === '\uD800', "input === '\uD800'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive string, lone low surrogate':
+        if (check_true(input === '\uDC00', "input === '\uDC00'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive string, NUL':
+        if (check_true(input === '\u0000', "input === '\u0000'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive string, astral character':
+        if (check_true(input === '\uDBFF\uDFFD', "input === '\uDBFF\uDFFD'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, 0.2':
+        if (check_true(input === 0.2, "input === 0.2")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, 0':
+        if (check_true(input === 0, "input === 0") &&
+            check_true(1/input === Infinity, "1/input === Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, -0':
+        if (check_true(input === 0, "input === 0") &&
+            check_true(1/input === -Infinity, "1/input === -Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, NaN':
+        if (check_true(input !== input, "input !== input")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, Infinity':
+        if (check_true(input === Infinity, "input === Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, -Infinity':
+        if (check_true(input === -Infinity, "input === -Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, 9007199254740992':
+        if (check_true(input === 9007199254740992, "input === 9007199254740992")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, -9007199254740992':
+        if (check_true(input === -9007199254740992, "input === -9007199254740992")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, 9007199254740994':
+        if (check_true(input === 9007199254740994, "input === 9007199254740994")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'primitive number, -9007199254740994':
+        if (check_true(input === -9007199254740994, "input === -9007199254740994")) {
+          port.postMessage(input);
+          close();
+          break;
+        }
+      case 'Array primitives':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 19, 'input.length === 19') &&
+            check_true(input[0] === undefined, 'input[0] === undefined') &&
+            check_true(input[1] === null, 'input[1] === null') &&
+            check_true(input[2] === true, 'input[2] === true') &&
+            check_true(input[3] === false, 'input[3] === false') &&
+            check_true(input[4] === '', "input[4] === ''") &&
+            check_true(input[5] === '\uD800', "input[5] === '\\uD800'") &&
+            check_true(input[6] === '\uDC00', "input[6] === '\\uDC00'") &&
+            check_true(input[7] === '\u0000', "input[7] === '\\u0000'") &&
+            check_true(input[8] === '\uDBFF\uDFFD', "input[8] === '\\uDBFF\\uDFFD'") &&
+            check_true(input[9] === 0.2, "input[9] === 0.2") &&
+            check_true(1/input[10] === Infinity, "1/input[10] === Infinity") &&
+            check_true(1/input[11] === -Infinity, "1/input[11] === -Infinity") &&
+            check_true(input[12] !== input[11], "input[12] !== input[11]") &&
+            check_true(input[13] === Infinity, "input[13] === Infinity") &&
+            check_true(input[14] === -Infinity, "input[14] === -Infinity") &&
+            check_true(input[15] === 9007199254740992, "input[15] === 9007199254740992") &&
+            check_true(input[16] === -9007199254740992, "input[16] === -9007199254740992") &&
+            check_true(input[17] === 9007199254740994, "input[17] === 9007199254740994") &&
+            check_true(input[18] === -9007199254740994, "input[18] === -9007199254740994")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object primitives':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_true(input['undefined'] === undefined, "input['undefined'] === undefined") &&
+              check_true(input['null'] === null, "input['null'] === null") &&
+              check_true(input['true'] === true, "input['true'] === true") &&
+              check_true(input['false'] === false, "input['false'] === false") &&
+              check_true(input['empty'] === '', "input['empty'] === ''") &&
+              check_true(input['high surrogate'] === '\uD800', "input['high surrogate'] === '\uD800'") &&
+              check_true(input['low surrogate'] === '\uDC00', "input['low surrogate'] === '\uDC00'") &&
+              check_true(input['nul'] === '\u0000', "input['nul'] === '\u0000'") &&
+              check_true(input['astral'] === '\uDBFF\uDFFD', "input['astral'] === '\uDBFF\uDFFD'") &&
+              check_true(input['0.2'] === 0.2, "input['0.2'] === 0.2") &&
+              check_true(1/input['0'] === Infinity, "1/input['0'] === Infinity") &&
+              check_true(1/input['-0'] === -Infinity, "1/input['-0'] === -Infinity") &&
+              check_true(input['NaN'] !== input['NaN'], "input['NaN'] !== input['NaN']") &&
+              check_true(input['Infinity'] === Infinity, "input['Infinity'] === Infinity") &&
+              check_true(input['-Infinity'] === -Infinity, "input['-Infinity'] === -Infinity") &&
+              check_true(input['9007199254740992'] === 9007199254740992, "input['9007199254740992'] === 9007199254740992") &&
+              check_true(input['-9007199254740992'] === -9007199254740992, "input['-9007199254740992'] === -9007199254740992") &&
+              check_true(input['9007199254740994'] === 9007199254740994, "input['9007199254740994'] === 9007199254740994") &&
+              check_true(input['-9007199254740994'] === -9007199254740994, "input['9007199254740994'] === -9007199254740994")) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 19, 'i === 19')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'Boolean true':
+        if (check_true(input instanceof Boolean, "input instanceof Boolean") &&
+            check_true(String(input) === 'true', "String(input) === 'true'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Boolean false':
+        if (check_true(input instanceof Boolean, "input instanceof Boolean") &&
+            check_true(String(input) === 'false', "String(input) === 'false'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array Boolean objects':
+        (function() {
+          if (check_true(input instanceof Array, 'input instanceof Array') &&
+              check_true(input.length === 2, 'input.length === 2') &&
+              check_true(String(input[0]) === 'true', "String(input[0]) === 'true'") &&
+              check_true(String(input[1]) === 'false', "String(input[1]) === 'false'")) {
+            for (var i = 0; i < input.length; ++i) {
+              if (!check_true(input[i] instanceof Boolean, 'input['+i+'] instanceof Boolean'))
+                return;
+            }
+            port.postMessage(input);
+            close();
+          }
+        })();
+        break;
+      case 'Object Boolean objects':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_true(String(input['true']) === 'true', "String(input['true']) === 'true'") &&
+              check_true(String(input['false']) === 'false', "String(input['false']) === 'false'")) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+              if (!check_true(input[x] instanceof Boolean, 'input['+x+'] instanceof Boolean'))
+                return;
+            }
+            if (check_true(i === 2, 'i === 2')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'String empty string':
+        if (check_true(input instanceof String, "input instanceof String") &&
+            check_true(String(input) === '', "String(input) === ''")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'String lone high surrogate':
+        if (check_true(input instanceof String, "input instanceof String") &&
+            check_true(String(input) === '\uD800', "String(input) === '\\uD800'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'String lone low surrogate':
+        if (check_true(input instanceof String, "input instanceof String") &&
+            check_true(String(input) === '\uDC00', "String(input) === '\\uDC00'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'String NUL':
+        if (check_true(input instanceof String, "input instanceof String") &&
+            check_true(String(input) === '\u0000', "String(input) === '\\u0000'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'String astral character':
+        if (check_true(input instanceof String, "input instanceof String") &&
+            check_true(String(input) === '\uDBFF\uDFFD', "String(input) === '\\uDBFF\\uDFFD'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array String objects':
+        (function() {
+          if (check_true(input instanceof Array, 'input instanceof Array') &&
+              check_true(input.length === 5, 'input.length === 5') &&
+              check_true(String(input[0]) === '', "String(input[0]) === ''") &&
+              check_true(String(input[1]) === '\uD800', "String(input[1]) === '\\uD800'") &&
+              check_true(String(input[2]) === '\uDC00', "String(input[1]) === '\\uDC00'") &&
+              check_true(String(input[3]) === '\u0000', "String(input[2]) === '\\u0000'") &&
+              check_true(String(input[4]) === '\uDBFF\uDFFD', "String(input[3]) === '\\uDBFF\\uDFFD'")) {
+            for (var i = 0; i < input.length; ++i) {
+              if (!check_true(input[i] instanceof String, 'input['+i+'] instanceof String'))
+                return;
+            }
+            port.postMessage(input);
+            close();
+          }
+        })();
+        break;
+      case 'Object String objects':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_true(String(input['empty']) === '', "String(input['empty']) === ''") &&
+              check_true(String(input['high surrogate']) === '\uD800', "String(input['high surrogate']) === '\\uD800'") &&
+              check_true(String(input['low surrogate']) === '\uDC00', "String(input['low surrogate']) === '\\uDC00'") &&
+              check_true(String(input['nul']) === '\u0000', "String(input['nul']) === '\\u0000'") &&
+              check_true(String(input['astral']) === '\uDBFF\uDFFD', "String(input['astral']) === '\\uDBFF\\uDFFD'")) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+              if (!check_true(input[x] instanceof String, 'input['+x+'] instanceof Boolean'))
+                return;
+            }
+            if (check_true(i === 5, 'i === 5')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'Number 0.2':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(Number(input) === 0.2, "Number(input) === 0.2")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number 0':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(1/Number(input) === Infinity, "1/Number(input) === Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number -0':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(1/Number(input) === -Infinity, "1/Number(input) === -Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number NaN':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(Number(input) !== Number(input), "Number(input) !== Number(input)")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number Infinity':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(Number(input) === Infinity, "Number(input) === Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number -Infinity':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(Number(input) === -Infinity, "Number(input) === -Infinity")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number 9007199254740992':
+        if (check_true(input instanceof Number) &&
+            check_true(Number(input) === 9007199254740992, "Number(input) === 9007199254740992")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number -9007199254740992':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(Number(input) === -9007199254740992, "Number(input) === -9007199254740992")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number 9007199254740994':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(Number(input) === 9007199254740994, "Number(input) === 9007199254740994")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Number -9007199254740994':
+        if (check_true(input instanceof Number, "input instanceof Number") &&
+            check_true(Number(input) === -9007199254740994, "Number(input) === -9007199254740994")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array Number objects':
+        (function() {
+          if (check_true(input instanceof Array, 'input instanceof Array') &&
+              check_true(input.length === 10, 'input.length === 10') &&
+              check_true(Number(input[0]) === 0.2, "Number(input[0]) === 0.2") &&
+              check_true(1/Number(input[1]) === Infinity, "1/Number(input[1]) === Infinity") &&
+              check_true(1/Number(input[2]) === -Infinity, "1/Number(input[2]) === -Infinity") &&
+              check_true(Number(input[3]) !== Number(input[3]), "Number(input[3]) !== Number(input[3])") &&
+              check_true(Number(input[4]) === Infinity, "Number(input[4]) === Infinity") &&
+              check_true(Number(input[5]) === -Infinity, "Number(input[5]) === -Infinity") &&
+              check_true(Number(input[6]) === 9007199254740992, "Number(input[6]) === 9007199254740992") &&
+              check_true(Number(input[7]) === -9007199254740992, "Number(input[7]) === -9007199254740992") &&
+              check_true(Number(input[8]) === 9007199254740994, "Number(input[8]) === 9007199254740994") &&
+              check_true(Number(input[9]) === -9007199254740994, "Number(input[9]) === -9007199254740994")) {
+            for (var i = 0; i < input.length; ++i) {
+              if (!check_true(input[i] instanceof Number, 'input['+i+'] instanceof Number'))
+                return;
+            }
+            port.postMessage(input);
+            close();
+          }
+        })();
+        break;
+      case 'Object Number objects':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_true(Number(input['0.2']) === 0.2, "Number(input['0.2']) === 0.2") &&
+              check_true(1/Number(input['0']) === Infinity, "1/Number(input['0']) === Infinity") &&
+              check_true(1/Number(input['-0']) === -Infinity, "1/Number(input['-0']) === -Infinity") &&
+              check_true(Number(input['NaN']) !== Number(input['NaN']), "Number(input['NaN']) !== Number(input['NaN'])") &&
+              check_true(Number(input['Infinity']) === Infinity, "Number(input['Infinity']) === Infinity") &&
+              check_true(Number(input['-Infinity']) === -Infinity, "Number(input['-Infinity']) === -Infinity") &&
+              check_true(Number(input['9007199254740992']) === 9007199254740992, "Number(input['9007199254740992']) === 9007199254740992") &&
+              check_true(Number(input['-9007199254740992']) === -9007199254740992, "Number(input['-9007199254740992']) === -9007199254740992") &&
+              check_true(Number(input['9007199254740994']) === 9007199254740994, "Number(input['9007199254740994']) === 9007199254740994") &&
+              check_true(Number(input['-9007199254740994']) === -9007199254740994, "Number(input['-9007199254740994']) === -9007199254740994")) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+              if (!check_true(input[x] instanceof Number, 'input['+x+'] instanceof Number'))
+                return;
+            }
+            if (check_true(i === 10, 'i === 10')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'Date 0':
+        if (check_true(input instanceof Date, "input instanceof Date") &&
+            check_true(1/Number(input) === 1/Number(new Date(0)), "1/Number(input) === 1/Number(new Date(0))")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Date -0':
+        if (check_true(input instanceof Date, "input instanceof Date") &&
+            check_true(1/Number(input) === 1/Number(new Date(-0)), "1/Number(input) === 1/Number(new Date(-0))")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Date -8.64e15':
+        if (check_true(input instanceof Date, "input instanceof Date") &&
+            check_true(Number(input) === -8.64e15, "Number(input) === -8.64e15")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Date 8.64e15':
+        if (check_true(input instanceof Date, "input instanceof Date") &&
+            check_true(Number(input) === 8.64e15, "Number(input) === 8.64e15")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array Date objects':
+        (function() {
+          if (check_true(input instanceof Array, 'input instanceof Array') &&
+              check_true(input.length === 4, 'input.length === 4') &&
+              check_true(1/Number(input[0]) === 1/new Date(0), '1/Number(input[0]) === 1/new Date(0)') &&
+              check_true(1/Number(input[1]) === 1/new Date(-0), '1/Number(input[1]) === 1/new Date(-0)') &&
+              check_true(Number(input[2]) === -8.64e15, 'Number(input[2]) === -8.64e15') &&
+              check_true(Number(input[3]) === 8.64e15, 'Number(input[3]) === 8.64e15')) {
+            for (var i = 0; i < input.length; ++i) {
+              if (!check_true(input[i] instanceof Date, 'input['+i+'] instanceof Date'))
+                return;
+            }
+            port.postMessage(input);
+            close();
+          }
+        })();
+        break;
+      case 'Object Date objects':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_true(1/Number(input['0']) === 1/new Date(0), "1/Number(input['0']) === 1/new Date(0)") &&
+              check_true(1/Number(input['-0']) === 1/new Date(-0), "1/Number(input[1]) === 1/new Date(-0)") &&
+              check_true(Number(input['-8.64e15']) === -8.64e15, "Number(input['-8.64e15']) === -8.64e15") &&
+              check_true(Number(input['8.64e15']) === 8.64e15, "Number(input['8.64e15']) === 8.64e15")) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+              if (!check_true(input[x] instanceof Date, 'input['+x+'] instanceof Date'))
+                return;
+            }
+            port.postMessage(input);
+            close();
+          }
+        })();
+        break;
+      case 'RegExp flags and lastIndex':
+      case 'RegExp empty':
+      case 'RegExp slash':
+      case 'RegExp new line':
+        if (check_RegExp(msg, input)) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array RegExp object, RegExp flags and lastIndex':
+      case 'Array RegExp object, RegExp empty':
+      case 'Array RegExp object, RegExp slash':
+      case 'Array RegExp object, RegExp new line':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1') &&
+            check_RegExp(msg.substr('Array RegExp object, '.length), input[0])) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object RegExp object, RegExp flags and lastIndex':
+      case 'Object RegExp object, RegExp empty':
+      case 'Object RegExp object, RegExp slash':
+      case 'Object RegExp object, RegExp new line':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_RegExp(msg.substr('Object RegExp object, '.length), input['x'])) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 1, 'i === 1')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'Blob basic':
+      case 'Blob unpaired high surrogate (invalid utf-8)':
+      case 'Blob unpaired low surrogate (invalid utf-8)':
+      case 'Blob paired surrogates (invalid utf-8)':
+      case 'Blob empty':
+      case 'Blob NUL':
+        check_Blob(msg, input, port);
+        // no postMessage or close here, check_Blob takes care of that
+        break;
+      case 'Array Blob object, Blob basic':
+      case 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)':
+      case 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)':
+      case 'Array Blob object, Blob paired surrogates (invalid utf-8)':
+      case 'Array Blob object, Blob empty':
+      case 'Array Blob object, Blob NUL':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1')) {
+          check_Blob(msg.substr('Array Blob object, '.length), input[0], port, false, input);
+          // no postMessage or close here, check_Blob takes care of that
+        }
+        break;
+      case 'Object Blob object, Blob basic':
+      case 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)':
+      case 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)':
+      case 'Object Blob object, Blob paired surrogates (invalid utf-8)':
+      case 'Object Blob object, Blob empty':
+      case 'Object Blob object, Blob NUL':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)')) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 1, 'i === 1')) {
+              check_Blob(msg.substr('Object Blob object, '.length), input['x'], port, false, input);
+              // no postMessage or close here, check_Blob takes care of that
+            }
+          }
+        })();
+        break;
+      case 'File basic':
+        check_Blob(msg, input, port, true);
+        // no postMessage or close here, check_Blob takes care of that
+        break;
+      case 'FileList empty':
+        if (check_FileList(msg, input)) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array FileList object, FileList empty':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1') &&
+            check_FileList(msg.substr('Array FileList object, '.length), input[0])) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object FileList object, FileList empty':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_FileList(msg.substr('Array FileList object, '.length), input['x'])) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 1, 'i === 1')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'ImageData 1x1 transparent black':
+        if (check_ImageData(input, {width:1, height:1, data:[0,0,0,0]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'ImageData 1x1 non-transparent non-black':
+        if (check_ImageData(input, {width:1, height:1, data:[100, 101, 102, 103]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array ImageData object, ImageData 1x1 transparent black':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1') &&
+            check_ImageData(input[0], {width:1, height:1, data:[0,0,0,0]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array ImageData object, ImageData 1x1 non-transparent non-black':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1') &&
+            check_ImageData(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object ImageData object, ImageData 1x1 transparent black':
+        (function(){
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_ImageData(input['x'], {width:1, height:1, data:[0,0,0,0]})) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 1, 'i === 1')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'Object ImageData object, ImageData 1x1 non-transparent non-black':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_ImageData(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 1, 'i === 1')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'ImageBitmap 1x1 transparent black':
+        if (check_ImageBitmap(input, {width:1, height:1, data:[0, 0, 0, 0]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'ImageBitmap 1x1 non-transparent non-black':
+        if (check_ImageBitmap(input, {width:1, height:1, data:[100, 101, 102, 103]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array ImageBitmap object, ImageBitmap 1x1 transparent black':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1') &&
+            check_ImageBitmap(input[0], {width:1, height:1, data:[0, 0, 0, 0]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1') &&
+            check_ImageBitmap(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object ImageBitmap object, ImageBitmap 1x1 transparent black':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_ImageBitmap(input['x'], {width:1, height:1, data:[0, 0, 0, 0]})) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 1, 'i === 1')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black':
+        (function() {
+          if (check_true(input instanceof Object, 'input instanceof Object') &&
+              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+              check_ImageBitmap(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) {
+            var i = 0;
+            for (var x in input) {
+              i++;
+            }
+            if (check_true(i === 1, 'i === 1')) {
+              port.postMessage(input);
+              close();
+            }
+          }
+        })();
+        break;
+      case 'Array sparse':
+        (function() {
+          if (check_true(input instanceof Array, 'input instanceof Array') &&
+              check_true(input.length === 10, 'input.length === 10')) {
+            for (var x in input) {
+              check_true(false, 'unexpected enumerable property '+x);
+              return;
+            }
+            port.postMessage(input);
+            close();
+          }
+        })();
+        break;
+      case 'Array with non-index property':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 0, 'input.length === 0') &&
+            check_true(input.foo === 'bar', "input.foo === 'bar'")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object with index property and length':
+        if (check_true(input instanceof Object, 'input instanceof Object') &&
+            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+            check_true(input[0] === 'foo', "input[0] === 'foo'") &&
+            check_true(input.length === 1, 'input.length === 1')) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array with circular reference':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 1, 'input.length === 1') &&
+            check_true(input[0] === input, "input[0] === input")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object with circular reference':
+        if (check_true(input instanceof Object, 'input instanceof Object') &&
+            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+            check_true(input['x'] === input, "input['x'] === input")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Array with identical property values':
+        if (check_true(input instanceof Array, 'input instanceof Array') &&
+            check_true(input.length === 2, 'input.length === 2') &&
+            check_true(input[0] === input[1], "input[0] === input[1]")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object with identical property values':
+        if (check_true(input instanceof Object, 'input instanceof Object') &&
+            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+            check_true(input['x'] === input['y'], "input['x'] === input['y']")) {
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object with property on prototype':
+      case 'Object with non-enumerable property':
+        if (check_true(input instanceof Object, 'input instanceof Object') &&
+            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+            check_true(!('foo' in input), "!('foo' in input)")) {
+          input = {};
+          Object.defineProperty(input, 'foo', {value:'bar', enumerable:false, writable:true, configurable:true});
+          port.postMessage(input);
+          close();
+        }
+        break;
+      case 'Object with non-writable property':
+        if (check_true(input instanceof Object, 'input instanceof Object') &&
+            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+            check_true(input.foo === 'bar', "input.foo === bar")) {
+          input.foo += ' baz';
+          if (check_true(input.foo === 'bar baz', "input.foo === 'bar baz'")) {
+            input = {};
+            Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:false, configurable:true});
+            port.postMessage(input);
+            close();
+          }
+        }
+        break;
+      case 'Object with non-configurable property':
+        if (check_true(input instanceof Object, 'input instanceof Object') &&
+            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+            check_true(input.foo === 'bar', "input.foo === bar")) {
+          delete input.foo;
+          if (check_true(!('foo' in input), "!('foo' in input)")) {
+            input = {};
+            Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false});
+            port.postMessage(input);
+            close();
+          }
+        }
+        break;
+
+      default:
+        port.postMessage('FAIL: unknown test');
+        close();
+    }
+    if (log.length > 0) {
+      port.postMessage('FAIL '+log);
+      close();
+    }
+  } catch (ex) {
+    port.postMessage('FAIL '+ex);
+    close();
+  }
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/001.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/001.html
new file mode 100644
index 0000000..e26e21c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/001.html
@@ -0,0 +1,35 @@
+<!--
+var xhr = new XMLHttpRequest();
+var log = '';
+xhr.onreadystatechange = function(e) {
+  if (this.readyState == 4) {
+    if (this.responseXML != null)
+      log += 'responseXML was not null. ';
+    if (this.responseText != '<x>foo</x>')
+      log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. ';
+    postMessage(log);
+  }
+}
+xhr.open('GET', '001-1.xml', true);
+xhr.send();
+/*
+-->
+<!doctype html>
+<title>async XMLHttpRequest in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/002.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/002.html
new file mode 100644
index 0000000..0d3386e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/002.html
@@ -0,0 +1,32 @@
+<!--
+var xhr = new XMLHttpRequest();
+var log = '';
+xhr.open('GET', '001-1.xml', false);
+xhr.send();
+if (xhr.responseXML != null)
+  log += 'responseXML was not null. ';
+if (xhr.responseText != '<x>foo</x>')
+  log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. ';
+postMessage(log);
+
+/*
+-->
+<!doctype html>
+<title>sync XMLHttpRequest in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+  var worker = new Worker('#');
+  worker.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//-->
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/003.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/003.html
new file mode 100644
index 0000000..70edaf4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/003.html
@@ -0,0 +1,41 @@
+<!--
+onconnect = function(e) {
+  var xhr = new XMLHttpRequest();
+  var log = '';
+  var port = e.ports[0];
+  var postMessage = port.postMessage;
+  xhr.onreadystatechange = function(e) {
+    if (this.readyState == 4) {
+      if (this.responseXML != null)
+        log += 'responseXML was not null. ';
+      if (this.responseText && this.responseText != '<x>foo</x>')
+        log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. ';
+      postMessage.call(port, log);
+    }
+  }
+  xhr.open('GET', '001-1.xml', true);
+  xhr.send();
+}
+
+/*
+-->
+<!doctype html>
+<title>async XMLHttpRequest in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+  var worker = new SharedWorker('#', '');
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//-->
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/004.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/004.html
new file mode 100644
index 0000000..ec5893a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/004.html
@@ -0,0 +1,36 @@
+<!--
+onconnect = function(e) {
+  var xhr = new XMLHttpRequest();
+  var log = '';
+  xhr.open('GET', '001-1.xml', false);
+  xhr.send();
+  if (xhr.responseXML != null)
+    log += 'responseXML was not null. ';
+  if (xhr.responseText != '<x>foo</x>')
+    log += 'responseText was ' + xhr.responseText + ', expected <x>foo</x>. ';
+  e.ports[0].postMessage(log);
+}
+
+/*
+-->
+<!doctype html>
+<title>sync XMLHttpRequest in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+  var worker = new SharedWorker('#', '');
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_equals(e.data, '');
+    this.done();
+  });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//-->
+
+
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/005.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/005.html
new file mode 100644
index 0000000..84abdb0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/005.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>base url, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+var i = 0;
+function runtest() {
+  i++;
+  if (i != 2)
+    return;
+  var worker = new Worker('support/005-1.js');
+  worker.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<iframe src=support/001-1.xml onload="t.step(runtest);"></iframe>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/006.html b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/006.html
new file mode 100644
index 0000000..7411b4ba
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/006.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>base url, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+var i = 0;
+function runtest() {
+  i++;
+  if (i != 2)
+    return;
+  var worker = new SharedWorker('support/006-1.js','');
+  worker.port.onmessage = this.step_func(function(e) {
+    assert_true(e.data);
+    this.done();
+  });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<iframe src=support/001-1.xml onload="t.step(runtest);"></iframe>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/001-1.xml b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/001-1.xml
new file mode 100644
index 0000000..ecea58a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/001-1.xml
@@ -0,0 +1 @@
+<x>bar</x>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/005-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/005-1.js
new file mode 100644
index 0000000..45f6519
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/005-1.js
@@ -0,0 +1,5 @@
+var xhr = new XMLHttpRequest();
+xhr.open('GET', '001-1.xml', false);
+xhr.send();
+var passed = xhr.responseText == '<x>bar</x>';
+postMessage(passed);
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/006-1.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/006-1.js
new file mode 100644
index 0000000..d446781
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/semantics/xhr/support/006-1.js
@@ -0,0 +1,7 @@
+onconnect = function(e) {
+  var xhr = new XMLHttpRequest();
+  xhr.open('GET', '001-1.xml', false);
+  xhr.send();
+  var passed = xhr.responseText == '<x>bar</x>';
+  e.ports[0].postMessage(passed);
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent-error.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent-error.js
new file mode 100644
index 0000000..930b54c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent-error.js
@@ -0,0 +1,9 @@
+onerror = function(message, location, line, col, error) {
+  postMessage({ source: "onerror", value: error });
+}
+
+addEventListener("error", function(e) {
+  postMessage({ source: "event listener", value: e.error });
+});
+
+throw "hello";
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent.js
new file mode 100644
index 0000000..22ea6d4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ErrorEvent.js
@@ -0,0 +1,10 @@
+onmessage = function(evt)
+{
+    throw(new Error(evt.data));
+}
+
+onerror = function(message, location, line, col)
+{
+    postMessage( {"message": message, "filename": location, "lineno": line, "colno": col} );
+    return false; // "not handled" so the error propagates up to the Worker object
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScripts.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScripts.js
new file mode 100644
index 0000000..7f2a2bc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScripts.js
@@ -0,0 +1,9 @@
+try
+{
+    importScripts("WorkerBasic.js");
+}
+catch(ex)
+{
+    result = "Fail";
+    postMessage(result);
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScriptsNetworkErr.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScriptsNetworkErr.js
new file mode 100644
index 0000000..8179c8b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/ImportScriptsNetworkErr.js
@@ -0,0 +1,15 @@
+var result = "Fail";
+
+try
+{
+    importScripts("NonExistentFile.js");
+}
+catch(ex)
+{
+    if (ex.code != null && ex.code == ex.NETWORK_ERR)
+    {
+        result = "Pass";
+    }
+}
+
+postMessage(result);
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/Timer.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/Timer.js
new file mode 100644
index 0000000..a86a224
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/Timer.js
@@ -0,0 +1,50 @@
+var count = 0;
+var id;
+
+onmessage = function(evt)
+{
+    try
+    {
+        switch(evt.data)
+        {
+            case "TimeoutHandler":
+                count = 0;
+                id = setTimeout("TimeoutHandler()", 10);
+                postMessage('hello');
+                break;
+            case "IntervalHandler":
+                count = 0;
+                id = setInterval("IntervalHandler()", 10);
+                postMessage('hello');
+                break;
+        }
+    }
+    catch(ex)
+    {
+        postMessage("Fail");
+    }
+}
+
+function TimeoutHandler()
+{
+    count++;
+    postMessage("worker");
+
+    id = setTimeout("TimeoutHandler()", 10);
+
+    if (count >= 2)
+    {
+        clearTimeout(id);
+    }
+}
+
+function IntervalHandler()
+{
+    count++;
+    postMessage("worker");
+
+    if (count >= 2)
+    {
+        clearInterval(id);
+    }
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerBasic.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerBasic.js
new file mode 100644
index 0000000..6bb6d32
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerBasic.js
@@ -0,0 +1,7 @@
+var result = "Fail";
+
+onmessage = function(evt)
+{
+    result = "Pass";
+    postMessage(result);
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerClose.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerClose.js
new file mode 100644
index 0000000..81f9999
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerClose.js
@@ -0,0 +1,5 @@
+onmessage = function(evt)
+{
+    postMessage(evt.data);
+    self.close();
+}
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerDataCloneErr.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerDataCloneErr.js
new file mode 100644
index 0000000..b7e8b0a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerDataCloneErr.js
@@ -0,0 +1,15 @@
+var result = "Fail";
+
+try
+{
+    postMessage(navigator);
+}
+catch(ex)
+{
+    if(ex.code != null && ex.code == ex.DATA_CLONE_ERR)
+    {
+        result = "Pass";
+    }
+}
+
+postMessage(result);
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerLocation.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerLocation.js
new file mode 100644
index 0000000..a57e2fc6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerLocation.js
@@ -0,0 +1,12 @@
+var obj = new Object();
+obj.location = location.toString();
+obj.href     = location.href;
+obj.protocol = location.protocol;
+obj.host     = location.host;
+obj.hostname = location.hostname;
+obj.port     = location.port;
+obj.pathname = location.pathname;
+obj.search   = location.search;
+obj.hash     = location.hash;
+
+postMessage(obj);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerNavigator.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerNavigator.js
new file mode 100644
index 0000000..084e45b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerNavigator.js
@@ -0,0 +1,8 @@
+var obj = new Object();
+obj.appName    = navigator.appName;
+obj.appVersion = navigator.appVersion;
+obj.platform   = navigator.platform;
+obj.userAgent  = navigator.userAgent;
+obj.onLine     = navigator.onLine;
+
+postMessage(obj);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerTerminate.js b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerTerminate.js
new file mode 100644
index 0000000..7c99e7e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerTerminate.js
@@ -0,0 +1,10 @@
+onmessage = function(evt)
+{
+    for (var i=0; true; i++)
+    {
+        if (i%1000 == 0)
+        {
+            postMessage(i);
+        }
+    }
+}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerText.txt b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerText.txt
new file mode 100644
index 0000000..e4eeb539
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/imported/wpt/workers/support/WorkerText.txt
@@ -0,0 +1,2 @@
+var result = "Pass";
+postMessage(result);
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt
index 33ee647e..8df5a1d 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/transform-inline-layered-child-expected.txt
@@ -30,11 +30,6 @@
           "object": "LayoutText #text",
           "rect": [300, 302, 80, 176],
           "reason": "subtree"
-        },
-        {
-          "object": "LayoutText #text",
-          "rect": [151, 87, 1, 1],
-          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
index f0629205..7743960 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
@@ -19,10 +19,10 @@
           chunk 1 text run 1 at (25.00,85.00) startOffset 0 endOffset 75 width 417.60: "Pattern created using red and green rectangles applied to fill of rectangle"
       LayoutSVGResourcePattern {pattern} [id="pat2"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse]
         LayoutSVGRect {rect} at (281,33) size 14x13 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=10.00] [height=10.00]
-        LayoutSVGRect {rect} at (287,38) size 14x14 [fill={[type=SOLID] [color=#008000]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
+        LayoutSVGRect {rect} at (287,38) size 13x14 [fill={[type=SOLID] [color=#008000]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
         LayoutSVGRect {rect} at (275,38) size 14x14 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=10.00] [width=10.00] [height=10.00]
         LayoutSVGRect {rect} at (281,44) size 14x14 [fill={[type=SOLID] [color=#FFFF00]}] [x=10.00] [y=10.00] [width=10.00] [height=10.00]
-      LayoutSVGRect {rect} at (207,105) size 292x292 [stroke={[type=PATTERN] [id="pat2"] [stroke width=20.00]}] [x=35.00] [y=110.00] [width=410.00] [height=40.00]
+      LayoutSVGRect {rect} at (207,105) size 291x292 [stroke={[type=PATTERN] [id="pat2"] [stroke width=20.00]}] [x=35.00] [y=110.00] [width=410.00] [height=40.00]
       LayoutSVGText {text} at (25,163) size 322x16 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 322x16
           chunk 1 text run 1 at (25.00,175.00) startOffset 0 endOffset 59 width 321.60: "Pattern of 4 rectangles applied to a stroke of a rectangle."
@@ -37,7 +37,7 @@
           chunk 1 text run 1 at (25.00,235.00) startOffset 0 endOffset 38 width 212.40: "Pattern consists of red and green rows"
       LayoutSVGResourcePattern {pattern} [id="pat4"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse]
         LayoutSVGRect {rect} at (281,33) size 14x13 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=10.00] [height=10.00]
-        LayoutSVGRect {rect} at (287,38) size 14x14 [fill={[type=SOLID] [color=#0000FF]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
+        LayoutSVGRect {rect} at (287,38) size 13x14 [fill={[type=SOLID] [color=#0000FF]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
       LayoutSVGText {text} at (25,237) size 292x47 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 292x46
           chunk 1 text run 1 at (25.00,275.00) startOffset 0 endOffset 17 width 291.60: "Pattern on stroke"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png
index 0e0ccd2..48b628c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/editing/selection/transformed-selection-rects-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt
index 04c2773..b15fac01 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/transform-inline-layered-child-expected.txt
@@ -30,11 +30,6 @@
           "object": "LayoutText #text",
           "rect": [300, 301, 80, 161],
           "reason": "subtree"
-        },
-        {
-          "object": "LayoutText #text",
-          "rect": [147, 85, 1, 1],
-          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
index 7fc1f7a0c..883a4e7a 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
@@ -19,10 +19,10 @@
           chunk 1 text run 1 at (25.00,85.00) startOffset 0 endOffset 75 width 386.91: "Pattern created using red and green rectangles applied to fill of rectangle"
       LayoutSVGResourcePattern {pattern} [id="pat2"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse]
         LayoutSVGRect {rect} at (281,31) size 14x13 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=10.00] [height=10.00]
-        LayoutSVGRect {rect} at (287,36) size 14x14 [fill={[type=SOLID] [color=#008000]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
+        LayoutSVGRect {rect} at (287,36) size 13x14 [fill={[type=SOLID] [color=#008000]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
         LayoutSVGRect {rect} at (275,36) size 14x14 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=10.00] [width=10.00] [height=10.00]
         LayoutSVGRect {rect} at (281,42) size 14x14 [fill={[type=SOLID] [color=#FFFF00]}] [x=10.00] [y=10.00] [width=10.00] [height=10.00]
-      LayoutSVGRect {rect} at (207,103) size 292x292 [stroke={[type=PATTERN] [id="pat2"] [stroke width=20.00]}] [x=35.00] [y=110.00] [width=410.00] [height=40.00]
+      LayoutSVGRect {rect} at (207,103) size 291x292 [stroke={[type=PATTERN] [id="pat2"] [stroke width=20.00]}] [x=35.00] [y=110.00] [width=410.00] [height=40.00]
       LayoutSVGText {text} at (25,164) size 302x14 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 302x14
           chunk 1 text run 1 at (25.00,175.00) startOffset 0 endOffset 59 width 301.52: "Pattern of 4 rectangles applied to a stroke of a rectangle."
@@ -37,7 +37,7 @@
           chunk 1 text run 1 at (25.00,235.00) startOffset 0 endOffset 38 width 205.44: "Pattern consists of red and green rows"
       LayoutSVGResourcePattern {pattern} [id="pat4"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse]
         LayoutSVGRect {rect} at (281,31) size 14x13 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=10.00] [height=10.00]
-        LayoutSVGRect {rect} at (287,36) size 14x14 [fill={[type=SOLID] [color=#0000FF]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
+        LayoutSVGRect {rect} at (287,36) size 13x14 [fill={[type=SOLID] [color=#0000FF]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
       LayoutSVGText {text} at (25,239) size 305x45 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 305x45
           chunk 1 text run 1 at (25.00,275.00) startOffset 0 endOffset 17 width 304.58: "Pattern on stroke"
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png
index 3b5ff05..dad29547 100644
--- a/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/editing/selection/transformed-selection-rects-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt
index 564b65f..1b971517 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/transform-inline-layered-child-expected.txt
@@ -30,11 +30,6 @@
           "object": "LayoutText #text",
           "rect": [300, 301, 80, 160],
           "reason": "subtree"
-        },
-        {
-          "object": "LayoutText #text",
-          "rect": [147, 85, 1, 1],
-          "reason": "subtree"
         }
       ]
     }
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
index 317dbeb..6f471a9 100644
--- a/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/svg/transforms/text-with-pattern-inside-transformed-html-expected.txt
@@ -19,10 +19,10 @@
           chunk 1 text run 1 at (25.00,85.00) startOffset 0 endOffset 75 width 414.00: "Pattern created using red and green rectangles applied to fill of rectangle"
       LayoutSVGResourcePattern {pattern} [id="pat2"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse]
         LayoutSVGRect {rect} at (281,31) size 14x13 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=10.00] [height=10.00]
-        LayoutSVGRect {rect} at (287,36) size 14x14 [fill={[type=SOLID] [color=#008000]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
+        LayoutSVGRect {rect} at (287,36) size 13x14 [fill={[type=SOLID] [color=#008000]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
         LayoutSVGRect {rect} at (275,36) size 14x14 [fill={[type=SOLID] [color=#0000FF]}] [x=0.00] [y=10.00] [width=10.00] [height=10.00]
         LayoutSVGRect {rect} at (281,42) size 14x14 [fill={[type=SOLID] [color=#FFFF00]}] [x=10.00] [y=10.00] [width=10.00] [height=10.00]
-      LayoutSVGRect {rect} at (207,103) size 292x292 [stroke={[type=PATTERN] [id="pat2"] [stroke width=20.00]}] [x=35.00] [y=110.00] [width=410.00] [height=40.00]
+      LayoutSVGRect {rect} at (207,103) size 291x292 [stroke={[type=PATTERN] [id="pat2"] [stroke width=20.00]}] [x=35.00] [y=110.00] [width=410.00] [height=40.00]
       LayoutSVGText {text} at (25,163) size 320x16 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 320x16
           chunk 1 text run 1 at (25.00,175.00) startOffset 0 endOffset 59 width 319.20: "Pattern of 4 rectangles applied to a stroke of a rectangle."
@@ -37,7 +37,7 @@
           chunk 1 text run 1 at (25.00,235.00) startOffset 0 endOffset 38 width 211.20: "Pattern consists of red and green rows"
       LayoutSVGResourcePattern {pattern} [id="pat4"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse]
         LayoutSVGRect {rect} at (281,31) size 14x13 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=10.00] [height=10.00]
-        LayoutSVGRect {rect} at (287,36) size 14x14 [fill={[type=SOLID] [color=#0000FF]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
+        LayoutSVGRect {rect} at (287,36) size 13x14 [fill={[type=SOLID] [color=#0000FF]}] [x=10.00] [y=0.00] [width=10.00] [height=10.00]
       LayoutSVGText {text} at (25,239) size 305x45 contains 1 chunk(s)
         LayoutSVGInlineText {#text} at (0,0) size 305x45
           chunk 1 text run 1 at (25.00,275.00) startOffset 0 endOffset 17 width 304.58: "Pattern on stroke"
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/event-composed-path-with-related-target.html b/third_party/WebKit/LayoutTests/shadow-dom/event-composed-path-with-related-target.html
deleted file mode 100644
index 4fdd35c..0000000
--- a/third_party/WebKit/LayoutTests/shadow-dom/event-composed-path-with-related-target.html
+++ /dev/null
@@ -1,254 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="resources/shadow-dom.js"></script>
-
-<div id="test1">
-  <div id="target"></div>
-  <div id="related"></div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test1);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.related }));
-  let path = ['target', 'test1'];
-  assert_event_path_equals(log, [['target', 'target', 'related', path],
-                                 ['test1', 'target', 'related', path]]);
-}, 'Event path for an event with a relatedTarget. relatedTarget != target.');
-</script>
-
-<script>
-test(() => {
-  let n = createTestTree(test1);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.target }));
-  let path = ['target', 'test1'];
-  assert_event_path_equals(log, [['target', 'target', 'target', path],
-                                 ['test1', 'target', 'target', path]]);
-}, 'Event path for an event with a relatedTarget. Event shoul be dispatched if 1) target and relatedTarget are same, and 2) they are not in a shadow tree.');
-</script>
-
-<div id="test2">
-  <div id="host">
-    <template id="sr" data-mode="open">
-      <div id="target"></div>
-      <div id="related"></div>
-    </template>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test2);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.related }));
-  let path = ['target', 'sr'];
-  assert_event_path_equals(log, [['target', 'target', 'related', path],
-                                 ['sr', 'target', 'related', path]]);
-}, 'Event path for an event with a relatedTarget. Event should stop at the shadow root');
-
-test(() => {
-  let n = createTestTree(test2);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.target }));
-  assert_event_path_equals(log, []);
-}, 'Event path for an event with a relatedTarget. Event should not be dispatched if 1) target and relatedTarget are same, and 2) both are in a shadow tree.');
-</script>
-
-<div id="test3_1">
-  <div id="host1">
-    <template id="sr1" data-mode="open">
-      <div id="target1"></div>
-    </template>
-  </div>
-</div>
-
-<div id="test3_2">
-  <div id="host2">
-    <template id="sr2" data-mode="open">
-      <div id="target2"></div>
-    </template>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n1 = createTestTree(test3_1);
-  let n2 = createTestTree(test3_2);
-  let log = dispatchEventWithLog(n1, n1.target1, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n2.target2 }));
-  let path = ['target1', 'sr1', 'host1', 'test3_1'];
-  assert_event_path_equals(log, [['target1', 'target1', 'host2', path],
-                                 ['sr1',     'target1', 'host2', path],
-                                 ['host1',   'host1',   'host2', path],
-                                 ['test3_1', 'host1',   'host2', path]]);
-}, 'Event path for an event with a relatedTarget. target and relaterTarget do not share any shadow-including ancestor. target is in a shadow tree.');
-
-test(() => {
-  let n1 = createTestTree(test3_1);
-  let n2 = createTestTree(test3_2);
-  let log = dispatchEventWithLog(n1, n1.host1, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n2.target2 }));
-  let path = ['host1', 'test3_1'];
-  assert_event_path_equals(log, [['host1',   'host1',   'host2', path],
-                                 ['test3_1', 'host1',   'host2', path]]);
-}, 'Event path for an event with a relatedTarget. target and relaterTarget do not share any shadow-including ancestor. target is not in a shadow tree');
-</script>
-
-<div id="test4">
-  <div id="host1">
-    <template id="sr1" data-mode="open">
-      <div id="host2">
-        <template id="sr2" data-mode="open">
-          <div id="target"></div>
-        </template>
-      </div>
-      <div id="host3">
-        <template id="sr3" data-mode="open">
-          <div id="related"></div>
-        </template>
-      </div>
-    </template>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test4);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.related }));
-  let path = ['target', 'sr2', 'host2', 'sr1'];
-  assert_event_path_equals(log, [['target', 'target', 'host3', path],
-                                 ['sr2', 'target', 'host3', path],
-                                 ['host2', 'host2', 'host3', path],
-                                 ['sr1', 'host2', 'host3', path]]);
-}, 'Event path for an event with a relatedTarget. target and relaterTarget share the same shadow-including ancestor. Both are in shadow trees.');
-
-test(() => {
-  let n = createTestTree(test4);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.host1 }));
-  let path = ['target', 'sr2', 'host2', 'sr1'];
-  assert_event_path_equals(log, [['target', 'target', 'host1', path],
-                                 ['sr2', 'target', 'host1', path],
-                                 ['host2', 'host2', 'host1', path],
-                                 ['sr1', 'host2', 'host1', path]]);
-}, 'Event path for an event with a relatedTarget. relaterTarget is a shadow-including ancestor of target.');
-
-test(() => {
-  let n = createTestTree(test4);
-  let log = dispatchEventWithLog(n, n.host1, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.target }));
-  assert_event_path_equals(log, []);
-}, 'Event path for an event with a relatedTarget. target is a shadow-including ancestor of relatedTarget.');
-</script>
-
-<div id="test5">
-  <div id="host">
-    <template id="sr" data-mode="open">
-      <slot id="slot"></slot>
-      <div id="related"></div>
-    </template>
-    <div id="target"></div>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test5);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.related }));
-  let path = ['target', 'slot', 'sr', 'host', 'test5'];
-  assert_event_path_equals(log, [['target', 'target', 'host', path],
-                                 ['slot', 'target', 'related', path],
-                                 ['sr', 'target', 'related', path],
-                                 ['host', 'target', 'host', path],
-                                 ['test5', 'target', 'host', path]]);
-}, 'Event path for an event with a relatedTarget. target is assigned to a slot.');
-
-test(() => {
-  let n = createTestTree(test5);
-  let log = dispatchEventWithLog(n, n.related, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.target }));
-  let path = ['related', 'sr', 'host', 'test5'];
-  assert_event_path_equals(log, [['related', 'related', 'target', path],
-                                 ['sr', 'related', 'target', path],
-                                 ['host', 'host', 'target', path],
-                                 ['test5', 'host', 'target', path]]);
-}, 'Event path for an event with a relatedTarget. relatedTarget is assigned to a slot.');
-</script>
-
-<div id="test6">
-  <div id="host0">
-    <template id="sr0" data-mode="open">
-      <div id="host1">
-        <template id="sr1" data-mode="open">
-          <div id="host2">
-            <template id="sr2" data-mode="open">
-              <slot id="slot2"></slot>
-              <div id="related2"></div>
-            </template>
-            <div id="related1"></div>
-            <div id="d1">
-              <slot id="slot1"></slot>
-            </div>
-          </div>
-        </template>
-        <div id="host3">
-          <template id="sr3" data-mode="open">
-            <div id="host4">
-              <template id="sr4" data-mode="open">
-                <div id="host5">
-                  <template id="sr5" data-mode="open">
-                    <slot id="slot5"></slot>
-                  </template>
-                  <slot id="slot4"></slot>
-                </div>
-              </template>
-              <div id="target"></div>
-            </div>
-          </template>
-        </div>
-      </div>
-    </template>
-  </div>
-</div>
-
-<script>
-test(() => {
-  let n = createTestTree(test6);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.related1 }));
-  let path = ['target', 'slot4', 'slot5', 'sr5', 'host5', 'sr4', 'host4', 'sr3', 'host3', 'slot1', 'd1', 'slot2', 'sr2', 'host2', 'sr1', 'host1', 'sr0'];
-  assert_event_path_equals(log, [['target',  'target', 'host1',    path],
-                                 ['slot4',   'target', 'host1',    path],
-                                 ['slot5',   'target', 'host1',    path],
-                                 ['sr5',     'target', 'host1',    path],
-                                 ['host5',   'target', 'host1',    path],
-                                 ['sr4',     'target', 'host1',    path],
-                                 ['host4',   'target', 'host1',    path],
-                                 ['sr3',     'target', 'host1',    path],
-                                 ['host3',   'host3',  'host1',    path],
-                                 ['slot1',   'host3',  'related1', path],
-                                 ['d1'   ,   'host3',  'related1', path],
-                                 ['slot2',   'host3',  'related1', path],
-                                 ['sr2',     'host3',  'related1', path],
-                                 ['host2',   'host3',  'related1', path],
-                                 ['sr1',     'host3',  'related1', path],
-                                 ['host1',   'host3',  'host1',    path],
-                                 ['sr0',     'host3',  'host1'   , path]]);
-}, 'Event path for an event with a relatedTarget. Event should be dispatched at every slots.');
-
-test(() => {
-  let n = createTestTree(test6);
-  let log = dispatchEventWithLog(n, n.target, new FocusEvent('my-focus', { bubbles: true, composed: true, relatedTarget: n.related2 }));
-  let path = ['target', 'slot4', 'slot5', 'sr5', 'host5', 'sr4', 'host4', 'sr3', 'host3', 'slot1', 'd1', 'slot2', 'sr2', 'host2', 'sr1', 'host1', 'sr0'];
-  assert_event_path_equals(log, [['target',  'target', 'host1',    path],
-                                 ['slot4',   'target', 'host1',    path],
-                                 ['slot5',   'target', 'host1',    path],
-                                 ['sr5',     'target', 'host1',    path],
-                                 ['host5',   'target', 'host1',    path],
-                                 ['sr4',     'target', 'host1',    path],
-                                 ['host4',   'target', 'host1',    path],
-                                 ['sr3',     'target', 'host1',    path],
-                                 ['host3',   'host3',  'host1',    path],
-                                 ['slot1',   'host3',  'host2',    path],
-                                 ['d1'   ,   'host3',  'host2',    path],
-                                 ['slot2',   'host3',  'related2', path],
-                                 ['sr2',     'host3',  'related2', path],
-                                 ['host2',   'host3',  'host2',    path],
-                                 ['sr1',     'host3',  'host2',    path],
-                                 ['host1',   'host3',  'host1',    path],
-                                 ['sr0',     'host3',  'host1'   , path]]);
-}, 'Event path for an event with a relatedTarget. Event should be dispatched at every slots. relatedTarget should be correctly retargeted.');
-</script>
diff --git a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
index 76cedce..adcb6c7 100644
--- a/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
+++ b/third_party/WebKit/Source/bindings/core/v8/BUILD.gn
@@ -121,8 +121,6 @@
   "$blink_core_output_dir/imagebitmap/ImageBitmapOptions.h",
   "$blink_core_output_dir/input/InputDeviceCapabilitiesInit.cpp",
   "$blink_core_output_dir/input/InputDeviceCapabilitiesInit.h",
-  "$blink_core_output_dir/page/EventSourceInit.cpp",
-  "$blink_core_output_dir/page/EventSourceInit.h",
   "$blink_core_output_dir/page/scrolling/ScrollStateInit.cpp",
   "$blink_core_output_dir/page/scrolling/ScrollStateInit.h",
   "$blink_core_output_dir/timing/PerformanceObserverInit.cpp",
diff --git a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
index e1b488395..93ef605 100644
--- a/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
+++ b/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py
@@ -97,6 +97,8 @@
         self._update_dependencies_include_paths(definition_name)
 
     def _update_dependencies_include_paths(self, definition_name):
+        if definition_name not in self.info_provider.interfaces_info:
+            return
         interface_info = self.info_provider.interfaces_info[definition_name]
         interface_info['additional_header_includes'] = set(
             self.additional_header_includes)
@@ -340,8 +342,10 @@
     def __init__(self, info_provider, cache_dir, output_dir, target_component):
         CodeGeneratorBase.__init__(self, MODULE_PYNAME, info_provider, cache_dir, output_dir)
         self.target_component = target_component
+        self.typedef_resolver = TypedefResolver(info_provider)
 
     def generate_code_internal(self, callback_function, path):
+        self.typedef_resolver.resolve(callback_function, callback_function.name)
         header_template = self.jinja_env.get_template('callback_function.h.tmpl')
         cpp_template = self.jinja_env.get_template('callback_function.cpp.tmpl')
         template_context = v8_callback_function.callback_function_context(
diff --git a/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl b/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl
index 1671210..eaa345c 100644
--- a/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl
+++ b/third_party/WebKit/Source/bindings/tests/idls/core/TestObject.idl
@@ -36,6 +36,7 @@
 callback LongCallbackFunction = long (long num1, long num2);
 callback VoidCallbackFunctionInterfaceArg = void (HTMLDivElement divElement);
 callback StringSequenceCallbackFunctionLongSequenceArg = sequence<DOMString> (sequence<long> arg);
+callback VoidCallbackFunctionTypedef = void (String arg);
 
 // No extended attributes on the interface; those go in TestInterface.idl
 interface TestObject {
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/VoidCallbackFunctionTypedef.cpp b/third_party/WebKit/Source/bindings/tests/results/core/VoidCallbackFunctionTypedef.cpp
new file mode 100644
index 0000000..ba327d9b
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/tests/results/core/VoidCallbackFunctionTypedef.cpp
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY!
+
+// clang-format off
+
+#include "VoidCallbackFunctionTypedef.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/ScriptState.h"
+#include "bindings/core/v8/ToV8.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "core/dom/ExecutionContext.h"
+#include "wtf/Assertions.h"
+
+namespace blink {
+
+VoidCallbackFunctionTypedef::VoidCallbackFunctionTypedef(v8::Isolate* isolate, v8::Local<v8::Function> callback)
+    : m_callback(isolate, callback)
+{
+    DCHECK(!m_callback.isEmpty());
+    m_callback.setPhantom();
+}
+
+DEFINE_TRACE(VoidCallbackFunctionTypedef)
+{
+}
+
+bool VoidCallbackFunctionTypedef::call(ScriptState* scriptState, ScriptWrappable* scriptWrappable, const String& arg)
+{
+    if (!scriptState->contextIsValid())
+        return false;
+
+    ExecutionContext* context = scriptState->getExecutionContext();
+    DCHECK(context);
+    if (context->activeDOMObjectsAreSuspended() || context->activeDOMObjectsAreStopped())
+        return false;
+
+    if (m_callback.isEmpty())
+        return false;
+
+    // TODO(bashi): Make sure that using TrackExceptionState is OK.
+    // crbug.com/653769
+    TrackExceptionState exceptionState;
+    ScriptState::Scope scope(scriptState);
+
+    v8::Local<v8::Value> argArgument = v8String(scriptState->isolate(), arg);
+
+    v8::Local<v8::Value> thisValue = toV8(scriptWrappable, scriptState->context()->Global(), scriptState->isolate());
+
+    v8::Local<v8::Value> argv[] = { argArgument };
+
+    v8::Local<v8::Value> v8ReturnValue;
+    v8::TryCatch exceptionCatcher(scriptState->isolate());
+    exceptionCatcher.SetVerbose(true);
+
+    if (V8ScriptRunner::callFunction(m_callback.newLocal(scriptState->isolate()), scriptState->getExecutionContext(), thisValue, 1, argv, scriptState->isolate()).ToLocal(&v8ReturnValue))
+    {
+        return true;
+    }
+    return false;
+}
+
+} // namespace blink
diff --git a/third_party/WebKit/Source/bindings/tests/results/core/VoidCallbackFunctionTypedef.h b/third_party/WebKit/Source/bindings/tests/results/core/VoidCallbackFunctionTypedef.h
new file mode 100644
index 0000000..4f56398
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/tests/results/core/VoidCallbackFunctionTypedef.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file has been auto-generated by code_generator_v8.py. DO NOT MODIFY!
+
+// clang-format off
+
+#ifndef VoidCallbackFunctionTypedef_h
+#define VoidCallbackFunctionTypedef_h
+
+#include "bindings/core/v8/ScopedPersistent.h"
+#include "core/CoreExport.h"
+#include "platform/heap/Handle.h"
+#include "wtf/text/WTFString.h"
+
+namespace blink {
+
+class ScriptState;
+
+class CORE_EXPORT VoidCallbackFunctionTypedef final : public GarbageCollectedFinalized<VoidCallbackFunctionTypedef> {
+public:
+    static VoidCallbackFunctionTypedef* create(v8::Isolate* isolate, v8::Local<v8::Function> callback)
+    {
+        return new VoidCallbackFunctionTypedef(isolate, callback);
+    }
+
+    ~VoidCallbackFunctionTypedef() = default;
+
+    DECLARE_TRACE();
+
+    bool call(ScriptState* scriptState, ScriptWrappable* scriptWrappable, const String& arg);
+
+    v8::Local<v8::Function> v8Value(v8::Isolate* isolate)
+    {
+        return m_callback.newLocal(isolate);
+    }
+
+    void setWrapperReference(v8::Isolate* isolate, const v8::Persistent<v8::Object>& wrapper)
+    {
+        DCHECK(!m_callback.isEmpty());
+        m_callback.setReference(wrapper, isolate);
+    }
+
+private:
+    VoidCallbackFunctionTypedef(v8::Isolate* isolate, v8::Local<v8::Function>);
+    ScopedPersistent<v8::Function> m_callback;
+};
+
+} // namespace blink
+
+#endif // VoidCallbackFunctionTypedef_h
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 4e71be67..2eb90f313 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1073,6 +1073,7 @@
     "editing/PositionTest.cpp",
     "editing/RelocatablePositionTest.cpp",
     "editing/SelectionAdjusterTest.cpp",
+    "editing/SelectionTemplateTest.cpp",
     "editing/SurroundingTextTest.cpp",
     "editing/VisiblePositionTest.cpp",
     "editing/VisibleSelectionTest.cpp",
@@ -1208,7 +1209,6 @@
     "origin_trials/OriginTrialContextTest.cpp",
     "page/ChromeClientTest.cpp",
     "page/ContextMenuControllerTest.cpp",
-    "page/EventSourceParserTest.cpp",
     "page/FocusControllerTest.cpp",
     "page/NetworkStateNotifierTest.cpp",
     "page/PagePopupClientTest.cpp",
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni
index d683a9bb..655387b 100644
--- a/third_party/WebKit/Source/core/core_idl_files.gni
+++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -288,7 +288,6 @@
                                  "observer/ResizeObserver.idl",
                                  "observer/ResizeObserverCallback.idl",
                                  "observer/ResizeObserverEntry.idl",
-                                 "page/EventSource.idl",
                                  "page/PagePopupController.idl",
                                  "page/scrolling/ScrollState.idl",
                                  "page/scrolling/ScrollStateCallback.idl",
@@ -561,7 +560,6 @@
                     "html/track/TrackEventInit.idl",
                     "imagebitmap/ImageBitmapOptions.idl",
                     "input/InputDeviceCapabilitiesInit.idl",
-                    "page/EventSourceInit.idl",
                     "page/scrolling/ScrollStateInit.idl",
                     "timing/PerformanceObserverInit.idl",
                   ],
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.cpp b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
index 35113d0..228921c 100644
--- a/third_party/WebKit/Source/core/css/StylePropertySet.cpp
+++ b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
@@ -347,19 +347,17 @@
 
 bool MutableStylePropertySet::setProperty(const CSSProperty& property,
                                           CSSProperty* slot) {
-  if (!removeShorthandProperty(property.id())) {
-    const AtomicString& name =
-        (property.id() == CSSPropertyVariable)
-            ? toCSSCustomPropertyDeclaration(property.value())->name()
-            : nullAtom;
-    CSSProperty* toReplace =
-        slot ? slot : findCSSPropertyWithID(property.id(), name);
-    if (toReplace && *toReplace == property)
-      return false;
-    if (toReplace) {
-      *toReplace = property;
-      return true;
-    }
+  const AtomicString& name =
+      (property.id() == CSSPropertyVariable)
+          ? toCSSCustomPropertyDeclaration(property.value())->name()
+          : nullAtom;
+  CSSProperty* toReplace =
+      slot ? slot : findCSSPropertyWithID(property.id(), name);
+  if (toReplace && *toReplace == property)
+    return false;
+  if (toReplace) {
+    *toReplace = property;
+    return true;
   }
   m_propertyVector.append(property);
   return true;
diff --git a/third_party/WebKit/Source/core/editing/BUILD.gn b/third_party/WebKit/Source/core/editing/BUILD.gn
index b85c46fe..8587385 100644
--- a/third_party/WebKit/Source/core/editing/BUILD.gn
+++ b/third_party/WebKit/Source/core/editing/BUILD.gn
@@ -54,6 +54,8 @@
     "SelectionEditor.h",
     "SelectionModifier.cpp",
     "SelectionModifier.h",
+    "SelectionTemplate.cpp",
+    "SelectionTemplate.h",
     "SelectionType.h",
     "SurroundingText.cpp",
     "SurroundingText.h",
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp
index 01c581c..6e52b6a 100644
--- a/third_party/WebKit/Source/core/editing/Editor.cpp
+++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -672,12 +672,6 @@
   return hasEditableStyle(*startContainer) && hasEditableStyle(*endContainer);
 }
 
-void Editor::notifyComponentsOnChangedSelection() {
-  client().respondToChangedSelection(m_frame,
-                                     frame().selection().getSelectionType());
-  setStartNewKillRingSequence(true);
-}
-
 void Editor::respondToChangedContents(const VisibleSelection& endingSelection) {
   if (frame().settings() && frame().settings()->accessibilityEnabled()) {
     Node* node = endingSelection.start().anchorNode();
@@ -1559,7 +1553,9 @@
     FrameSelection::SetSelectionOptions options) {
   spellChecker().respondToChangedSelection(oldSelection, options);
   frame().inputMethodController().cancelCompositionIfSelectionIsInvalid();
-  notifyComponentsOnChangedSelection();
+  client().respondToChangedSelection(&frame(),
+                                     frame().selection().getSelectionType());
+  setStartNewKillRingSequence(true);
 }
 
 SpellChecker& Editor::spellChecker() const {
diff --git a/third_party/WebKit/Source/core/editing/Editor.h b/third_party/WebKit/Source/core/editing/Editor.h
index 6db54cf..abe4db1c 100644
--- a/third_party/WebKit/Source/core/editing/Editor.h
+++ b/third_party/WebKit/Source/core/editing/Editor.h
@@ -343,7 +343,6 @@
       RevealExtentOption = DoNotRevealExtent);
   void changeSelectionAfterCommand(const VisibleSelection& newSelection,
                                    FrameSelection::SetSelectionOptions);
-  void notifyComponentsOnChangedSelection();
 
   SpellChecker& spellChecker() const;
 
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp
new file mode 100644
index 0000000..4640df7
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.cpp
@@ -0,0 +1,263 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/editing/SelectionTemplate.h"
+
+#include "wtf/Assertions.h"
+#include <ostream>  // NOLINT
+
+namespace blink {
+
+template <typename Strategy>
+SelectionTemplate<Strategy>::SelectionTemplate(const SelectionTemplate& other)
+    : m_base(other.m_base),
+      m_extent(other.m_extent),
+      m_affinity(other.m_affinity),
+      m_granularity(other.m_granularity),
+      m_hasTrailingWhitespace(other.m_hasTrailingWhitespace),
+      m_isDirectional(other.m_isDirectional)
+#if DCHECK_IS_ON()
+      ,
+      m_domTreeVersion(other.m_domTreeVersion)
+#endif
+{
+  DCHECK(other.assertValid());
+  if (!m_hasTrailingWhitespace)
+    return;
+  DCHECK_EQ(m_granularity, WordGranularity) << *this;
+}
+
+template <typename Strategy>
+SelectionTemplate<Strategy>::SelectionTemplate() = default;
+
+template <typename Strategy>
+bool SelectionTemplate<Strategy>::operator==(
+    const SelectionTemplate& other) const {
+  DCHECK(assertValid());
+  DCHECK(other.assertValid());
+  if (isNone())
+    return other.isNone();
+  if (other.isNone())
+    return false;
+  DCHECK_EQ(m_base.document(), other.document()) << *this << ' ' << other;
+  return m_base == other.m_base && m_extent == other.m_extent &&
+         m_affinity == other.m_affinity &&
+         m_granularity == other.m_granularity &&
+         m_hasTrailingWhitespace == other.m_hasTrailingWhitespace &&
+         m_isDirectional == other.m_isDirectional;
+}
+
+template <typename Strategy>
+bool SelectionTemplate<Strategy>::operator!=(
+    const SelectionTemplate& other) const {
+  return !operator==(other);
+}
+
+template <typename Strategy>
+const PositionTemplate<Strategy>& SelectionTemplate<Strategy>::base() const {
+  DCHECK(assertValid());
+  DCHECK(!m_base.isOrphan()) << m_base;
+  return m_base;
+}
+
+template <typename Strategy>
+Document* SelectionTemplate<Strategy>::document() const {
+  DCHECK(assertValid());
+  return m_base.document();
+}
+
+template <typename Strategy>
+const PositionTemplate<Strategy>& SelectionTemplate<Strategy>::extent() const {
+  DCHECK(assertValid());
+  DCHECK(!m_extent.isOrphan()) << m_extent;
+  return m_extent;
+}
+
+template <typename Strategy>
+bool SelectionTemplate<Strategy>::assertValidFor(
+    const Document& document) const {
+  if (!assertValid())
+    return false;
+  if (m_base.isNull())
+    return true;
+  DCHECK_EQ(m_base.document(), document) << *this;
+  return true;
+}
+
+#if DCHECK_IS_ON()
+template <typename Strategy>
+bool SelectionTemplate<Strategy>::assertValid() const {
+  if (m_base.isNull())
+    return true;
+  DCHECK_EQ(m_base.document()->domTreeVersion(), m_domTreeVersion) << *this;
+  DCHECK(!m_base.isOrphan()) << *this;
+  DCHECK(!m_extent.isOrphan()) << *this;
+  DCHECK_EQ(m_base.document(), m_extent.document());
+  return true;
+}
+#else
+template <typename Strategy>
+bool SelectionTemplate<Strategy>::assertValid() const {
+  return true;
+}
+#endif
+
+template <typename Strategy>
+void SelectionTemplate<Strategy>::printTo(std::ostream* ostream,
+                                          const char* type) const {
+  if (isNone()) {
+    *ostream << "()";
+    return;
+  }
+  *ostream << type << '(';
+#if DCHECK_IS_ON()
+  if (m_domTreeVersion != m_base.document()->domTreeVersion()) {
+    *ostream << "Dirty: " << m_domTreeVersion;
+    *ostream << " != " << m_base.document()->domTreeVersion() << ' ';
+  }
+#endif
+  *ostream << "base: " << m_base << ", extent: " << m_extent << ')';
+}
+
+std::ostream& operator<<(std::ostream& ostream,
+                         const SelectionInDOMTree& selection) {
+  selection.printTo(&ostream, "Selection");
+  return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream,
+                         const SelectionInFlatTree& selection) {
+  selection.printTo(&ostream, "SelectionInFlatTree");
+  return ostream;
+}
+
+// --
+
+template <typename Strategy>
+SelectionTemplate<Strategy>::Builder::Builder(
+    const SelectionTemplate<Strategy>& selection)
+    : m_selection(selection) {}
+
+template <typename Strategy>
+SelectionTemplate<Strategy>::Builder::Builder() = default;
+
+template <typename Strategy>
+SelectionTemplate<Strategy> SelectionTemplate<Strategy>::Builder::build()
+    const {
+  DCHECK(m_selection.assertValid());
+  return m_selection;
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::collapse(
+    const PositionTemplate<Strategy>& position) {
+  DCHECK(position.isConnected());
+  m_selection.m_base = position;
+  m_selection.m_extent = position;
+#if DCHECK_IS_ON()
+  m_selection.m_domTreeVersion = position.document()->domTreeVersion();
+#endif
+  return *this;
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::collapse(
+    const PositionWithAffinityTemplate<Strategy>& positionWithAffinity) {
+  collapse(positionWithAffinity.position());
+  setAffinity(positionWithAffinity.affinity());
+  return *this;
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::extend(
+    const PositionTemplate<Strategy>& position) {
+  DCHECK(position.isConnected());
+  DCHECK_EQ(m_selection.document(), position.document());
+  DCHECK(m_selection.base().isConnected());
+  DCHECK(m_selection.assertValid());
+  m_selection.m_extent = position;
+  return *this;
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::setAffinity(TextAffinity affinity) {
+  m_selection.m_affinity = affinity;
+  return *this;
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::setBaseAndExtent(
+    const EphemeralRangeTemplate<Strategy>& range) {
+  if (range.isNull()) {
+    m_selection.m_base = PositionTemplate<Strategy>();
+    m_selection.m_extent = PositionTemplate<Strategy>();
+#if DCHECK_IS_ON()
+    m_selection.m_domTreeVersion = 0;
+#endif
+    return *this;
+  }
+  return collapse(range.startPosition()).extend(range.endPosition());
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::setBaseAndExtent(
+    const PositionTemplate<Strategy>& base,
+    const PositionTemplate<Strategy>& extent) {
+  if (base.isNull()) {
+    DCHECK(extent.isNull()) << extent;
+    return setBaseAndExtent(EphemeralRangeTemplate<Strategy>());
+  }
+  DCHECK(extent.isNotNull());
+  return collapse(base).extend(extent);
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::setBaseAndExtentDeprecated(
+    const PositionTemplate<Strategy>& base,
+    const PositionTemplate<Strategy>& extent) {
+  if (base.isNotNull() && extent.isNotNull()) {
+    return setBaseAndExtent(base, extent);
+  }
+  if (base.isNotNull())
+    return collapse(base);
+  if (extent.isNotNull())
+    return collapse(extent);
+  return setBaseAndExtent(EphemeralRangeTemplate<Strategy>());
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::setGranularity(
+    TextGranularity granularity) {
+  m_selection.m_granularity = granularity;
+  return *this;
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::setHasTrailingWhitespace(
+    bool hasTrailingWhitespace) {
+  m_selection.m_hasTrailingWhitespace = hasTrailingWhitespace;
+  return *this;
+}
+
+template <typename Strategy>
+typename SelectionTemplate<Strategy>::Builder&
+SelectionTemplate<Strategy>::Builder::setIsDirectional(bool isDirectional) {
+  m_selection.m_isDirectional = isDirectional;
+  return *this;
+}
+
+template class CORE_TEMPLATE_EXPORT SelectionTemplate<EditingStrategy>;
+template class CORE_TEMPLATE_EXPORT
+    SelectionTemplate<EditingInFlatTreeStrategy>;
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplate.h b/third_party/WebKit/Source/core/editing/SelectionTemplate.h
new file mode 100644
index 0000000..c4189ab8
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/SelectionTemplate.h
@@ -0,0 +1,130 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SelectionTemplate_h
+#define SelectionTemplate_h
+
+#include "base/macros.h"
+#include "core/CoreExport.h"
+#include "core/editing/EphemeralRange.h"
+#include "core/editing/Position.h"
+#include "core/editing/PositionWithAffinity.h"
+#include "core/editing/TextAffinity.h"
+#include "core/editing/TextGranularity.h"
+#include "wtf/Allocator.h"
+#include <iosfwd>
+
+namespace blink {
+
+// SelectionTemplate is used for representing a selection in DOM tree or Flat
+// tree with template parameter |Strategy|. Instances of |SelectionTemplate|
+// are immutable objects, you can't change them once constructed.
+//
+// To construct |SelectionTemplate| object, please use |Builder| class.
+template <typename Strategy>
+class CORE_EXPORT SelectionTemplate final {
+  DISALLOW_NEW();
+
+ public:
+  // |Builder| is a helper class for constructing |SelectionTemplate| object.
+  class CORE_EXPORT Builder final {
+    DISALLOW_NEW();
+
+   public:
+    explicit Builder(const SelectionTemplate&);
+    Builder();
+
+    SelectionTemplate build() const;
+
+    // Move selection to |base|. |base| can't be null.
+    Builder& collapse(const PositionTemplate<Strategy>& base);
+    Builder& collapse(const PositionWithAffinityTemplate<Strategy>& base);
+
+    // Extend selection to |extent|. It is error if selection is none.
+    // |extent| can be in different tree scope of base, but should be in same
+    // document.
+    Builder& extend(const PositionTemplate<Strategy>& extent);
+
+    Builder& setBaseAndExtent(const EphemeralRangeTemplate<Strategy>&);
+
+    // |extent| can not be null if |base| isn't null.
+    Builder& setBaseAndExtent(const PositionTemplate<Strategy>& base,
+                              const PositionTemplate<Strategy>& extent);
+
+    // |extent| can be non-null while |base| is null, which is undesired.
+    // Note: This function should be used only in "core/editing/commands".
+    // TODO(yosin): Once all we get rid of all call sites, we remove this.
+    Builder& setBaseAndExtentDeprecated(
+        const PositionTemplate<Strategy>& base,
+        const PositionTemplate<Strategy>& extent);
+
+    Builder& setAffinity(TextAffinity);
+    Builder& setGranularity(TextGranularity);
+    Builder& setHasTrailingWhitespace(bool);
+    Builder& setIsDirectional(bool);
+
+   private:
+    SelectionTemplate m_selection;
+
+    DISALLOW_COPY_AND_ASSIGN(Builder);
+  };
+
+  SelectionTemplate(const SelectionTemplate& other);
+  SelectionTemplate();
+
+  SelectionTemplate& operator=(const SelectionTemplate&) = default;
+
+  bool operator==(const SelectionTemplate&) const;
+  bool operator!=(const SelectionTemplate&) const;
+
+  const PositionTemplate<Strategy>& base() const;
+  const PositionTemplate<Strategy>& extent() const;
+  TextAffinity affinity() const { return m_affinity; }
+  TextGranularity granularity() const { return m_granularity; }
+  bool hasTrailingWhitespace() const { return m_hasTrailingWhitespace; }
+  bool isDirectional() const { return m_isDirectional; }
+  bool isNone() const { return m_base.isNull(); }
+
+  // Returns true if |this| selection holds valid values otherwise it causes
+  // assertion failure.
+  bool assertValid() const;
+  bool assertValidFor(const Document&) const;
+
+  DEFINE_INLINE_TRACE() {
+    visitor->trace(m_base);
+    visitor->trace(m_extent);
+  }
+
+  void printTo(std::ostream*, const char* type) const;
+
+ private:
+  friend class SelectionEditor;
+
+  Document* document() const;
+
+  PositionTemplate<Strategy> m_base;
+  PositionTemplate<Strategy> m_extent;
+  TextAffinity m_affinity = TextAffinity::Downstream;
+  TextGranularity m_granularity = CharacterGranularity;
+  bool m_hasTrailingWhitespace = false;
+  bool m_isDirectional = false;
+#if DCHECK_IS_ON()
+  uint64_t m_domTreeVersion;
+#endif
+};
+
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+    SelectionTemplate<EditingStrategy>;
+extern template class CORE_EXTERN_TEMPLATE_EXPORT
+    SelectionTemplate<EditingInFlatTreeStrategy>;
+
+using SelectionInDOMTree = SelectionTemplate<EditingStrategy>;
+using SelectionInFlatTree = SelectionTemplate<EditingInFlatTreeStrategy>;
+
+CORE_EXPORT std::ostream& operator<<(std::ostream&, const SelectionInDOMTree&);
+CORE_EXPORT std::ostream& operator<<(std::ostream&, const SelectionInFlatTree&);
+
+}  // namespace blink
+
+#endif  // SelectionTemplate_h
diff --git a/third_party/WebKit/Source/core/editing/SelectionTemplateTest.cpp b/third_party/WebKit/Source/core/editing/SelectionTemplateTest.cpp
new file mode 100644
index 0000000..e1f9864
--- /dev/null
+++ b/third_party/WebKit/Source/core/editing/SelectionTemplateTest.cpp
@@ -0,0 +1,64 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/editing/SelectionTemplate.h"
+
+#include "core/editing/EditingTestBase.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class SelectionTest : public EditingTestBase {};
+
+TEST_F(SelectionTest, defaultConstructor) {
+  SelectionInDOMTree selection;
+
+  EXPECT_EQ(TextAffinity::Downstream, selection.affinity());
+  EXPECT_EQ(CharacterGranularity, selection.granularity());
+  EXPECT_FALSE(selection.hasTrailingWhitespace());
+  EXPECT_FALSE(selection.isDirectional());
+  EXPECT_TRUE(selection.isNone());
+  EXPECT_EQ(Position(), selection.base());
+  EXPECT_EQ(Position(), selection.extent());
+}
+
+TEST_F(SelectionTest, caret) {
+  setBodyContent("<div id='sample'>abcdef</div>");
+
+  Element* sample = document().getElementById("sample");
+  Position position(Position(sample->firstChild(), 2));
+  SelectionInDOMTree::Builder builder;
+  builder.collapse(position);
+  const SelectionInDOMTree& selection = builder.build();
+
+  EXPECT_EQ(TextAffinity::Downstream, selection.affinity());
+  EXPECT_EQ(CharacterGranularity, selection.granularity());
+  EXPECT_FALSE(selection.hasTrailingWhitespace());
+  EXPECT_FALSE(selection.isDirectional());
+  EXPECT_FALSE(selection.isNone());
+  EXPECT_EQ(position, selection.base());
+  EXPECT_EQ(position, selection.extent());
+}
+
+TEST_F(SelectionTest, range) {
+  setBodyContent("<div id='sample'>abcdef</div>");
+
+  Element* sample = document().getElementById("sample");
+  Position base(Position(sample->firstChild(), 2));
+  Position extent(Position(sample->firstChild(), 4));
+  SelectionInDOMTree::Builder builder;
+  builder.collapse(base);
+  builder.extend(extent);
+  const SelectionInDOMTree& selection = builder.build();
+
+  EXPECT_EQ(TextAffinity::Downstream, selection.affinity());
+  EXPECT_EQ(CharacterGranularity, selection.granularity());
+  EXPECT_FALSE(selection.hasTrailingWhitespace());
+  EXPECT_FALSE(selection.isDirectional());
+  EXPECT_FALSE(selection.isNone());
+  EXPECT_EQ(base, selection.base());
+  EXPECT_EQ(extent, selection.extent());
+}
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/VisiblePosition.cpp b/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
index 8e85aef..63009d22 100644
--- a/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
+++ b/third_party/WebKit/Source/core/editing/VisiblePosition.cpp
@@ -97,11 +97,6 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy> VisiblePositionTemplate<Strategy>::afterNode(
     Node* node) {
-  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  if (node)
-    node->document().updateStyleAndLayoutIgnorePendingStylesheets();
-
   return create(PositionWithAffinityTemplate<Strategy>(
       PositionTemplate<Strategy>::afterNode(node)));
 }
@@ -109,11 +104,6 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy> VisiblePositionTemplate<Strategy>::beforeNode(
     Node* node) {
-  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  if (node)
-    node->document().updateStyleAndLayoutIgnorePendingStylesheets();
-
   return create(PositionWithAffinityTemplate<Strategy>(
       PositionTemplate<Strategy>::beforeNode(node)));
 }
@@ -121,11 +111,6 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy>
 VisiblePositionTemplate<Strategy>::firstPositionInNode(Node* node) {
-  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  if (node)
-    node->document().updateStyleAndLayoutIgnorePendingStylesheets();
-
   return create(PositionWithAffinityTemplate<Strategy>(
       PositionTemplate<Strategy>::firstPositionInNode(node)));
 }
@@ -133,10 +118,6 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy>
 VisiblePositionTemplate<Strategy>::inParentAfterNode(const Node& node) {
-  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  node.document().updateStyleAndLayoutIgnorePendingStylesheets();
-
   return create(PositionWithAffinityTemplate<Strategy>(
       PositionTemplate<Strategy>::inParentAfterNode(node)));
 }
@@ -144,10 +125,6 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy>
 VisiblePositionTemplate<Strategy>::inParentBeforeNode(const Node& node) {
-  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  node.document().updateStyleAndLayoutIgnorePendingStylesheets();
-
   return create(PositionWithAffinityTemplate<Strategy>(
       PositionTemplate<Strategy>::inParentBeforeNode(node)));
 }
@@ -155,11 +132,6 @@
 template <typename Strategy>
 VisiblePositionTemplate<Strategy>
 VisiblePositionTemplate<Strategy>::lastPositionInNode(Node* node) {
-  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
-  // needs to be audited.  See http://crbug.com/590369 for more details.
-  if (node)
-    node->document().updateStyleAndLayoutIgnorePendingStylesheets();
-
   return create(PositionWithAffinityTemplate<Strategy>(
       PositionTemplate<Strategy>::lastPositionInNode(node)));
 }
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
index 051d6dd..04d893e 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -411,17 +411,15 @@
 }
 
 template <typename Strategy>
-void VisibleSelectionTemplate<Strategy>::setStartRespectingGranularity(
+static PositionTemplate<Strategy> computeStartRespectingGranularity(
+    const PositionWithAffinityTemplate<Strategy>& passedStart,
     TextGranularity granularity) {
-  DCHECK(m_base.isNotNull());
-  DCHECK(m_extent.isNotNull());
-
-  m_start = m_baseIsFirst ? m_base : m_extent;
+  DCHECK(passedStart.isNotNull());
 
   switch (granularity) {
     case CharacterGranularity:
       // Don't do any expansion.
-      break;
+      return passedStart.position();
     case WordGranularity: {
       // General case: Select the word the caret is positioned inside of.
       // If the caret is on the word boundary, select the word according to
@@ -433,68 +431,54 @@
       // from the the end of the last word to the line break (also
       // RightWordIfOnBoundary);
       const VisiblePositionTemplate<Strategy> visibleStart =
-          createVisiblePosition(m_start, m_affinity);
-      EWordSide side = RightWordIfOnBoundary;
+          createVisiblePosition(passedStart);
       if (isEndOfEditableOrNonEditableContent(visibleStart) ||
           (isEndOfLine(visibleStart) && !isStartOfLine(visibleStart) &&
-           !isEndOfParagraph(visibleStart)))
-        side = LeftWordIfOnBoundary;
-      m_start = startOfWord(visibleStart, side).deepEquivalent();
-      break;
+           !isEndOfParagraph(visibleStart))) {
+        return startOfWord(visibleStart, LeftWordIfOnBoundary).deepEquivalent();
+      }
+      return startOfWord(visibleStart, RightWordIfOnBoundary).deepEquivalent();
     }
-    case SentenceGranularity: {
-      m_start = startOfSentence(createVisiblePosition(m_start, m_affinity))
-                    .deepEquivalent();
-      break;
-    }
-    case LineGranularity: {
-      m_start = startOfLine(createVisiblePosition(m_start, m_affinity))
-                    .deepEquivalent();
-      break;
-    }
+    case SentenceGranularity:
+      return startOfSentence(createVisiblePosition(passedStart))
+          .deepEquivalent();
+    case LineGranularity:
+      return startOfLine(createVisiblePosition(passedStart)).deepEquivalent();
     case LineBoundary:
-      m_start = startOfLine(createVisiblePosition(m_start, m_affinity))
-                    .deepEquivalent();
-      break;
+      return startOfLine(createVisiblePosition(passedStart)).deepEquivalent();
     case ParagraphGranularity: {
-      VisiblePositionTemplate<Strategy> pos =
-          createVisiblePosition(m_start, m_affinity);
+      const VisiblePositionTemplate<Strategy> pos =
+          createVisiblePosition(passedStart);
       if (isStartOfLine(pos) && isEndOfEditableOrNonEditableContent(pos))
-        pos = previousPositionOf(pos);
-      m_start = startOfParagraph(pos).deepEquivalent();
-      break;
+        return startOfParagraph(previousPositionOf(pos)).deepEquivalent();
+      return startOfParagraph(pos).deepEquivalent();
     }
     case DocumentBoundary:
-      m_start = startOfDocument(createVisiblePosition(m_start, m_affinity))
-                    .deepEquivalent();
-      break;
+      return startOfDocument(createVisiblePosition(passedStart))
+          .deepEquivalent();
     case ParagraphBoundary:
-      m_start = startOfParagraph(createVisiblePosition(m_start, m_affinity))
-                    .deepEquivalent();
-      break;
+      return startOfParagraph(createVisiblePosition(passedStart))
+          .deepEquivalent();
     case SentenceBoundary:
-      m_start = startOfSentence(createVisiblePosition(m_start, m_affinity))
-                    .deepEquivalent();
-      break;
+      return startOfSentence(createVisiblePosition(passedStart))
+          .deepEquivalent();
   }
 
-  // Make sure we do not have a Null position.
-  if (m_start.isNull())
-    m_start = m_baseIsFirst ? m_base : m_extent;
+  NOTREACHED();
+  return passedStart.position();
 }
 
 template <typename Strategy>
-void VisibleSelectionTemplate<Strategy>::setEndRespectingGranularity(
+static PositionTemplate<Strategy> computeEndRespectingGranularity(
+    const PositionTemplate<Strategy>& start,
+    const PositionWithAffinityTemplate<Strategy>& passedEnd,
     TextGranularity granularity) {
-  DCHECK(m_base.isNotNull());
-  DCHECK(m_extent.isNotNull());
-
-  m_end = m_baseIsFirst ? m_extent : m_base;
+  DCHECK(passedEnd.isNotNull());
 
   switch (granularity) {
     case CharacterGranularity:
       // Don't do any expansion.
-      break;
+      return passedEnd.position();
     case WordGranularity: {
       // General case: Select the word the caret is positioned inside of.
       // If the caret is on the word boundary, select the word according to
@@ -506,7 +490,7 @@
       // from the the end of the last word to the line break (also
       // |RightWordIfOnBoundary|);
       const VisiblePositionTemplate<Strategy> originalEnd =
-          createVisiblePosition(m_end, m_affinity);
+          createVisiblePosition(passedEnd);
       EWordSide side = RightWordIfOnBoundary;
       if (isEndOfEditableOrNonEditableContent(originalEnd) ||
           (isEndOfLine(originalEnd) && !isStartOfLine(originalEnd) &&
@@ -515,98 +499,89 @@
 
       const VisiblePositionTemplate<Strategy> wordEnd =
           endOfWord(originalEnd, side);
-      VisiblePositionTemplate<Strategy> end = wordEnd;
+      if (!isEndOfParagraph(originalEnd))
+        return wordEnd.deepEquivalent();
+      if (isEmptyTableCell(start.anchorNode()))
+        return wordEnd.deepEquivalent();
 
-      if (isEndOfParagraph(originalEnd) &&
-          !isEmptyTableCell(m_start.anchorNode())) {
-        // Select the paragraph break (the space from the end of a paragraph
-        // to the start of the next one) to match TextEdit.
-        end = nextPositionOf(wordEnd);
-
-        if (Element* table = tableElementJustBefore(end)) {
-          // The paragraph break after the last paragraph in the last cell
-          // of a block table ends at the start of the paragraph after the
-          // table.
-          if (isEnclosingBlock(table))
-            end = nextPositionOf(end, CannotCrossEditingBoundary);
-          else
-            end = wordEnd;
-        }
-
+      // Select the paragraph break (the space from the end of a paragraph
+      // to the start of the next one) to match TextEdit.
+      const VisiblePositionTemplate<Strategy> end = nextPositionOf(wordEnd);
+      Element* const table = tableElementJustBefore(end);
+      if (!table) {
         if (end.isNull())
-          end = wordEnd;
+          return wordEnd.deepEquivalent();
+        return end.deepEquivalent();
       }
 
-      m_end = end.deepEquivalent();
-      break;
+      if (!isEnclosingBlock(table))
+        return wordEnd.deepEquivalent();
+
+      // The paragraph break after the last paragraph in the last cell
+      // of a block table ends at the start of the paragraph after the
+      // table.
+      const VisiblePositionTemplate<Strategy> next =
+          nextPositionOf(end, CannotCrossEditingBoundary);
+      if (next.isNull())
+        return wordEnd.deepEquivalent();
+      return next.deepEquivalent();
     }
-    case SentenceGranularity: {
-      m_end = endOfSentence(createVisiblePosition(m_end, m_affinity))
-                  .deepEquivalent();
-      break;
-    }
+    case SentenceGranularity:
+      return endOfSentence(createVisiblePosition(passedEnd)).deepEquivalent();
     case LineGranularity: {
-      VisiblePositionTemplate<Strategy> end =
-          endOfLine(createVisiblePosition(m_end, m_affinity));
+      const VisiblePositionTemplate<Strategy> end =
+          endOfLine(createVisiblePosition(passedEnd));
+      if (!isEndOfParagraph(end))
+        return end.deepEquivalent();
       // If the end of this line is at the end of a paragraph, include the
       // space after the end of the line in the selection.
-      if (isEndOfParagraph(end)) {
-        VisiblePositionTemplate<Strategy> next = nextPositionOf(end);
-        if (next.isNotNull())
-          end = next;
-      }
-      m_end = end.deepEquivalent();
-      break;
+      const VisiblePositionTemplate<Strategy> next = nextPositionOf(end);
+      if (next.isNull())
+        return end.deepEquivalent();
+      return next.deepEquivalent();
     }
     case LineBoundary:
-      m_end =
-          endOfLine(createVisiblePosition(m_end, m_affinity)).deepEquivalent();
-      break;
+      return endOfLine(createVisiblePosition(passedEnd)).deepEquivalent();
     case ParagraphGranularity: {
       const VisiblePositionTemplate<Strategy> visibleParagraphEnd =
-          endOfParagraph(createVisiblePosition(m_end, m_affinity));
+          endOfParagraph(createVisiblePosition(passedEnd));
 
       // Include the "paragraph break" (the space from the end of this
       // paragraph to the start of the next one) in the selection.
-      VisiblePositionTemplate<Strategy> end =
+      const VisiblePositionTemplate<Strategy> end =
           nextPositionOf(visibleParagraphEnd);
 
-      if (Element* table = tableElementJustBefore(end)) {
-        // The paragraph break after the last paragraph in the last cell of
-        // a block table ends at the start of the paragraph after the table,
-        // not at the position just after the table.
-        if (isEnclosingBlock(table)) {
-          end = nextPositionOf(end, CannotCrossEditingBoundary);
-        } else {
-          // There is no parargraph break after the last paragraph in the
-          // last cell of an inline table.
-          end = visibleParagraphEnd;
-        }
+      Element* const table = tableElementJustBefore(end);
+      if (!table) {
+        if (end.isNull())
+          return visibleParagraphEnd.deepEquivalent();
+        return end.deepEquivalent();
       }
 
-      if (end.isNull())
-        end = visibleParagraphEnd;
+      if (!isEnclosingBlock(table)) {
+        // There is no paragraph break after the last paragraph in the
+        // last cell of an inline table.
+        return visibleParagraphEnd.deepEquivalent();
+      }
 
-      m_end = end.deepEquivalent();
-      break;
+      // The paragraph break after the last paragraph in the last cell of
+      // a block table ends at the start of the paragraph after the table,
+      // not at the position just after the table.
+      const VisiblePositionTemplate<Strategy> next =
+          nextPositionOf(end, CannotCrossEditingBoundary);
+      if (next.isNull())
+        return visibleParagraphEnd.deepEquivalent();
+      return next.deepEquivalent();
     }
     case DocumentBoundary:
-      m_end = endOfDocument(createVisiblePosition(m_end, m_affinity))
-                  .deepEquivalent();
-      break;
+      return endOfDocument(createVisiblePosition(passedEnd)).deepEquivalent();
     case ParagraphBoundary:
-      m_end = endOfParagraph(createVisiblePosition(m_end, m_affinity))
-                  .deepEquivalent();
-      break;
+      return endOfParagraph(createVisiblePosition(passedEnd)).deepEquivalent();
     case SentenceBoundary:
-      m_end = endOfSentence(createVisiblePosition(m_end, m_affinity))
-                  .deepEquivalent();
-      break;
+      return endOfSentence(createVisiblePosition(passedEnd)).deepEquivalent();
   }
-
-  // Make sure we do not have a Null position.
-  if (m_end.isNull())
-    m_end = m_baseIsFirst ? m_extent : m_base;
+  NOTREACHED();
+  return passedEnd.position();
 }
 
 template <typename Strategy>
@@ -633,12 +608,17 @@
     return;
   }
 
-  m_start = m_baseIsFirst ? m_base : m_extent;
-  m_end = m_baseIsFirst ? m_extent : m_base;
-  setStartRespectingGranularity(granularity);
-  DCHECK(m_start.isNotNull());
-  setEndRespectingGranularity(granularity);
-  DCHECK(m_end.isNotNull());
+  const PositionTemplate<Strategy> start = m_baseIsFirst ? m_base : m_extent;
+  const PositionTemplate<Strategy> newStart = computeStartRespectingGranularity(
+      PositionWithAffinityTemplate<Strategy>(start, m_affinity), granularity);
+  m_start = newStart.isNotNull() ? newStart : start;
+
+  const PositionTemplate<Strategy> end = m_baseIsFirst ? m_extent : m_base;
+  const PositionTemplate<Strategy> newEnd = computeEndRespectingGranularity(
+      m_start, PositionWithAffinityTemplate<Strategy>(end, m_affinity),
+      granularity);
+  m_end = newEnd.isNotNull() ? newEnd : end;
+
   adjustSelectionToAvoidCrossingShadowBoundaries();
   adjustSelectionToAvoidCrossingEditingBoundaries();
   updateSelectionType();
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.h b/third_party/WebKit/Source/core/editing/VisibleSelection.h
index c558d24..4c68c5a3 100644
--- a/third_party/WebKit/Source/core/editing/VisibleSelection.h
+++ b/third_party/WebKit/Source/core/editing/VisibleSelection.h
@@ -172,8 +172,6 @@
   void setBaseAndExtentToDeepEquivalents();
   void adjustSelectionToAvoidCrossingShadowBoundaries();
   void adjustSelectionToAvoidCrossingEditingBoundaries();
-  void setEndRespectingGranularity(TextGranularity);
-  void setStartRespectingGranularity(TextGranularity);
   void updateSelectionType();
 
   // We need to store these as Positions because VisibleSelection is
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
index 82b4762..8b78769 100644
--- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -56,6 +56,7 @@
   if (!isHTMLTableRowElement(row))
     return false;
 
+  row->document().updateStyleAndLayoutIgnorePendingStylesheets();
   for (Node* child = row->firstChild(); child; child = child->nextSibling()) {
     if (isTableCell(child) && !isTableCellEmpty(child))
       return false;
@@ -414,11 +415,13 @@
   // FIXME: This code doesn't belong in here.
   // We detect the case where the start is an empty line consisting of BR not
   // wrapped in a block element.
-  if (upstreamStartIsBR && downstreamStartIsBR &&
-      !(isStartOfBlock(VisiblePosition::beforeNode(nodeAfterUpstreamStart)) &&
-        isEndOfBlock(VisiblePosition::afterNode(nodeAfterUpstreamStart)))) {
-    m_startsAtEmptyLine = true;
-    m_endingPosition = m_downstreamEnd;
+  if (upstreamStartIsBR && downstreamStartIsBR) {
+    document().updateStyleAndLayoutIgnorePendingStylesheets();
+    if (!(isStartOfBlock(VisiblePosition::beforeNode(nodeAfterUpstreamStart)) &&
+          isEndOfBlock(VisiblePosition::afterNode(nodeAfterUpstreamStart)))) {
+      m_startsAtEmptyLine = true;
+      m_endingPosition = m_downstreamEnd;
+    }
   }
 
   return false;
@@ -490,6 +493,7 @@
     return;
   }
 
+  document().updateStyleAndLayoutIgnorePendingStylesheets();
   if (node == m_startBlock) {
     VisiblePosition previous = previousPositionOf(
         VisiblePosition::firstPositionInNode(m_startBlock.get()));
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
index d51cc9f..9b16ad8 100644
--- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -361,6 +361,7 @@
       if (editingState->isAborted())
         return false;
 
+      document().updateStyleAndLayoutIgnorePendingStylesheets();
       Node* firstChildInList =
           enclosingListChild(VisiblePosition::firstPositionInNode(listElement)
                                  .deepEquivalent()
@@ -401,6 +402,7 @@
         currentSelection.setEnd(newList, Position::lastOffsetInNode(newList),
                                 IGNORE_EXCEPTION);
 
+      document().updateStyleAndLayoutIgnorePendingStylesheets();
       setEndingSelection(VisiblePosition::firstPositionInNode(newList));
 
       return true;
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
index 8eb0a689..2242aaec 100644
--- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -627,6 +627,8 @@
                        AtomicString(newInlineStyle->style()->asText()));
     }
 
+    document().updateStyleAndLayoutIgnorePendingStylesheets();
+
     // FIXME: Tolerate differences in id, class, and style attributes.
     if (element->parentNode() && isNonTableCellHTMLBlockElement(element) &&
         areIdenticalElements(*element, *element->parentNode()) &&
@@ -1475,6 +1477,7 @@
       return;
   }
 
+  document().updateStyleAndLayoutIgnorePendingStylesheets();
   if (endBR &&
       (plainTextFragment ||
        (shouldRemoveEndBR(endBR, originalVisPosBeforeEndBR) &&
@@ -1611,6 +1614,7 @@
           if (editingState->isAborted())
             return;
         }
+        document().updateStyleAndLayoutIgnorePendingStylesheets();
         setEndingSelection(
             VisiblePosition::afterNode(insertedNodes.lastLeafInserted()));
         // Select up to the paragraph separator that was added.
@@ -1625,6 +1629,7 @@
           insertNodeAfter(newListItem, enclosingBlockElement, editingState);
           if (editingState->isAborted())
             return;
+          document().updateStyleAndLayoutIgnorePendingStylesheets();
           setEndingSelection(VisiblePosition::firstPositionInNode(newListItem));
         } else {
           // Use a default paragraph element (a plain div) for the empty
diff --git a/third_party/WebKit/Source/core/events/EventPath.cpp b/third_party/WebKit/Source/core/events/EventPath.cpp
index 28c8bb6..95d95b5 100644
--- a/third_party/WebKit/Source/core/events/EventPath.cpp
+++ b/third_party/WebKit/Source/core/events/EventPath.cpp
@@ -300,7 +300,7 @@
   if (target.document() != relatedNode->document())
     return;
   retargetRelatedTarget(*relatedNode);
-  shrinkForRelatedTarget(target, *relatedNode);
+  shrinkForRelatedTarget(target);
 }
 
 void EventPath::retargetRelatedTarget(const Node& relatedTargetNode) {
@@ -315,13 +315,22 @@
   }
 }
 
-void EventPath::shrinkForRelatedTarget(const Node& target,
-                                       const Node& relatedTarget) {
-  if (!target.isInShadowTree() && !relatedTarget.isInShadowTree())
-    return;
+bool EventPath::shouldStopEventPath(EventTarget& currentTarget,
+                                    EventTarget& currentRelatedTarget,
+                                    const Node& target) {
+  if (&currentTarget != &currentRelatedTarget)
+    return false;
+  if (m_event->isTrusted())
+    return true;
+  Node* currentTargetNode = currentTarget.toNode();
+  if (!currentTargetNode)
+    return false;
+  return currentTargetNode->treeScope() != target.treeScope();
+}
+
+void EventPath::shrinkForRelatedTarget(const Node& target) {
   for (size_t i = 0; i < size(); ++i) {
-    if (at(i).target() == at(i).relatedTarget()) {
-      // Event dispatching should be stopped here.
+    if (shouldStopEventPath(*at(i).target(), *at(i).relatedTarget(), target)) {
       shrink(i);
       break;
     }
diff --git a/third_party/WebKit/Source/core/events/EventPath.h b/third_party/WebKit/Source/core/events/EventPath.h
index 1eefb91..544c77f7 100644
--- a/third_party/WebKit/Source/core/events/EventPath.h
+++ b/third_party/WebKit/Source/core/events/EventPath.h
@@ -91,6 +91,10 @@
   void calculateAdjustedTargets();
   void calculateTreeOrderAndSetNearestAncestorClosedTree();
 
+  bool shouldStopEventPath(EventTarget& currentTarget,
+                           EventTarget& currentRelatedTarget,
+                           const Node& target);
+
   void shrink(size_t newSize) {
     DCHECK(!m_windowEventContext);
     m_nodeEventContexts.shrink(newSize);
@@ -98,7 +102,7 @@
 
   void retargetRelatedTarget(const Node& relatedTargetNode);
 
-  void shrinkForRelatedTarget(const Node& target, const Node& relatedTarget);
+  void shrinkForRelatedTarget(const Node& target);
 
   void adjustTouchList(const TouchList*,
                        HeapVector<Member<TouchList>> adjustedTouchList,
diff --git a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp
index 72ee750..8566854 100644
--- a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.cpp
@@ -43,8 +43,12 @@
             WebURLRequest::FrameTypeNone);
   request.mutableResourceRequest().setRequestContext(
       WebURLRequest::RequestContextStyle);
-  return toCSSStyleSheetResource(
+  CSSStyleSheetResource* resource = toCSSStyleSheetResource(
       fetcher->requestResource(request, CSSStyleSheetResourceFactory()));
+  // TODO(kouhei): Dedupe this logic w/ ScriptResource::fetch
+  if (resource && !request.integrityMetadata().isEmpty())
+    resource->setIntegrityMetadata(request.integrityMetadata());
+  return resource;
 }
 
 CSSStyleSheetResource* CSSStyleSheetResource::createForTest(
@@ -99,14 +103,21 @@
 
 const String CSSStyleSheetResource::sheetText(
     MIMETypeCheck mimeTypeCheck) const {
-  if (!data() || data()->isEmpty() || !canUseSheet(mimeTypeCheck))
+  if (!canUseSheet(mimeTypeCheck))
     return String();
 
-  if (!m_decodedSheetText.isNull())
-    return m_decodedSheetText;
+  // Use cached decoded sheet text when available
+  if (!m_decodedSheetText.isNull()) {
+    // We should have the decoded sheet text cached when the resource is fully
+    // loaded.
+    DCHECK_EQ(getStatus(), Resource::Cached);
 
-  // Don't cache the decoded text, regenerating is cheap and it can use quite a
-  // bit of memory
+    return m_decodedSheetText;
+  }
+
+  if (!data() || data()->isEmpty())
+    return String();
+
   return decodedText();
 }
 
@@ -121,10 +132,10 @@
 }
 
 void CSSStyleSheetResource::checkNotify() {
-  // Decode the data to find out the encoding and keep the sheet text around
-  // during checkNotify()
-  if (data())
+  // Decode the data to find out the encoding and cache the decoded sheet text.
+  if (data()) {
     m_decodedSheetText = decodedText();
+  }
 
   ResourceClientWalker<StyleSheetResourceClient> w(clients());
   while (StyleSheetResourceClient* c = w.next()) {
@@ -132,9 +143,13 @@
     c->setCSSStyleSheet(resourceRequest().url(), response().url(), encoding(),
                         this);
   }
-  // Clear the decoded text as it is unlikely to be needed immediately again and
-  // is cheap to regenerate.
-  m_decodedSheetText = String();
+
+  // Clear raw bytes as now we have the full decoded sheet text.
+  // We wait for all LinkStyle::setCSSStyleSheet to run (at least once)
+  // as SubresourceIntegrity checks require raw bytes.
+  // Note that LinkStyle::setCSSStyleSheet can be called from didAddClient too,
+  // but is safe as we should have a cached ResourceIntegrityDisposition.
+  clearData();
 }
 
 void CSSStyleSheetResource::destroyDecodedDataIfPossible() {
@@ -145,6 +160,11 @@
   setDecodedSize(0);
 }
 
+void CSSStyleSheetResource::destroyDecodedDataForFailedRevalidation() {
+  m_decodedSheetText = String();
+  destroyDecodedDataIfPossible();
+}
+
 bool CSSStyleSheetResource::canUseSheet(MIMETypeCheck mimeTypeCheck) const {
   if (errorOccurred())
     return false;
diff --git a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h
index 51ff8d9..7426b3b 100644
--- a/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h
+++ b/third_party/WebKit/Source/core/fetch/CSSStyleSheetResource.h
@@ -79,10 +79,10 @@
   void setParsedStyleSheetCache(StyleSheetContents*);
 
   void destroyDecodedDataIfPossible() override;
-  void destroyDecodedDataForFailedRevalidation() override {
-    destroyDecodedDataIfPossible();
-  }
+  void destroyDecodedDataForFailedRevalidation() override;
 
+  // Decoded sheet text cache is available iff loading this CSS resource is
+  // successfully complete.
   String m_decodedSheetText;
 
   Member<StyleSheetContents> m_parsedStyleSheetCache;
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
index ddafecd..586d1f77 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
@@ -437,14 +437,6 @@
   Resource::finish(loadFinishTime);
 }
 
-void ImageResource::onMemoryDump(WebMemoryDumpLevelOfDetail levelOfDetail,
-                                 WebProcessMemoryDump* memoryDump) const {
-  Resource::onMemoryDump(levelOfDetail, memoryDump);
-  const String name = getMemoryDumpName() + "/encoded_data";
-  if (m_image && !m_image->isNull())
-    m_image->data()->onMemoryDump(name, memoryDump);
-}
-
 void ImageResource::error(const ResourceError& error) {
   if (m_multipartParser)
     m_multipartParser->cancel();
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.h b/third_party/WebKit/Source/core/fetch/ImageResource.h
index 3768717c..4652299c 100644
--- a/third_party/WebKit/Source/core/fetch/ImageResource.h
+++ b/third_party/WebKit/Source/core/fetch/ImageResource.h
@@ -128,9 +128,6 @@
                         std::unique_ptr<WebDataConsumerHandle>) override;
   void finish(double finishTime = 0.0) override;
 
-  void onMemoryDump(WebMemoryDumpLevelOfDetail,
-                    WebProcessMemoryDump*) const override;
-
   // For compatibility, images keep loading even if there are HTTP errors.
   bool shouldIgnoreHTTPStatusCodeErrors() const override { return true; }
 
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp
index bbbd21c..01ce75d 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.cpp
+++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -455,7 +455,7 @@
 void Resource::setIntegrityDisposition(
     ResourceIntegrityDisposition disposition) {
   DCHECK_NE(disposition, ResourceIntegrityDisposition::NotChecked);
-  DCHECK(m_type == Resource::Script);
+  DCHECK(m_type == Resource::Script || m_type == Resource::CSSStyleSheet);
   m_integrityDisposition = disposition;
 }
 
diff --git a/third_party/WebKit/Source/core/fetch/Resource.h b/third_party/WebKit/Source/core/fetch/Resource.h
index a8066ef6..a338bfa 100644
--- a/third_party/WebKit/Source/core/fetch/Resource.h
+++ b/third_party/WebKit/Source/core/fetch/Resource.h
@@ -227,7 +227,7 @@
   bool errorOccurred() const {
     return m_status == LoadError || m_status == DecodeError;
   }
-  bool loadFailedOrCanceled() { return !m_error.isNull(); }
+  bool loadFailedOrCanceled() const { return !m_error.isNull(); }
 
   DataBufferingPolicy getDataBufferingPolicy() const {
     return m_options.dataBufferingPolicy;
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
index 05af9497..6c0ecfe 100644
--- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
+++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -40,6 +40,7 @@
 #include "platform/RuntimeEnabledFeatures.h"
 #include "platform/mhtml/ArchiveResource.h"
 #include "platform/mhtml/MHTMLArchive.h"
+#include "platform/network/NetworkUtils.h"
 #include "platform/network/ResourceTimingInfo.h"
 #include "platform/tracing/TraceEvent.h"
 #include "platform/tracing/TracedValue.h"
@@ -387,8 +388,8 @@
     memoryCache()->remove(oldResource);
   }
 
-  WebString mimetype;
-  WebString charset;
+  AtomicString mimetype;
+  AtomicString charset;
   RefPtr<SharedBuffer> data;
   if (substituteData.isValid()) {
     mimetype = substituteData.mimeType();
@@ -396,7 +397,7 @@
     data = substituteData.content();
   } else if (url.protocolIsData()) {
     data = PassRefPtr<SharedBuffer>(
-        Platform::current()->parseDataURL(url, mimetype, charset));
+        NetworkUtils::parseDataURL(url, mimetype, charset));
     if (!data)
       return nullptr;
   } else {
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
index 504686d..a27a6472c 100644
--- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -429,17 +429,37 @@
   // See the comment in PendingScript.cpp about why this check is necessary
   // here, instead of in the resource fetcher. https://crbug.com/500701.
   if (!cachedStyleSheet->errorOccurred() &&
-      m_owner->fastHasAttribute(HTMLNames::integrityAttr) &&
-      cachedStyleSheet->resourceBuffer() &&
-      !SubresourceIntegrity::CheckSubresourceIntegrity(
-          *m_owner, cachedStyleSheet->resourceBuffer()->data(),
-          cachedStyleSheet->resourceBuffer()->size(), KURL(baseURL, href),
-          *cachedStyleSheet)) {
-    m_loading = false;
-    removePendingSheet();
-    notifyLoadedSheetAndAllCriticalSubresources(
-        Node::ErrorOccurredLoadingSubresource);
-    return;
+      !m_owner->fastGetAttribute(HTMLNames::integrityAttr).isEmpty() &&
+      !cachedStyleSheet->integrityMetadata().isEmpty()) {
+    ResourceIntegrityDisposition disposition =
+        cachedStyleSheet->integrityDisposition();
+
+    DCHECK(disposition != ResourceIntegrityDisposition::NotChecked ||
+           !cachedStyleSheet->sheetText().isNull());
+
+    if (disposition == ResourceIntegrityDisposition::NotChecked &&
+        !cachedStyleSheet->loadFailedOrCanceled()) {
+      DCHECK(cachedStyleSheet->resourceBuffer());
+      if (SubresourceIntegrity::CheckSubresourceIntegrity(
+              *m_owner, cachedStyleSheet->resourceBuffer()->data(),
+              cachedStyleSheet->resourceBuffer()->size(), KURL(baseURL, href),
+              *cachedStyleSheet))
+        disposition = ResourceIntegrityDisposition::Passed;
+      else
+        disposition = ResourceIntegrityDisposition::Failed;
+
+      // TODO(kouhei): Remove this const_cast crbug.com/653502
+      const_cast<CSSStyleSheetResource*>(cachedStyleSheet)
+          ->setIntegrityDisposition(disposition);
+    }
+
+    if (disposition == ResourceIntegrityDisposition::Failed) {
+      m_loading = false;
+      removePendingSheet();
+      notifyLoadedSheetAndAllCriticalSubresources(
+          Node::ErrorOccurredLoadingSubresource);
+      return;
+    }
   }
 
   CSSParserContext parserContext(m_owner->document(), nullptr, baseURL,
diff --git a/third_party/WebKit/Source/core/inspector/BUILD.gn b/third_party/WebKit/Source/core/inspector/BUILD.gn
index 165506c..8b945e6 100644
--- a/third_party/WebKit/Source/core/inspector/BUILD.gn
+++ b/third_party/WebKit/Source/core/inspector/BUILD.gn
@@ -6,6 +6,7 @@
 import("//third_party/WebKit/Source/core/core.gni")
 import(
     "//third_party/WebKit/Source/platform/inspector_protocol/inspector_protocol.gni")
+import("//v8/gni/v8.gni")
 
 blink_core_sources("inspector") {
   sources = [
@@ -128,10 +129,9 @@
 
   config_file = "inspector_protocol_config.json"
 
-  # TODO(dgozman): export js_protocol.json path from v8's build.
   inputs = [
     "browser_protocol.json",
-    "//v8/src/inspector/js_protocol.json",
+    v8_inspector_js_protocol,
     "inspector_protocol_config.json",
   ]
 
@@ -231,7 +231,7 @@
 
   inputs = [
     "browser_protocol.json",
-    "//v8/src/inspector/js_protocol.json",
+    v8_inspector_js_protocol,
   ]
   _stamp = "$blink_core_output_dir/inspector/browser_protocol.stamp"
   outputs = [
@@ -242,7 +242,7 @@
     "--stamp",
     rebase_path(_stamp, root_build_dir),
     rebase_path("browser_protocol.json", root_build_dir),
-    rebase_path("//v8/src/inspector/js_protocol.json", root_build_dir),
+    rebase_path(v8_inspector_js_protocol, root_build_dir),
   ]
 }
 
@@ -254,7 +254,7 @@
 
   inputs = [
     "browser_protocol.json",
-    "//v8/src/inspector/js_protocol.json",
+    v8_inspector_js_protocol,
   ]
   output_file = "$blink_core_output_dir/inspector/protocol.json"
   outputs = [
@@ -263,7 +263,7 @@
 
   args = [
     rebase_path("browser_protocol.json", root_build_dir),
-    rebase_path("//v8/src/inspector/js_protocol.json", root_build_dir),
+    rebase_path(v8_inspector_js_protocol, root_build_dir),
     rebase_path(output_file, root_build_dir),
   ]
 }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
index 7d872d6..b44d350f 100644
--- a/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
+++ b/third_party/WebKit/Source/core/inspector/InspectorPageAgent.cpp
@@ -231,7 +231,8 @@
   switch (cachedResource->getType()) {
     case Resource::CSSStyleSheet:
       maybeEncodeTextContent(
-          toCSSStyleSheetResource(cachedResource)->sheetText(),
+          toCSSStyleSheetResource(cachedResource)
+              ->sheetText(CSSStyleSheetResource::MIMETypeCheck::Lax),
           cachedResource->resourceBuffer(), result, base64Encoded);
       return true;
     case Resource::Script:
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index 91f24af7..6c86ce9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -2328,7 +2328,9 @@
     // for painted elements within the transform since we don't know the desired
     // subpixel accumulation at this point, and the transform may include a
     // scale.
-    rect = LayoutRect(layer()->transform()->mapRect(enclosingIntRect(rect)));
+    FloatRect floatRect =
+        rect.isEmpty() ? FloatRect(rect) : FloatRect(enclosingIntRect(rect));
+    rect = LayoutRect(layer()->transform()->mapRect(floatRect));
   }
   LayoutPoint topLeft = rect.location();
   if (container->isBox()) {
diff --git a/third_party/WebKit/Source/core/page/BUILD.gn b/third_party/WebKit/Source/core/page/BUILD.gn
index 6434c97..07a42671 100644
--- a/third_party/WebKit/Source/core/page/BUILD.gn
+++ b/third_party/WebKit/Source/core/page/BUILD.gn
@@ -18,10 +18,6 @@
     "CustomContextMenuProvider.h",
     "DragController.cpp",
     "DragData.cpp",
-    "EventSource.cpp",
-    "EventSource.h",
-    "EventSourceParser.cpp",
-    "EventSourceParser.h",
     "EventWithHitTestResults.h",
     "FocusController.cpp",
     "FrameTree.cpp",
diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
index 439720b1..8c090076 100644
--- a/third_party/WebKit/Source/core/page/DragController.cpp
+++ b/third_party/WebKit/Source/core/page/DragController.cpp
@@ -264,8 +264,9 @@
             isHTMLPlugInElement(*result.innerNode()) &&
             toHTMLPlugInElement(result.innerNode())->canProcessDrag();
       }
-      dataTransfer->setAccessPolicy(
-          DataTransferNumb);  // Invalidate clipboard here for security
+
+      // Invalidate clipboard here for security.
+      dataTransfer->setAccessPolicy(DataTransferNumb);
     }
     if (preventedDefault) {
       m_documentUnderMouse = nullptr;
@@ -285,9 +286,10 @@
   if (operationForLoad(dragData) == DragOperationNone)
     return false;
 
-  if (m_page->settings().navigateOnDragDrop())
-    m_page->deprecatedLocalMainFrame()->loader().load(
+  if (m_page->settings().navigateOnDragDrop()) {
+    m_page->mainFrame()->navigate(
         FrameLoadRequest(nullptr, ResourceRequest(dragData->asURL())));
+  }
   return true;
 }
 
diff --git a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
index 25ba128..d8c6599e 100644
--- a/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/ScrollingCoordinator.cpp
@@ -64,9 +64,9 @@
 #include "public/platform/WebScrollbarLayer.h"
 #include "public/platform/WebScrollbarThemeGeometry.h"
 #include "public/platform/WebScrollbarThemePainter.h"
-#include "wtf/PtrUtil.h"
 #include "wtf/text/StringBuilder.h"
 #include <memory>
+#include <utility>
 
 using blink::WebLayer;
 using blink::WebLayerPositionConstraint;
@@ -309,8 +309,8 @@
       WebScrollbarThemeGeometryNative::create(theme));
 
   std::unique_ptr<WebScrollbarLayer> scrollbarLayer =
-      wrapUnique(Platform::current()->compositorSupport()->createScrollbarLayer(
-          WebScrollbarImpl::create(&scrollbar), painter, geometry.release()));
+      Platform::current()->compositorSupport()->createScrollbarLayer(
+          WebScrollbarImpl::create(&scrollbar), painter, std::move(geometry));
   GraphicsLayer::registerContentsLayer(scrollbarLayer->layer());
   return scrollbarLayer;
 }
@@ -324,10 +324,10 @@
   WebScrollbar::Orientation webOrientation =
       (orientation == HorizontalScrollbar) ? WebScrollbar::Horizontal
                                            : WebScrollbar::Vertical;
-  std::unique_ptr<WebScrollbarLayer> scrollbarLayer = wrapUnique(
+  std::unique_ptr<WebScrollbarLayer> scrollbarLayer =
       Platform::current()->compositorSupport()->createSolidColorScrollbarLayer(
           webOrientation, thumbThickness, trackStart,
-          isLeftSideVerticalScrollbar));
+          isLeftSideVerticalScrollbar);
   GraphicsLayer::registerContentsLayer(scrollbarLayer->layer());
   return scrollbarLayer;
 }
diff --git a/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp b/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp
index f7648986..b481b99 100644
--- a/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp
+++ b/third_party/WebKit/Source/core/paint/VideoPainterTest.cpp
@@ -35,8 +35,7 @@
     m_client->networkStateChanged();
     m_readyState = ReadyStateHaveEnoughData;
     m_client->readyStateChanged();
-    m_webLayer =
-        wrapUnique(Platform::current()->compositorSupport()->createLayer());
+    m_webLayer = Platform::current()->compositorSupport()->createLayer();
     m_client->setWebLayer(m_webLayer.get());
   }
   void play() override {}
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequestProgressEventThrottle.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequestProgressEventThrottle.cpp
index 0d083a1..40bf6d2 100644
--- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequestProgressEventThrottle.cpp
+++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequestProgressEventThrottle.cpp
@@ -28,7 +28,6 @@
 #include "core/xmlhttprequest/XMLHttpRequestProgressEventThrottle.h"
 
 #include "core/EventTypeNames.h"
-#include "core/dom/TaskRunnerHelper.h"
 #include "core/events/ProgressEvent.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "core/inspector/InspectorTraceEvents.h"
@@ -78,8 +77,8 @@
 
 XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(
     XMLHttpRequest* target)
-    : TimerBase(TaskRunnerHelper::get(TaskType::Networking,
-                                      target->getExecutionContext())),
+    : TimerBase(
+          Platform::current()->currentThread()->scheduler()->timerTaskRunner()),
       m_target(target),
       m_hasDispatchedProgressProgressEvent(false) {
   DCHECK(target);
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
index b3965fd..a7de6f3 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -507,14 +507,12 @@
      */
     selectFilmStripFrame: function(time)
     {
-        for (var divider of this._eventDividers)
-            divider.element.classList.toggle("network-frame-divider-selected", divider.time === time);
+        this._columns.selectFilmStripFrame(time);
     },
 
     clearFilmStripFrame: function()
     {
-        for (var divider of this._eventDividers)
-            divider.element.classList.toggle("network-frame-divider-selected", false);
+        this._columns.clearFilmStripFrame();
     },
 
     _refreshIfNeeded: function()
@@ -699,7 +697,6 @@
 
         this._mainRequestLoadTime = -1;
         this._mainRequestDOMContentLoadedTime = -1;
-        this._eventDividers = [];
 
         if (this._dataGrid) {
             this._dataGrid.rootNode().removeChildren();
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
index da5ab6b..8623c8b3 100644
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js
@@ -815,6 +815,21 @@
         this._timelineGrid.showEventDividers();
     },
 
+    /**
+     * @param {number} time
+     */
+    selectFilmStripFrame: function(time)
+    {
+        for (var divider of this._eventDividers)
+            divider.element.classList.toggle("network-frame-divider-selected", divider.time === time);
+    },
+
+    clearFilmStripFrame: function()
+    {
+        for (var divider of this._eventDividers)
+            divider.element.classList.toggle("network-frame-divider-selected", false);
+    },
+
     _updateRowsSize: function()
     {
         if (Runtime.experiments.isEnabled("canvasNetworkTimeline"))
diff --git a/third_party/WebKit/Source/devtools/services/dispatcher.js b/third_party/WebKit/Source/devtools/services/dispatcher.js
index 25355bd..3735931 100644
--- a/third_party/WebKit/Source/devtools/services/dispatcher.js
+++ b/third_party/WebKit/Source/devtools/services/dispatcher.js
@@ -8,8 +8,7 @@
 function Dispatcher()
 {
     this._constructors = new Map();
-    this._objects = new Map();
-    this._lastObjectId = 1;
+    this._connections = new Set();
 }
 
 Dispatcher.prototype = {
@@ -22,9 +21,8 @@
         var options = { server: http_server, path: "/endpoint" };
         var wss = new WebSocketServer(options);
         wss.on("connection", (socket) => {
-            this._socket = socket;
-            this._socket.on("message", this._dispatchMessageWrapped.bind(this));
-            this._socket.on("close", this._connectionClosed.bind(this));
+            var connection = new Connection(this, socket);
+            this._connections.add(connection);
         });
     },
 
@@ -33,6 +31,25 @@
         this._constructors.set(name, constructor);
     },
 
+    _connectionClosed: function(connection)
+    {
+        this._connections.delete(connection);
+    }
+}
+
+exports.Dispatcher = Dispatcher;
+
+function Connection(dispatcher, socket)
+{
+    this._dispatcher = dispatcher;
+    this._objects = new Map();
+    this._lastObjectId = 1;
+    this._socket = socket;
+    this._socket.on("message", this._dispatchMessageWrapped.bind(this));
+    this._socket.on("close", this._connectionClosed.bind(this));
+}
+
+Connection.prototype = {
     _dispatchMessageWrapped: function(data)
     {
         try {
@@ -47,7 +64,7 @@
     {
         var [objectName, method] = message.method.split(".");
         var result = JSON.stringify({id: message.id});
-        var constructor = this._constructors.get(objectName);
+        var constructor = this._dispatcher._constructors.get(objectName);
         if (!constructor) {
             this._sendErrorResponse(message.id, "Could not resolve service '" + objectName + "'");
             return;
@@ -89,6 +106,7 @@
         for (var object of this._objects.values())
             object.dispose();
         this._objects.clear();
+        this._dispatcher._connectionClosed(this);
     },
 
     _notify: function(objectId, objectName, method, params)
@@ -110,5 +128,3 @@
         this._socket.send(JSON.stringify(message));
     },
 }
-
-exports.Dispatcher = Dispatcher;
diff --git a/third_party/WebKit/Source/devtools/services/package.json b/third_party/WebKit/Source/devtools/services/package.json
index 71c9d6e..824851c 100644
--- a/third_party/WebKit/Source/devtools/services/package.json
+++ b/third_party/WebKit/Source/devtools/services/package.json
@@ -1,10 +1,11 @@
 {
-    "name": "devtools-backend",
-    "version": "1.0.0",
-    "ignore": [
-        ".gitignore"
-    ],
-    "devDependencies": {
-        "pty.js": "0.3.1"
-    }
+  "name": "devtools-backend",
+  "version": "1.0.0",
+  "ignore": [
+    ".gitignore"
+  ],
+  "dependencies": {
+    "pty.js": "0.3.1",
+    "ws": "^1.1.1"
+  }
 }
diff --git a/third_party/WebKit/Source/modules/BUILD.gn b/third_party/WebKit/Source/modules/BUILD.gn
index ae130d80..8b9607a 100644
--- a/third_party/WebKit/Source/modules/BUILD.gn
+++ b/third_party/WebKit/Source/modules/BUILD.gn
@@ -110,6 +110,7 @@
     "//third_party/WebKit/Source/modules/donottrack",
     "//third_party/WebKit/Source/modules/encoding",
     "//third_party/WebKit/Source/modules/encryptedmedia",
+    "//third_party/WebKit/Source/modules/eventsource",
     "//third_party/WebKit/Source/modules/fetch",
     "//third_party/WebKit/Source/modules/filesystem",
     "//third_party/WebKit/Source/modules/gamepad",
@@ -229,6 +230,7 @@
     "credentialmanager/PasswordCredentialTest.cpp",
     "csspaint/PaintRenderingContext2DTest.cpp",
     "csspaint/PaintWorkletTest.cpp",
+    "eventsource/EventSourceParserTest.cpp",
     "fetch/BlobBytesConsumerTest.cpp",
     "fetch/BodyStreamBufferTest.cpp",
     "fetch/BytesConsumerForDataConsumerHandleTest.cpp",
diff --git a/third_party/WebKit/Source/modules/DEPS b/third_party/WebKit/Source/modules/DEPS
index 507e92d..9f2ddf77 100644
--- a/third_party/WebKit/Source/modules/DEPS
+++ b/third_party/WebKit/Source/modules/DEPS
@@ -4,6 +4,5 @@
     "+modules",
     "+platform",
     "+public/platform",
-    "+skia/ext",
     "-web",
 ]
diff --git a/third_party/WebKit/Source/modules/beacon/DEPS b/third_party/WebKit/Source/modules/beacon/DEPS
index b2af894..a5627b7 100644
--- a/third_party/WebKit/Source/modules/beacon/DEPS
+++ b/third_party/WebKit/Source/modules/beacon/DEPS
@@ -1,9 +1,4 @@
 include_rules = [
-    "+bindings",
-    "+core",
     "-modules",
     "+modules/beacon",
-    "+platform",
-    "+public/platform",
-    "-web",
 ]
diff --git a/third_party/WebKit/Source/modules/eventsource/BUILD.gn b/third_party/WebKit/Source/modules/eventsource/BUILD.gn
new file mode 100644
index 0000000..10e2a3c
--- /dev/null
+++ b/third_party/WebKit/Source/modules/eventsource/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/WebKit/Source/modules/modules.gni")
+
+blink_modules_sources("eventsource") {
+  sources = [
+    "EventSource.cpp",
+    "EventSource.h",
+    "EventSourceParser.cpp",
+    "EventSourceParser.h",
+  ]
+}
diff --git a/third_party/WebKit/Source/modules/eventsource/DEPS b/third_party/WebKit/Source/modules/eventsource/DEPS
new file mode 100644
index 0000000..875c191
--- /dev/null
+++ b/third_party/WebKit/Source/modules/eventsource/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+    "-modules",
+    "+modules/ModulesExport.h",
+    "+modules/eventsource",
+]
diff --git a/third_party/WebKit/Source/core/page/EventSource.cpp b/third_party/WebKit/Source/modules/eventsource/EventSource.cpp
similarity index 98%
rename from third_party/WebKit/Source/core/page/EventSource.cpp
rename to third_party/WebKit/Source/modules/eventsource/EventSource.cpp
index 35c0ef8c..acaee28 100644
--- a/third_party/WebKit/Source/core/page/EventSource.cpp
+++ b/third_party/WebKit/Source/modules/eventsource/EventSource.cpp
@@ -30,7 +30,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "core/page/EventSource.h"
+#include "modules/eventsource/EventSource.h"
 
 #include "bindings/core/v8/ExceptionState.h"
 #include "bindings/core/v8/ScriptController.h"
@@ -48,7 +48,7 @@
 #include "core/inspector/ConsoleMessage.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "core/loader/ThreadableLoader.h"
-#include "core/page/EventSourceInit.h"
+#include "modules/eventsource/EventSourceInit.h"
 #include "platform/HTTPNames.h"
 #include "platform/network/ResourceError.h"
 #include "platform/network/ResourceRequest.h"
diff --git a/third_party/WebKit/Source/core/page/EventSource.h b/third_party/WebKit/Source/modules/eventsource/EventSource.h
similarity index 91%
rename from third_party/WebKit/Source/core/page/EventSource.h
rename to third_party/WebKit/Source/modules/eventsource/EventSource.h
index 64711a8..dc5a544 100644
--- a/third_party/WebKit/Source/core/page/EventSource.h
+++ b/third_party/WebKit/Source/modules/eventsource/EventSource.h
@@ -37,7 +37,8 @@
 #include "core/events/EventTarget.h"
 #include "core/loader/ThreadableLoader.h"
 #include "core/loader/ThreadableLoaderClient.h"
-#include "core/page/EventSourceParser.h"
+#include "modules/ModulesExport.h"
+#include "modules/eventsource/EventSourceParser.h"
 #include "platform/Timer.h"
 #include "platform/heap/Handle.h"
 #include "platform/weborigin/KURL.h"
@@ -50,11 +51,11 @@
 class ExceptionState;
 class ResourceResponse;
 
-class CORE_EXPORT EventSource final : public EventTargetWithInlineData,
-                                      private ThreadableLoaderClient,
-                                      public ActiveScriptWrappable,
-                                      public ActiveDOMObject,
-                                      public EventSourceParser::Client {
+class MODULES_EXPORT EventSource final : public EventTargetWithInlineData,
+                                         private ThreadableLoaderClient,
+                                         public ActiveScriptWrappable,
+                                         public ActiveDOMObject,
+                                         public EventSourceParser::Client {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(EventSource);
 
diff --git a/third_party/WebKit/Source/core/page/EventSource.idl b/third_party/WebKit/Source/modules/eventsource/EventSource.idl
similarity index 100%
rename from third_party/WebKit/Source/core/page/EventSource.idl
rename to third_party/WebKit/Source/modules/eventsource/EventSource.idl
diff --git a/third_party/WebKit/Source/core/page/EventSourceInit.idl b/third_party/WebKit/Source/modules/eventsource/EventSourceInit.idl
similarity index 100%
rename from third_party/WebKit/Source/core/page/EventSourceInit.idl
rename to third_party/WebKit/Source/modules/eventsource/EventSourceInit.idl
diff --git a/third_party/WebKit/Source/core/page/EventSourceParser.cpp b/third_party/WebKit/Source/modules/eventsource/EventSourceParser.cpp
similarity index 95%
rename from third_party/WebKit/Source/core/page/EventSourceParser.cpp
rename to third_party/WebKit/Source/modules/eventsource/EventSourceParser.cpp
index 8a07466..4fbad24 100644
--- a/third_party/WebKit/Source/core/page/EventSourceParser.cpp
+++ b/third_party/WebKit/Source/modules/eventsource/EventSourceParser.cpp
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/page/EventSourceParser.h"
+#include "modules/eventsource/EventSourceParser.h"
 
 #include "core/EventTypeNames.h"
-#include "core/page/EventSource.h"
+#include "modules/eventsource/EventSource.h"
 #include "wtf/ASCIICType.h"
 #include "wtf/Assertions.h"
 #include "wtf/NotFound.h"
@@ -34,7 +34,7 @@
         m_line.size() + (i - start) == WTF_ARRAY_LENGTH(kBOM)) {
       Vector<char> line = m_line;
       line.append(&bytes[start], i - start);
-      ASSERT(line.size() == WTF_ARRAY_LENGTH(kBOM));
+      DCHECK_EQ(line.size(), WTF_ARRAY_LENGTH(kBOM));
       m_isRecognizingBOM = false;
       if (memcmp(line.data(), kBOM, sizeof(kBOM)) == 0) {
         start = i;
@@ -68,7 +68,7 @@
     m_lastEventId = m_id;
     // We dispatch an event when seeing an empty line.
     if (!m_data.isEmpty()) {
-      ASSERT(m_data[m_data.size() - 1] == '\n');
+      DCHECK_EQ(m_data[m_data.size() - 1], '\n');
       String data = fromUTF8(m_data.data(), m_data.size() - 1);
       m_client->onMessageEvent(
           m_eventType.isEmpty() ? EventTypeNames::message : m_eventType, data,
diff --git a/third_party/WebKit/Source/core/page/EventSourceParser.h b/third_party/WebKit/Source/modules/eventsource/EventSourceParser.h
similarity index 92%
rename from third_party/WebKit/Source/core/page/EventSourceParser.h
rename to third_party/WebKit/Source/modules/eventsource/EventSourceParser.h
index ba7638ef..4028048 100644
--- a/third_party/WebKit/Source/core/page/EventSourceParser.h
+++ b/third_party/WebKit/Source/modules/eventsource/EventSourceParser.h
@@ -5,7 +5,7 @@
 #ifndef EventSourceParser_h
 #define EventSourceParser_h
 
-#include "core/CoreExport.h"
+#include "modules/ModulesExport.h"
 #include "platform/heap/Handle.h"
 #include "wtf/Vector.h"
 #include "wtf/text/AtomicString.h"
@@ -15,10 +15,10 @@
 
 namespace blink {
 
-class CORE_EXPORT EventSourceParser final
+class MODULES_EXPORT EventSourceParser final
     : public GarbageCollectedFinalized<EventSourceParser> {
  public:
-  class CORE_EXPORT Client : public GarbageCollectedMixin {
+  class MODULES_EXPORT Client : public GarbageCollectedMixin {
    public:
     virtual ~Client() {}
     virtual void onMessageEvent(const AtomicString& type,
diff --git a/third_party/WebKit/Source/core/page/EventSourceParserTest.cpp b/third_party/WebKit/Source/modules/eventsource/EventSourceParserTest.cpp
similarity index 98%
rename from third_party/WebKit/Source/core/page/EventSourceParserTest.cpp
rename to third_party/WebKit/Source/modules/eventsource/EventSourceParserTest.cpp
index 5b4bd693..96d17bd 100644
--- a/third_party/WebKit/Source/core/page/EventSourceParserTest.cpp
+++ b/third_party/WebKit/Source/modules/eventsource/EventSourceParserTest.cpp
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "core/page/EventSourceParser.h"
+#include "modules/eventsource/EventSourceParser.h"
 
-#include "core/page/EventSource.h"
+#include "modules/eventsource/EventSource.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "wtf/text/CharacterNames.h"
 
diff --git a/third_party/WebKit/Source/modules/eventsource/OWNERS b/third_party/WebKit/Source/modules/eventsource/OWNERS
new file mode 100644
index 0000000..c1f23ed
--- /dev/null
+++ b/third_party/WebKit/Source/modules/eventsource/OWNERS
@@ -0,0 +1,2 @@
+tyoshino@chromium.org
+yhirano@chromium.org
diff --git a/third_party/WebKit/Source/modules/fetch/DEPS b/third_party/WebKit/Source/modules/fetch/DEPS
index 52ea6c2..c6e03118 100644
--- a/third_party/WebKit/Source/modules/fetch/DEPS
+++ b/third_party/WebKit/Source/modules/fetch/DEPS
@@ -1,12 +1,7 @@
 include_rules = [
-    "+bindings",
-    "+core",
     "+gin/public",
     "-modules",
     "+modules/ModulesExport.h",
     "+modules/fetch",
     "+modules/credentialmanager",
-    "+platform",
-    "+public/platform",
-    "-web",
 ]
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni
index e32744eb..625cb2b 100644
--- a/third_party/WebKit/Source/modules/modules_idl_files.gni
+++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -85,6 +85,7 @@
                     "encryptedmedia/MediaKeyStatusMap.idl",
                     "encryptedmedia/MediaKeySystemAccess.idl",
                     "encryptedmedia/MediaKeys.idl",
+                    "eventsource/EventSource.idl",
                     "fetch/Body.idl",
                     "fetch/Headers.idl",
                     "fetch/Request.idl",
@@ -398,6 +399,7 @@
                     "encryptedmedia/MediaKeyMessageEventInit.idl",
                     "encryptedmedia/MediaKeySystemConfiguration.idl",
                     "encryptedmedia/MediaKeySystemMediaCapability.idl",
+                    "eventsource/EventSourceInit.idl",
                     "filesystem/FileSystemFlags.idl",
                     "gamepad/GamepadEventInit.idl",
                     "geolocation/PositionOptions.idl",
@@ -671,6 +673,8 @@
   "$blink_modules_output_dir/encryptedmedia/MediaKeySystemConfiguration.h",
   "$blink_modules_output_dir/encryptedmedia/MediaKeySystemMediaCapability.cpp",
   "$blink_modules_output_dir/encryptedmedia/MediaKeySystemMediaCapability.h",
+  "$blink_modules_output_dir/eventsource/EventSourceInit.cpp",
+  "$blink_modules_output_dir/eventsource/EventSourceInit.h",
   "$blink_modules_output_dir/filesystem/FileSystemFlags.cpp",
   "$blink_modules_output_dir/filesystem/FileSystemFlags.h",
   "$blink_modules_output_dir/gamepad/GamepadEventInit.cpp",
diff --git a/third_party/WebKit/Source/modules/notifications/DEPS b/third_party/WebKit/Source/modules/notifications/DEPS
index 6138cfb..797072d 100644
--- a/third_party/WebKit/Source/modules/notifications/DEPS
+++ b/third_party/WebKit/Source/modules/notifications/DEPS
@@ -11,5 +11,6 @@
     "+modules/vibration",
     "+platform",
     "+public/platform",
+    "+skia/ext",
     "-web",
 ]
diff --git a/third_party/WebKit/Source/modules/websockets/DEPS b/third_party/WebKit/Source/modules/websockets/DEPS
index a2d7c33..c37370d 100644
--- a/third_party/WebKit/Source/modules/websockets/DEPS
+++ b/third_party/WebKit/Source/modules/websockets/DEPS
@@ -1,13 +1,8 @@
 include_rules = [
-    "+bindings",
-    "+core",
     "-modules",
     "+modules/EventModules.h",
     "+modules/EventTargetModules.h",
     "+modules/ModulesExport.h",
     "+modules/websockets",
     "+mojo/public/cpp/bindings",
-    "+platform",
-    "+public/platform",
-    "-web",
 ]
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn
index cf3ac13..f797e4ff 100644
--- a/third_party/WebKit/Source/platform/BUILD.gn
+++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -1402,6 +1402,7 @@
   deps = [
     ":blink_common",
     "//components/link_header_util:link_header_util",
+    "//components/mime_util:mime_util",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/bindings:wtf_support",
     "//third_party/WebKit/Source/platform/heap",
diff --git a/third_party/WebKit/Source/platform/SharedBuffer.cpp b/third_party/WebKit/Source/platform/SharedBuffer.cpp
index 5e2195e..f898cd14 100644
--- a/third_party/WebKit/Source/platform/SharedBuffer.cpp
+++ b/third_party/WebKit/Source/platform/SharedBuffer.cpp
@@ -255,13 +255,12 @@
     dump->addScalar("size", "bytes", m_buffer.size());
     memoryDump->addSuballocation(
         dump->guid(), String(WTF::Partitions::kAllocatedObjectPoolName));
-  }
-  if (m_segments.size()) {
+  } else {
     // If there is data in the segments, then it should have been allocated
     // using fastMalloc.
     const String dataDumpName = dumpPrefix + "/segments";
     auto dump = memoryDump->createMemoryAllocatorDump(dataDumpName);
-    dump->addScalar("size", "bytes", m_size - m_buffer.size());
+    dump->addScalar("size", "bytes", m_size);
     memoryDump->addSuballocation(
         dump->guid(), String(WTF::Partitions::kAllocatedObjectPoolName));
   }
diff --git a/third_party/WebKit/Source/platform/audio/VectorMath.cpp b/third_party/WebKit/Source/platform/audio/VectorMath.cpp
index bf0d2ad..8f3592c 100644
--- a/third_party/WebKit/Source/platform/audio/VectorMath.cpp
+++ b/third_party/WebKit/Source/platform/audio/VectorMath.cpp
@@ -41,6 +41,10 @@
 #include <arm_neon.h>
 #endif
 
+#if HAVE(MIPS_MSA_INTRINSICS)
+#include "platform/cpu/mips/CommonMacrosMSA.h"
+#endif
+
 #include <math.h>
 #include <algorithm>
 
@@ -229,6 +233,27 @@
     }
     n = tailFrames;
   }
+#elif HAVE(MIPS_MSA_INTRINSICS)
+  if ((sourceStride == 1) && (destStride == 1)) {
+    float* destPCopy = destP;
+    v4f32 vScale;
+    v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7;
+    v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7;
+    FloatInt scaleVal;
+
+    scaleVal.floatVal = *scale;
+    vScale = (v4f32)__msa_fill_w(scaleVal.intVal);
+
+    for (; n >= 32; n -= 32) {
+      LD_SP8(sourceP, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6,
+             vSrc7);
+      LD_SP8(destPCopy, 4, vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6,
+             vDst7);
+      VSMA4(vSrc0, vSrc1, vSrc2, vSrc3, vDst0, vDst1, vDst2, vDst3, vScale);
+      VSMA4(vSrc4, vSrc5, vSrc6, vSrc7, vDst4, vDst5, vDst6, vDst7, vScale);
+      ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, destP, 4);
+    }
+  }
 #endif
   while (n) {
     *destP += *sourceP * *scale;
@@ -310,6 +335,24 @@
     }
     n = tailFrames;
   }
+#elif HAVE(MIPS_MSA_INTRINSICS)
+  if ((sourceStride == 1) && (destStride == 1)) {
+    v4f32 vScale;
+    v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7;
+    v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7;
+    FloatInt scaleVal;
+
+    scaleVal.floatVal = *scale;
+    vScale = (v4f32)__msa_fill_w(scaleVal.intVal);
+
+    for (; n >= 32; n -= 32) {
+      LD_SP8(sourceP, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6,
+             vSrc7);
+      VSMUL4(vSrc0, vSrc1, vSrc2, vSrc3, vDst0, vDst1, vDst2, vDst3, vScale);
+      VSMUL4(vSrc4, vSrc5, vSrc6, vSrc7, vDst4, vDst5, vDst6, vDst7, vScale);
+      ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, destP, 4);
+    }
+  }
 #endif
     float k = *scale;
     while (n--) {
@@ -431,6 +474,26 @@
     }
     n = tailFrames;
   }
+#elif HAVE(MIPS_MSA_INTRINSICS)
+  if ((sourceStride1 == 1) && (sourceStride2 == 1) && (destStride == 1)) {
+    v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6,
+        vSrc1P7;
+    v4f32 vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, vSrc2P6,
+        vSrc2P7;
+    v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7;
+
+    for (; n >= 32; n -= 32) {
+      LD_SP8(source1P, 4, vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5,
+             vSrc1P6, vSrc1P7);
+      LD_SP8(source2P, 4, vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5,
+             vSrc2P6, vSrc2P7);
+      ADD4(vSrc1P0, vSrc2P0, vSrc1P1, vSrc2P1, vSrc1P2, vSrc2P2, vSrc1P3,
+           vSrc2P3, vDst0, vDst1, vDst2, vDst3);
+      ADD4(vSrc1P4, vSrc2P4, vSrc1P5, vSrc2P5, vSrc1P6, vSrc2P6, vSrc1P7,
+           vSrc2P7, vDst4, vDst5, vDst6, vDst7);
+      ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, destP, 4);
+    }
+  }
 #endif
     while (n--) {
       *destP = *source1P + *source2P;
@@ -514,6 +577,26 @@
     }
     n = tailFrames;
   }
+#elif HAVE(MIPS_MSA_INTRINSICS)
+  if ((sourceStride1 == 1) && (sourceStride2 == 1) && (destStride == 1)) {
+    v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6,
+        vSrc1P7;
+    v4f32 vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5, vSrc2P6,
+        vSrc2P7;
+    v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7;
+
+    for (; n >= 32; n -= 32) {
+      LD_SP8(source1P, 4, vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5,
+             vSrc1P6, vSrc1P7);
+      LD_SP8(source2P, 4, vSrc2P0, vSrc2P1, vSrc2P2, vSrc2P3, vSrc2P4, vSrc2P5,
+             vSrc2P6, vSrc2P7);
+      MUL4(vSrc1P0, vSrc2P0, vSrc1P1, vSrc2P1, vSrc1P2, vSrc2P2, vSrc1P3,
+           vSrc2P3, vDst0, vDst1, vDst2, vDst3);
+      MUL4(vSrc1P4, vSrc2P4, vSrc1P5, vSrc2P5, vSrc1P6, vSrc2P6, vSrc1P7,
+           vSrc2P7, vDst4, vDst5, vDst6, vDst7);
+      ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, destP, 4);
+    }
+  }
 #endif
   while (n) {
     *destP = *source1P * *source2P;
@@ -716,6 +799,28 @@
 
     n = tailFrames;
   }
+#elif HAVE(MIPS_MSA_INTRINSICS)
+  if (sourceStride == 1) {
+    v4f32 vMax = {
+        0,
+    };
+    v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7;
+    const v16i8 vSignBitMask = (v16i8)__msa_fill_w(0x7FFFFFFF);
+
+    for (; n >= 32; n -= 32) {
+      LD_SP8(sourceP, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6,
+             vSrc7);
+      AND_W4_SP(vSrc0, vSrc1, vSrc2, vSrc3, vSignBitMask);
+      VMAX_W4_SP(vSrc0, vSrc1, vSrc2, vSrc3, vMax);
+      AND_W4_SP(vSrc4, vSrc5, vSrc6, vSrc7, vSignBitMask);
+      VMAX_W4_SP(vSrc4, vSrc5, vSrc6, vSrc7, vMax);
+    }
+
+    max = std::max(max, vMax[0]);
+    max = std::max(max, vMax[1]);
+    max = std::max(max, vMax[2]);
+    max = std::max(max, vMax[3]);
+  }
 #endif
 
   while (n--) {
@@ -754,6 +859,28 @@
     }
     n = tailFrames;
   }
+#elif HAVE(MIPS_MSA_INTRINSICS)
+  if ((sourceStride == 1) && (destStride == 1)) {
+    v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7;
+    v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7;
+    v4f32 vLowThr, vHighThr;
+    FloatInt lowThr, highThr;
+
+    lowThr.floatVal = lowThreshold;
+    highThr.floatVal = highThreshold;
+    vLowThr = (v4f32)__msa_fill_w(lowThr.intVal);
+    vHighThr = (v4f32)__msa_fill_w(highThr.intVal);
+
+    for (; n >= 32; n -= 32) {
+      LD_SP8(sourceP, 4, vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6,
+             vSrc7);
+      VCLIP4(vSrc0, vSrc1, vSrc2, vSrc3, vLowThr, vHighThr, vDst0, vDst1, vDst2,
+             vDst3);
+      VCLIP4(vSrc4, vSrc5, vSrc6, vSrc7, vLowThr, vHighThr, vDst4, vDst5, vDst6,
+             vDst7);
+      ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, destP, 4);
+    }
+  }
 #endif
   while (n--) {
     *destP = clampTo(*sourceP, lowThreshold, highThreshold);
diff --git a/third_party/WebKit/Source/platform/cpu/mips/CommonMacrosMSA.h b/third_party/WebKit/Source/platform/cpu/mips/CommonMacrosMSA.h
index 5f3d332..ad0bf93c 100644
--- a/third_party/WebKit/Source/platform/cpu/mips/CommonMacrosMSA.h
+++ b/third_party/WebKit/Source/platform/cpu/mips/CommonMacrosMSA.h
@@ -12,6 +12,11 @@
 #define CLANG_BUILD
 #endif
 
+typedef union {
+  int32_t intVal;
+  float floatVal;
+} FloatInt;
+
 #ifdef CLANG_BUILD
 #define SRLI_B(a, b) __msa_srli_b((v16i8)a, b)
 #define SRLI_H(a, b) __msa_srli_h((v8i16)a, b)
@@ -664,10 +669,58 @@
     DIV2(in4, in5, in6, in7, out2, out3);                                    \
   }
 
+/* Description : Logical AND of 4 pairs of vectors with mask
+   Arguments   : Inputs  - in0, in1, in2, in3, mask
+                 Outputs - in0, in1, in2, in3
+   Details     : Each element in 'in0' is logically AND'ed with mask
+                 Each element in 'in1' is logically AND'ed with mask
+                 Each element in 'in2' is logically AND'ed with mask
+                 Each element in 'in3' is logically AND'ed with mask
+*/
+#define AND_W4(RTYPE, in0, in1, in2, in3, mask) \
+  {                                             \
+    in0 = (RTYPE)((v16i8)in0 & (v16i8)mask);    \
+    in1 = (RTYPE)((v16i8)in1 & (v16i8)mask);    \
+    in2 = (RTYPE)((v16i8)in2 & (v16i8)mask);    \
+    in3 = (RTYPE)((v16i8)in3 & (v16i8)mask);    \
+  }
+#define AND_W4_SP(...) AND_W4(v4f32, __VA_ARGS__)
+
+/* Description : Addition of 2 pairs of vectors
+   Arguments   : Inputs  - in0, in1, in2, in3
+                 Outputs - out0, out1
+   Details     : Each element in 'in0' is added to 'in1' and result is written
+                 to 'out0'
+                 Each element in 'in2' is added to 'in3' and result is written
+                 to 'out1'
+*/
+#define ADD2(in0, in1, in2, in3, out0, out1) \
+  {                                          \
+    out0 = in0 + in1;                        \
+    out1 = in2 + in3;                        \
+  }
+
+/* Description : Addition of 4 pairs of vectors
+   Arguments   : Inputs  - in0, in1, in2, in3, in4, in5, in6, in7
+                 Outputs - out0, out1
+   Details     : Each element in 'in0' is added to 'in1' and result is written
+                 to 'out0'
+                 Each element in 'in2' is added to 'in3' and result is written
+                 to 'out1'
+                 Each element in 'in4' is added to 'in5' and result is written
+                 to 'out2'
+                 Each element in 'in6' is added to 'in7' and result is written
+                 to 'out3'
+*/
+#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, out0, out1, out2, out3) \
+  {                                                                          \
+    ADD2(in0, in1, in2, in3, out0, out1);                                    \
+    ADD2(in4, in5, in6, in7, out2, out3);                                    \
+  }
+
 /* Description : Vector Floating-Point Convert from Unsigned Integer
    Arguments   : Inputs  - in0, in1
                  Outputs - out0, out1
-   Details     :
 */
 #define FFINTU_W2(RTYPE, in0, in1, out0, out1) \
   {                                            \
@@ -676,6 +729,10 @@
   }
 #define FFINTU_W2_SP(...) FFINTU_W2(v4f32, __VA_ARGS__)
 
+/* Description : Vector Floating-Point Convert from Unsigned Integer
+   Arguments   : Inputs  - in0, in1, in2, in3
+                 Outputs - out0, out1, out2, out3
+*/
 #define FFINTU_W4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3) \
   {                                                                  \
     FFINTU_W2(RTYPE, in0, in1, out0, out1);                          \
@@ -686,7 +743,6 @@
 /* Description : Vector Floating-Point Truncate and Convert to Unsigned Integer
    Arguments   : Inputs  - in0, in1
                  Outputs - out0, out1
-   Details     :
 */
 #define FTRUNCU_W2(RTYPE, in0, in1, out0, out1) \
   {                                             \
@@ -695,6 +751,10 @@
   }
 #define FTRUNCU_W2_UB(...) FTRUNCU_W2(v16u8, __VA_ARGS__)
 
+/* Description : Vector Floating-Point Truncate and Convert to Unsigned Integer
+   Arguments   : Inputs  - in0, in1, in2, in3
+                 Outputs - out0, out1, out2, out3
+*/
 #define FTRUNCU_W4(RTYPE, in0, in1, in2, in3, out0, out1, out2, out3) \
   {                                                                   \
     FTRUNCU_W2(RTYPE, in0, in1, out0, out1);                          \
@@ -702,4 +762,53 @@
   }
 #define FTRUNCU_W4_UB(...) FTRUNCU_W4(v16u8, __VA_ARGS__)
 
+/* Description : Vector Floating-Point multiply with scale and accumulate
+   Arguments   : Inputs  - in0, in1, in2, in3, out0, out1, out2, out3, scale
+                 Outputs - out0, out1, out2, out3
+*/
+#define VSMA4(in0, in1, in2, in3, out0, out1, out2, out3, scale) \
+  {                                                              \
+    out0 += in0 * scale;                                         \
+    out1 += in1 * scale;                                         \
+    out2 += in2 * scale;                                         \
+    out3 += in3 * scale;                                         \
+  }
+
+/* Description : Vector Floating-Point multiply with scale
+   Arguments   : Inputs  - in0, in1, in2, in3, scale
+                 Outputs - out0, out1, out2, out3
+*/
+#define VSMUL4(in0, in1, in2, in3, out0, out1, out2, out3, scale) \
+  {                                                               \
+    out0 = in0 * scale;                                           \
+    out1 = in1 * scale;                                           \
+    out2 = in2 * scale;                                           \
+    out3 = in3 * scale;                                           \
+  }
+
+/* Description : Vector Floating-Point max value
+   Arguments   : Inputs - in0, in1, in2, in3, max
+                 Output - max
+*/
+#define VMAX_W4(RTYPE, in0, in1, in2, in3, max)        \
+  {                                                    \
+    max = (RTYPE)__msa_fmax_w((v4f32)max, (v4f32)in0); \
+    max = (RTYPE)__msa_fmax_w((v4f32)max, (v4f32)in1); \
+    max = (RTYPE)__msa_fmax_w((v4f32)max, (v4f32)in2); \
+    max = (RTYPE)__msa_fmax_w((v4f32)max, (v4f32)in3); \
+  }
+#define VMAX_W4_SP(...) VMAX_W4(v4f32, __VA_ARGS__)
+
+/* Description : Vector Floating-Point clip to min max
+   Arguments   : Inputs  - in0, in1, in2, in3, min, max
+                 Outputs - out0, out1, out2, out3
+*/
+#define VCLIP4(in0, in1, in2, in3, min, max, out0, out1, out2, out3) \
+  {                                                                  \
+    out0 = __msa_fmax_w(__msa_fmin_w(in0, max), min);                \
+    out1 = __msa_fmax_w(__msa_fmin_w(in1, max), min);                \
+    out2 = __msa_fmax_w(__msa_fmin_w(in2, max), min);                \
+    out3 = __msa_fmax_w(__msa_fmin_w(in3, max), min);                \
+  }
+
 #endif  // CommonMacrosMSA_h
diff --git a/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h b/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h
index e6fa7a2..71a01ca 100644
--- a/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h
+++ b/third_party/WebKit/Source/platform/exported/WebScrollbarImpl.h
@@ -30,6 +30,9 @@
 #include "public/platform/WebScrollbar.h"
 #include "wtf/Allocator.h"
 #include "wtf/Noncopyable.h"
+#include "wtf/PtrUtil.h"
+
+#include <memory>
 
 namespace blink {
 
@@ -39,8 +42,8 @@
   WTF_MAKE_NONCOPYABLE(WebScrollbarImpl);
 
  public:
-  static WebScrollbarImpl* create(Scrollbar* scrollbar) {
-    return new WebScrollbarImpl(scrollbar);
+  static std::unique_ptr<WebScrollbarImpl> create(Scrollbar* scrollbar) {
+    return wrapUnique(new WebScrollbarImpl(scrollbar));
   }
 
   // Implement WebScrollbar methods
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
index ac44f52..db8d6d6b 100644
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -562,9 +562,9 @@
   }
 
   if (m_surface && surfaceIsAccelerated && !m_layer) {
-    m_layer = wrapUnique(
+    m_layer =
         Platform::current()->compositorSupport()->createExternalTextureLayer(
-            this));
+            this);
     m_layer->setOpaque(m_opacityMode == Opaque);
     m_layer->setBlendBackgroundColor(m_opacityMode != Opaque);
     GraphicsLayer::registerContentsLayer(m_layer->layer());
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp
index 9f07588..4355cae 100644
--- a/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp
+++ b/third_party/WebKit/Source/platform/graphics/CanvasSurfaceLayerBridge.cpp
@@ -14,7 +14,6 @@
 #include "public/platform/WebLayer.h"
 #include "ui/gfx/geometry/size.h"
 #include "wtf/Functional.h"
-#include "wtf/PtrUtil.h"
 
 namespace blink {
 
@@ -40,9 +39,8 @@
   m_surfaceLayer->SetSurfaceId(m_surfaceId, 1.f,
                                gfx::Size(canvasWidth, canvasHeight));
 
-  m_webLayer = wrapUnique(
-      Platform::current()->compositorSupport()->createLayerFromCCLayer(
-          m_surfaceLayer.get()));
+  m_webLayer = Platform::current()->compositorSupport()->createLayerFromCCLayer(
+      m_surfaceLayer.get());
   GraphicsLayer::registerContentsLayer(m_webLayer.get());
   return true;
 }
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
index 18d7bc3..2eac66ac 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -116,9 +116,8 @@
 #endif
 
   m_contentLayerDelegate = wrapUnique(new ContentLayerDelegate(this));
-  m_layer =
-      wrapUnique(Platform::current()->compositorSupport()->createContentLayer(
-          m_contentLayerDelegate.get()));
+  m_layer = Platform::current()->compositorSupport()->createContentLayer(
+      m_contentLayerDelegate.get());
   m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
   m_layer->layer()->setLayerClient(this);
 }
@@ -1040,8 +1039,8 @@
 
   if (image && skImage) {
     if (!m_imageLayer) {
-      m_imageLayer = wrapUnique(
-          Platform::current()->compositorSupport()->createImageLayer());
+      m_imageLayer =
+          Platform::current()->compositorSupport()->createImageLayer();
       registerContentsLayer(m_imageLayer->layer());
     }
     m_imageLayer->setImage(skImage.get());
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
index a9927e9..66a8962b 100644
--- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
+++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
@@ -163,9 +163,8 @@
   if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
     return;
   m_rootLayer = cc::Layer::Create();
-  m_webLayer = wrapUnique(
-      Platform::current()->compositorSupport()->createLayerFromCCLayer(
-          m_rootLayer.get()));
+  m_webLayer = Platform::current()->compositorSupport()->createLayerFromCCLayer(
+      m_rootLayer.get());
   m_isTrackingRasterInvalidations = false;
 }
 
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
index 402465f..0f9a35d 100644
--- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -49,7 +49,6 @@
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "third_party/skia/include/gpu/gl/GrGLTypes.h"
 #include "wtf/CheckedNumeric.h"
-#include "wtf/PtrUtil.h"
 #include "wtf/typed_arrays/ArrayBufferContents.h"
 #include <algorithm>
 #include <memory>
@@ -759,9 +758,9 @@
 
 WebLayer* DrawingBuffer::platformLayer() {
   if (!m_layer) {
-    m_layer = wrapUnique(
+    m_layer =
         Platform::current()->compositorSupport()->createExternalTextureLayer(
-            this));
+            this);
 
     m_layer->setOpaque(!m_wantAlphaChannel);
     m_layer->setBlendBackgroundColor(m_wantAlphaChannel);
diff --git a/third_party/WebKit/Source/platform/network/DEPS b/third_party/WebKit/Source/platform/network/DEPS
index 5eb30d59..49d9ffa 100644
--- a/third_party/WebKit/Source/platform/network/DEPS
+++ b/third_party/WebKit/Source/platform/network/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
     "+components/link_header_util",
+    "+components/mime_util",
     # net/ includes should be allowed only in a limited set of directories,
     # so we have separate DEPS from platform's one.
     "+net/base",
diff --git a/third_party/WebKit/Source/platform/network/NetworkUtils.cpp b/third_party/WebKit/Source/platform/network/NetworkUtils.cpp
index f64443e..2305b6a 100644
--- a/third_party/WebKit/Source/platform/network/NetworkUtils.cpp
+++ b/third_party/WebKit/Source/platform/network/NetworkUtils.cpp
@@ -4,9 +4,17 @@
 
 #include "platform/network/NetworkUtils.h"
 
+#include "components/mime_util/mime_util.h"
+#include "net/base/data_url.h"
 #include "net/base/ip_address.h"
+#include "net/base/net_errors.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
+#include "platform/SharedBuffer.h"
+#include "platform/weborigin/KURL.h"
+#include "public/platform/URLConversion.h"
+#include "public/platform/WebString.h"
+#include "url/gurl.h"
 #include "wtf/text/StringUTF8Adaptor.h"
 #include "wtf/text/WTFString.h"
 
@@ -53,6 +61,22 @@
   return String(domain.data(), domain.length());
 }
 
+PassRefPtr<SharedBuffer> parseDataURL(const KURL& url,
+                                      AtomicString& mimetype,
+                                      AtomicString& charset) {
+  std::string utf8MimeType;
+  std::string utf8Charset;
+  std::string data;
+  if (net::DataURL::Parse(WebStringToGURL(url.getString()), &utf8MimeType,
+                          &utf8Charset, &data) &&
+      mime_util::IsSupportedMimeType(utf8MimeType)) {
+    mimetype = WebString::fromUTF8(utf8MimeType);
+    charset = WebString::fromUTF8(utf8Charset);
+    return SharedBuffer::create(data.data(), data.size());
+  }
+  return nullptr;
+}
+
 }  // NetworkUtils
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/network/NetworkUtils.h b/third_party/WebKit/Source/platform/network/NetworkUtils.h
index d59f4547..a579917 100644
--- a/third_party/WebKit/Source/platform/network/NetworkUtils.h
+++ b/third_party/WebKit/Source/platform/network/NetworkUtils.h
@@ -10,6 +10,9 @@
 
 namespace blink {
 
+class KURL;
+class SharedBuffer;
+
 namespace NetworkUtils {
 
 enum PrivateRegistryFilter {
@@ -24,6 +27,12 @@
 PLATFORM_EXPORT String getDomainAndRegistry(const String& host,
                                             PrivateRegistryFilter);
 
+// Returns the decoded data url if url had a supported mimetype and parsing was
+// successful.
+PLATFORM_EXPORT PassRefPtr<SharedBuffer> parseDataURL(const KURL&,
+                                                      AtomicString& mimetype,
+                                                      AtomicString& charset);
+
 }  // NetworkUtils
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
index dd253bc..8e44543 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.cpp
@@ -43,6 +43,10 @@
 #include "platform/scheduler/base/test_time_source.h"
 #include "platform/scheduler/child/scheduler_tqm_delegate_for_test.h"
 #include "platform/scheduler/renderer/renderer_scheduler_impl.h"
+#include "public/platform/WebContentLayer.h"
+#include "public/platform/WebExternalTextureLayer.h"
+#include "public/platform/WebImageLayer.h"
+#include "public/platform/WebScrollbarLayer.h"
 #include "wtf/CryptographicallyRandomNumber.h"
 #include "wtf/CurrentTime.h"
 #include "wtf/PtrUtil.h"
@@ -66,6 +70,45 @@
 
 }  // namespace
 
+std::unique_ptr<WebLayer> TestingCompositorSupport::createLayer() {
+  return nullptr;
+}
+
+std::unique_ptr<WebLayer> TestingCompositorSupport::createLayerFromCCLayer(
+    cc::Layer*) {
+  return nullptr;
+}
+
+std::unique_ptr<WebContentLayer> TestingCompositorSupport::createContentLayer(
+    WebContentLayerClient*) {
+  return nullptr;
+}
+std::unique_ptr<WebExternalTextureLayer>
+TestingCompositorSupport::createExternalTextureLayer(cc::TextureLayerClient*) {
+  return nullptr;
+}
+
+std::unique_ptr<WebImageLayer> TestingCompositorSupport::createImageLayer() {
+  return nullptr;
+}
+
+std::unique_ptr<WebScrollbarLayer>
+TestingCompositorSupport::createScrollbarLayer(
+    std::unique_ptr<WebScrollbar>,
+    WebScrollbarThemePainter,
+    std::unique_ptr<WebScrollbarThemeGeometry>) {
+  return nullptr;
+}
+
+std::unique_ptr<WebScrollbarLayer>
+TestingCompositorSupport::createSolidColorScrollbarLayer(
+    WebScrollbar::Orientation,
+    int thumbThickness,
+    int trackStart,
+    bool isLeftSideVerticalScrollbar) {
+  return nullptr;
+}
+
 TestingPlatformSupport::TestingPlatformSupport()
     : TestingPlatformSupport(TestingPlatformSupport::Config()) {}
 
diff --git a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
index 8935c5b..5cf5b13c 100644
--- a/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
+++ b/third_party/WebKit/Source/platform/testing/TestingPlatformSupport.h
@@ -62,7 +62,24 @@
 class WebCompositorSupport;
 class WebThread;
 
-class TestingCompositorSupport : public WebCompositorSupport {};
+class TestingCompositorSupport : public WebCompositorSupport {
+  std::unique_ptr<WebLayer> createLayer() override;
+  std::unique_ptr<WebLayer> createLayerFromCCLayer(cc::Layer*) override;
+  std::unique_ptr<WebContentLayer> createContentLayer(
+      WebContentLayerClient*) override;
+  std::unique_ptr<WebExternalTextureLayer> createExternalTextureLayer(
+      cc::TextureLayerClient*) override;
+  std::unique_ptr<WebImageLayer> createImageLayer() override;
+  std::unique_ptr<WebScrollbarLayer> createScrollbarLayer(
+      std::unique_ptr<WebScrollbar>,
+      WebScrollbarThemePainter,
+      std::unique_ptr<WebScrollbarThemeGeometry>) override;
+  std::unique_ptr<WebScrollbarLayer> createSolidColorScrollbarLayer(
+      WebScrollbar::Orientation,
+      int thumbThickness,
+      int trackStart,
+      bool isLeftSideVerticalScrollbar) override;
+};
 
 class TestingPlatformMockScheduler : public WebScheduler {
   WTF_MAKE_NONCOPYABLE(TestingPlatformMockScheduler);
diff --git a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
index a9db55e..da8a32e 100644
--- a/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
+++ b/third_party/WebKit/Source/web/LinkHighlightImpl.cpp
@@ -87,8 +87,8 @@
   WebCompositorSupport* compositorSupport =
       Platform::current()->compositorSupport();
   DCHECK(compositorSupport);
-  m_contentLayer = wrapUnique(compositorSupport->createContentLayer(this));
-  m_clipLayer = wrapUnique(compositorSupport->createLayer());
+  m_contentLayer = compositorSupport->createContentLayer(this);
+  m_clipLayer = compositorSupport->createLayer();
   m_clipLayer->setTransformOrigin(WebFloatPoint3D());
   m_clipLayer->addChild(m_contentLayer->layer());
 
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
index c28fcbe3..c522068 100644
--- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
+++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
@@ -188,10 +188,9 @@
     const WebServiceWorkerRequest& webRequest) {
   if (!OriginTrials::foreignFetchEnabled(workerGlobalScope())) {
     // If origin trial tokens have expired, or are otherwise no longer valid
-    // no events should be dispatched. We can check it in the browser process if
-    // the service worker is installed after M56. But if the service worker was
-    // installed in old version of Chrome (< M56) we have to check it in the
-    // renderer process (here).
+    // no events should be dispatched.
+    // TODO(mek): Ideally the browser wouldn't even start the service worker
+    // if its tokens have expired.
     ServiceWorkerGlobalScopeClient::from(workerGlobalScope())
         ->respondToFetchEvent(responseID, WTF::currentTime());
     ServiceWorkerGlobalScopeClient::from(workerGlobalScope())
diff --git a/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp b/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp
index e56eefe..8ced299e 100644
--- a/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/WebPluginContainerTest.cpp
@@ -65,7 +65,6 @@
 #include "web/WebViewImpl.h"
 #include "web/tests/FakeWebPlugin.h"
 #include "web/tests/FrameTestHelpers.h"
-#include "wtf/PtrUtil.h"
 #include <memory>
 
 using blink::testing::runPendingTasks;
@@ -679,8 +678,7 @@
  public:
   CompositedPlugin(WebLocalFrame* frame, const WebPluginParams& params)
       : FakeWebPlugin(frame, params),
-        m_layer(wrapUnique(
-            Platform::current()->compositorSupport()->createLayer())) {}
+        m_layer(Platform::current()->compositorSupport()->createLayer()) {}
 
   WebLayer* getWebLayer() const { return m_layer.get(); }
 
diff --git a/third_party/WebKit/public/platform/Platform.h b/third_party/WebKit/public/platform/Platform.h
index cbe6aca..708d13a59 100644
--- a/third_party/WebKit/public/platform/Platform.h
+++ b/third_party/WebKit/public/platform/Platform.h
@@ -363,14 +363,6 @@
       const blink::WebSecurityOrigin& cacheStorageOrigin,
       const WebString& cacheStorageCacheName) {}
 
-  // Returns the decoded data url if url had a supported mimetype and parsing
-  // was successful.
-  virtual WebData parseDataURL(const WebURL&,
-                               WebString& mimetype,
-                               WebString& charset) {
-    return WebData();
-  }
-
   virtual WebURLError cancelledError(const WebURL&) const {
     return WebURLError();
   }
diff --git a/third_party/WebKit/public/platform/WebCompositorSupport.h b/third_party/WebKit/public/platform/WebCompositorSupport.h
index 6a90e22..0ef1b3c 100644
--- a/third_party/WebKit/public/platform/WebCompositorSupport.h
+++ b/third_party/WebKit/public/platform/WebCompositorSupport.h
@@ -32,6 +32,8 @@
 #include "WebScrollbar.h"
 #include "WebScrollbarThemePainter.h"
 
+#include <memory>
+
 namespace cc {
 class Layer;
 class TextureLayerClient;
@@ -51,36 +53,28 @@
  public:
   // Layers -------------------------------------------------------
 
-  virtual WebLayer* createLayer() { return nullptr; }
+  virtual std::unique_ptr<WebLayer> createLayer() = 0;
 
-  virtual WebLayer* createLayerFromCCLayer(cc::Layer*) { return nullptr; }
+  virtual std::unique_ptr<WebLayer> createLayerFromCCLayer(cc::Layer*) = 0;
 
-  virtual WebContentLayer* createContentLayer(WebContentLayerClient*) {
-    return nullptr;
-  }
+  virtual std::unique_ptr<WebContentLayer> createContentLayer(
+      WebContentLayerClient*) = 0;
 
-  virtual WebExternalTextureLayer* createExternalTextureLayer(
-      cc::TextureLayerClient*) {
-    return nullptr;
-  }
+  virtual std::unique_ptr<WebExternalTextureLayer> createExternalTextureLayer(
+      cc::TextureLayerClient*) = 0;
 
-  virtual WebImageLayer* createImageLayer() { return nullptr; }
+  virtual std::unique_ptr<WebImageLayer> createImageLayer() = 0;
 
-  // The ownership of the WebScrollbarThemeGeometry pointer is passed to
-  // Chromium.
-  virtual WebScrollbarLayer* createScrollbarLayer(WebScrollbar*,
-                                                  WebScrollbarThemePainter,
-                                                  WebScrollbarThemeGeometry*) {
-    return nullptr;
-  }
+  virtual std::unique_ptr<WebScrollbarLayer> createScrollbarLayer(
+      std::unique_ptr<WebScrollbar>,
+      WebScrollbarThemePainter,
+      std::unique_ptr<WebScrollbarThemeGeometry>) = 0;
 
-  virtual WebScrollbarLayer* createSolidColorScrollbarLayer(
+  virtual std::unique_ptr<WebScrollbarLayer> createSolidColorScrollbarLayer(
       WebScrollbar::Orientation,
       int thumbThickness,
       int trackStart,
-      bool isLeftSideVerticalScrollbar) {
-    return nullptr;
-  }
+      bool isLeftSideVerticalScrollbar) = 0;
 
  protected:
   virtual ~WebCompositorSupport() {}
diff --git a/third_party/opus/BUILD.gn b/third_party/opus/BUILD.gn
index fbefab6..5e5c9cce 100644
--- a/third_party/opus/BUILD.gn
+++ b/third_party/opus/BUILD.gn
@@ -394,9 +394,6 @@
       deps = [
         ":convert_rtcd_assembler",
       ]
-
-      configs -= [ "//build/config/compiler:compiler_arm_fpu" ]
-      cflags += [ "-mfpu=neon" ]
     }
   }
 }
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index d1b35c81..8bc5849 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -78,6 +78,7 @@
       'Android Cloud Tests': 'android_debug_static_bot_x86',
       'Android Tests (x86 emulator)': 'android_debug_static_bot_x86',
       'Android Builder (dbg)': 'android_debug_static_bot_vr_shell',
+      'Android Builder Goma Canary (dbg)': 'android_debug_bot',
       'Android deterministic': 'android_without_codecs_release_bot_minimal_symbols',
       'Android deterministic (dbg)': 'android_debug_bot',
       'Blimp Android Client':
@@ -156,6 +157,7 @@
       'CrWinClngLLD64dbg': 'clang_tot_minimal_symbols_shared_debug_use_lld',
       'CrWinClngLLDdbg': 'clang_tot_minimal_symbols_shared_debug_use_lld_x86',
       'EarlGreyiOS': 'ios',
+      'GomaCanaryiOS': 'ios',
       'Headless Linux (dbg)': '//build/args/bots/chromium.fyi/headless_linux_dbg.gn',
       'MD Top Chrome ChromeOS material-hybrid': 'chromeos_with_codecs_debug_bot',
       'MD Top Chrome ChromeOS non-material': 'chromeos_with_codecs_debug_bot',
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 02f8281..0f9e7c8 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -51249,7 +51249,19 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.V4AddUnlumpedHashes.Time" units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to copy the SafeBrowsing list update as a string,
+    into a map which contains the hash prefixes that are looked up when a client
+    queries for the reputation of a resource (URL, full hash, etc.).
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.V4AddUnlumpedHashesTime" units="ms">
+  <obsolete>
+    Replaced by SafeBrowsing.V4AddUnlumpedHashes.Time.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Records the time it takes to copy the SafeBrowsing list update as a string,
@@ -51261,6 +51273,9 @@
 <histogram name="SafeBrowsing.V4ApplyUpdateResult"
     enum="SafeBrowsingV4ApplyUpdateResult">
   <owner>vakh@chromium.org</owner>
+  <obsolete>
+    Replaced by SafeBrowsing.V4*.ApplyUpdate.Result.
+  </obsolete>
   <summary>
     Track the result of applying the update fetched from the PVer4 service for a
     particular store.
@@ -51269,6 +51284,9 @@
 
 <histogram name="SafeBrowsing.V4ApplyUpdateResultWhenReadingFromDisk"
     enum="SafeBrowsingV4ApplyUpdateResult">
+  <obsolete>
+    Replaced by SafeBrowsing.V4ReadFromDisk.ApplyUpdate.Result.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Track the result of applying an update read from disk after parsing it
@@ -51278,6 +51296,9 @@
 
 <histogram name="SafeBrowsing.V4DecodeAdditionsResult"
     enum="SafeBrowsingV4DecodeResult">
+  <obsolete>
+    Replaced by SafeBrowsing.V4*.DecodeAdditions.Result.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Track the result of decoding the Rice-encoded list of additions of 4-byte
@@ -51287,6 +51308,9 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4DecodeAdditionsTime" units="ms">
+  <obsolete>
+    Replaced by SafeBrowsing.V4*.DecodeAdditions.Time.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Records the time it takes to decode the Rice-encoded additions to the
@@ -51296,6 +51320,9 @@
 
 <histogram name="SafeBrowsing.V4DecodeRemovalsResult"
     enum="SafeBrowsingV4DecodeResult">
+  <obsolete>
+    Replaced by SafeBrowsing.V4ProcessPartialUpdate.DecodeRemovals.Result.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Track the result of decoding the Rice-encoded list of indexes of hash
@@ -51305,6 +51332,9 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4DecodeRemovalsTime" units="ms">
+  <obsolete>
+    Replaced by SafeBrowsing.V4ProcessPartialUpdate.DecodeRemovals.Time.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Records the time it takes to decode the Rice-encoded removals from the
@@ -51327,6 +51357,9 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4MergeUpdateTime" units="ms">
+  <obsolete>
+    Replaced by SafeBrowsing.V4*.MergeUpdate.Time.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Records the time it takes to merge the existing state of the list with the
@@ -51335,7 +51368,58 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.V4ProcessFullUpdate.ApplyUpdate.Result"
+    enum="SafeBrowsingV4ApplyUpdateResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the result of applying a full update for a store received from PVer4
+    SafeBrowsing service.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessFullUpdate.ApplyUpdate.Time" units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to process a SafeBrowsing list full update. It
+    includes V4AddUnlumpedHashes.Time for each prefix-sized list, and
+    V4ProcessFullUpdate.MergeUpdate.Time. Additionally, if the update is
+    Rice-encoded, it includes V4ProcessFullUpdate.DecodeAdditions.Time for each
+    prefix-sized list that's Rice-encoded.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessFullUpdate.DecodeAdditions.Result"
+    enum="SafeBrowsingV4DecodeResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the result of decoding the Rice-encoded list of additions of 4-byte
+    hash prefixes. This is logged once per store, per update containing
+    Rice-encoded additions. This histogram is specific to processing full
+    updates received from the server.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessFullUpdate.DecodeAdditions.Time"
+    units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to decode the Rice-encoded additions to the
+    blacklist into raw format when applying a full update to a store.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessFullUpdate.MergeUpdate.Time" units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to merge the existing state of the list with a
+    full update received from the server.
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.V4ProcessFullUpdateTime" units="ms">
+  <obsolete>
+    Replaced by SafeBrowsing.V4ProcessFullUpdate.ApplyUpdate.Time.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Records the time it takes to process a SafeBrowsing list full update. It
@@ -51345,7 +51429,81 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.V4ProcessPartialUpdate.ApplyUpdate.Result"
+    enum="SafeBrowsingV4ApplyUpdateResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the result of applying a partial update for a store received from
+    PVer4 SafeBrowsing service.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessPartialUpdate.ApplyUpdate.Time"
+    units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to process a SafeBrowsing list partial update. It
+    includes V4AddUnlumpedHashes.Time for each prefix-sized list, and
+    SafeBrowsing.V4ProcessPartialUpdate.MergeUpdate.Time. Additionally, if the
+    update is Rice-encoded, it includes
+    V4ProcessPartialUpdate.DecodeRemovals.Time, and
+    V4ProcessPartialUpdate.DecodeAdditions.Time for each prefix-sized list
+    that's Rice-encoded.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessPartialUpdate.DecodeAdditions.Result"
+    enum="SafeBrowsingV4DecodeResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the result of decoding the Rice-encoded list of additions of 4-byte
+    hash prefixes. This is logged once per store, per update containing
+    Rice-encoded additions. This histogram is specific to processing partial
+    updates received from the server.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessPartialUpdate.DecodeAdditions.Time"
+    units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to decode the Rice-encoded additions to the
+    blacklist into raw format when applying a partial update to a store.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessPartialUpdate.DecodeRemovals.Result"
+    enum="SafeBrowsingV4DecodeResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the result of decoding the Rice-encoded list of indexes of hash
+    prefixes to remove since the last update. This is logged once per store, per
+    update containing Rice-encoded removals.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessPartialUpdate.DecodeRemovals.Time"
+    units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to decode the Rice-encoded removals from the
+    blacklist into raw format when applying a partial update to a store.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ProcessPartialUpdate.MergeUpdate.Time"
+    units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to merge the existing state of the list with a
+    partial update received from the server.
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.V4ProcessPartialUpdateTime" units="ms">
+  <obsolete>
+    Replaced by SafeBrowsing.V4ProcessPartialUpdate.ApplyUpdate.Time.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Records the time it takes to process a SafeBrowsing list partial update. It
@@ -51356,7 +51514,57 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.V4ReadFromDisk.ApplyUpdate.Result"
+    enum="SafeBrowsingV4ApplyUpdateResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the result of applying an ListUpdateResponse read from disk after
+    parsing it successfully as a protobuf.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ReadFromDisk.ApplyUpdate.Time" units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to read, parse, and process a SafeBrowsing list
+    stored on disk. This happens at Chromium start-up. It includes
+    V4AddUnlumpedHashes.Time for each prefix-sized list, and
+    SafeBrowsing.V4ReadFromDisk.MergeUpdate.Time. Additionally, if the file is
+    Rice-encoded, it includes V4ReadFromDisk.DecodeAdditions.Time for each
+    prefix-sized list that's Rice-encoded.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ReadFromDisk.DecodeAdditions.Result"
+    enum="SafeBrowsingV4DecodeResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the result of decoding the Rice-encoded list of additions of 4-byte
+    hash prefixes. This is logged once per store, per Chrome launch. It is
+    specific to processing V4StoreFileFormat proto read from disk.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ReadFromDisk.DecodeAdditions.Time" units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to decode the Rice-encoded additions to the
+    blacklist into raw format when reading a store file from disk.
+  </summary>
+</histogram>
+
+<histogram name="SafeBrowsing.V4ReadFromDisk.MergeUpdate.Time" units="ms">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Records the time it takes to perform in-memory copy of the map of raw hash
+    prefixes read from disk.
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.V4ReadFromDiskTime" units="ms">
+  <obsolete>
+    Replaced by SafeBrowsing.V4ReadFromDisk.ApplyUpdate.Time.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Records the time it takes to read, parse, and process a SafeBrowsing list
@@ -51367,8 +51575,20 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.V4StoreRead.Result"
+    enum="SafeBrowsingV4StoreReadResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the parsing results of reading the SafeBrowsing V4 store file from
+    disk. Recorded every time a store is read from disk.
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.V4StoreReadResult"
     enum="SafeBrowsingV4StoreReadResult">
+  <obsolete>
+    Replaced by SafeBrowsing.V4StoreRead.Result.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Track the parsing results of reading the SafeBrowsing V4 store file from
@@ -51384,8 +51604,20 @@
   </summary>
 </histogram>
 
+<histogram name="SafeBrowsing.V4StoreWrite.Result"
+    enum="SafeBrowsingV4StoreWriteResult">
+  <owner>vakh@chromium.org</owner>
+  <summary>
+    Track the results of writing the SafeBrowsing V4 store file to disk.
+    Recorded every time a store is written to disk.
+  </summary>
+</histogram>
+
 <histogram name="SafeBrowsing.V4StoreWriteResult"
     enum="SafeBrowsingV4StoreWriteResult">
+  <obsolete>
+    Replaced by SafeBrowsing.V4StoreWrite.Result.
+  </obsolete>
   <owner>vakh@chromium.org</owner>
   <summary>
     Track the results of writing the SafeBrowsing V4 store file to disk.
diff --git a/tools/perf/benchmarks/loading.py b/tools/perf/benchmarks/loading.py
index 66ff7c3..04cb69d4 100644
--- a/tools/perf/benchmarks/loading.py
+++ b/tools/perf/benchmarks/loading.py
@@ -12,7 +12,7 @@
 from telemetry.page import traffic_setting
 
 
-@benchmark.Disabled('all')  # crbug.com/654215
+@benchmark.Enabled('android')
 class LoadingMobile(perf_benchmark.PerfBenchmark):
   """ A benchmark measuring loading performance of mobile sites. """
 
@@ -22,6 +22,18 @@
     return page_cycler_v2.TimelineBasedMeasurementOptionsForLoadingMetric()
 
   @classmethod
+  def ShouldDisable(cls, possible_browser):
+    # crbug.com/619254
+    if possible_browser.browser_type == 'reference':
+      return True
+
+    # crbug.com/651188
+    if possible_browser.browser_type == 'android-webview':
+      return True
+
+    return False
+
+  @classmethod
   def Name(cls):
     return 'loading.mobile'
 
diff --git a/tools/perf/benchmarks/service_worker.py b/tools/perf/benchmarks/service_worker.py
index 99b07f5..71d6f2c 100644
--- a/tools/perf/benchmarks/service_worker.py
+++ b/tools/perf/benchmarks/service_worker.py
@@ -8,6 +8,7 @@
 
 from core import perf_benchmark
 
+from telemetry import benchmark
 from telemetry.core import util
 from telemetry.page import legacy_page_test
 from telemetry.timeline import async_slice as async_slice_module
@@ -173,6 +174,7 @@
     return 'service_worker.service_worker'
 
 
+@benchmark.Disabled('android-webview')  # http://crbug.com/653924
 class ServiceWorkerMicroBenchmarkPerfTest(perf_benchmark.PerfBenchmark):
   """This test is a microbenchmark of service worker.
 
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm
index d706579..2dc4afd 100644
--- a/ui/views/cocoa/bridged_native_widget.mm
+++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -589,7 +589,7 @@
   // mouse clicks till then.
   // TODO(karandeepb): Investigate whether similar technique is needed for other
   // dialog types.
-  if (layer() && [window_ isOpaque] &&
+  if (layer() && [window_ isOpaque] && !window_visible_ &&
       !native_widget_mac_->GetWidget()->IsModal()) {
     initial_visibility_suppressed_ = true;
     [window_ setAlphaValue:0.0];