diff --git a/BUILD.gn b/BUILD.gn
index 681f8a4..72893af 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -148,6 +148,7 @@
       "//tools/gn",
       "//tools/gn:gn_unittests",
       "//tools/perf/clear_system_cache",
+      "//tools/traffic_annotation/auditor:traffic_annotation_auditor",
       "//ui/accessibility:accessibility_unittests",
       "//ui/accessibility/extensions",
     ]
@@ -181,7 +182,7 @@
       "//mojo/edk/test:mojo_public_system_unittests",
       "//net:net_perftests",
       "//services/service_manager/public/cpp",
-      "//storage//browser:storage_unittests",
+      "//storage:storage_unittests",
       "//third_party/WebKit/Source/platform:blink_platform_unittests",
       "//third_party/WebKit/Source/platform/heap:blink_heap_unittests",
       "//third_party/WebKit/Source/platform/wtf:wtf_unittests",
diff --git a/DEPS b/DEPS
index b28b578..aad5983 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '63c64c6d52fb854d2b0380ff7f43349fe8ebabf3',
+  'v8_revision': '8b0dbb50bbb5f85413b32a1fc101d6ef5f0392dc',
   # 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.
@@ -232,7 +232,7 @@
     Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067',
 
   'src/third_party/webrtc':
-    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '118a3735394b55da76127370471a592d870c4b4c', # commit position 17786
+    Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '73c0f2ada2cec69680336eee7bb7ee2b49417753', # commit position 17805
 
   'src/third_party/openmax_dl':
     Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' +  Var('openmax_dl_revision'),
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc
index c04e5c4..99d2991 100644
--- a/base/memory/discardable_shared_memory.cc
+++ b/base/memory/discardable_shared_memory.cc
@@ -344,6 +344,11 @@
 // provide MADV_FREE which has the same result but memory is purged lazily.
 #if defined(OS_LINUX) || defined(OS_ANDROID)
 #define MADV_PURGE_ARGUMENT MADV_REMOVE
+#elif defined(OS_MACOSX)
+// MADV_FREE_REUSABLE is similar to MADV_FREE, but also marks the pages with the
+// reusable bit, which allows both Activity Monitor and memory-infra to
+// correctly track the pages.
+#define MADV_PURGE_ARGUMENT MADV_FREE_REUSABLE
 #else
 #define MADV_PURGE_ARGUMENT MADV_FREE
 #endif
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
index 59d08fc..c4cf630 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
@@ -136,6 +136,7 @@
      */
     @LargeTest
     @Feature({"CopylessPaste"})
+    @DisabledTest(message = "Flaky: crbug.com/713172")
     public void testValid() throws InterruptedException, TimeoutException {
         loadUrl(mTestServer.getURL(DATA_PAGE));
         mCallbackHelper.waitForCallback(0);
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index a1f0506..288dce4 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -1269,8 +1269,6 @@
   NavigateToFile("/password/between_parsing_and_rendering.html");
 
   NavigationObserver observer(WebContents());
-  std::unique_ptr<BubbleObserver> prompt_observer(
-      new BubbleObserver(WebContents()));
   std::string submit =
       "document.getElementById('username').value = 'temp';"
       "document.getElementById('password').value = 'random';"
@@ -1278,7 +1276,36 @@
   ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
   observer.Wait();
 
-  EXPECT_TRUE(prompt_observer->IsShowingSavePrompt());
+  EXPECT_TRUE(BubbleObserver(WebContents()).IsShowingSavePrompt());
+}
+
+// Test that if a hidden form gets dynamically added between the form parsing
+// and rendering, it still is registered, and autofilling works.
+IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
+                       HiddenFormAddedBetweenParsingAndRendering) {
+  // At first let us save a credential to the password store.
+  scoped_refptr<password_manager::TestPasswordStore> password_store =
+      static_cast<password_manager::TestPasswordStore*>(
+          PasswordStoreFactory::GetForProfile(
+              browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS)
+              .get());
+  autofill::PasswordForm signin_form;
+  signin_form.signon_realm = embedded_test_server()->base_url().spec();
+  signin_form.origin = embedded_test_server()->base_url();
+  signin_form.action = embedded_test_server()->base_url();
+  signin_form.username_value = base::ASCIIToUTF16("admin");
+  signin_form.password_value = base::ASCIIToUTF16("12345");
+  password_store->AddLogin(signin_form);
+
+  NavigateToFile("/password/between_parsing_and_rendering.html?hidden");
+
+  std::string show_form =
+      "document.getElementsByTagName('form')[0].style.display = 'block'";
+  ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), show_form));
+
+  // Wait until the username is filled, to make sure autofill kicked in.
+  WaitForElementValue("username", "admin");
+  CheckElementValue("password", "12345");
 }
 
 // Test that if there was no previous page load then the PasswordManagerDriver
@@ -1344,23 +1371,13 @@
   EXPECT_FALSE(password_store->IsEmpty());
 }
 
-// In some situations, multiple PasswordFormManager instances from
-// PasswordManager::pending_login_managers_ would match (via DoesManage) a form
-// to be provisionally saved. One of them might be a complete match, the other
-// all-but-action match. Normally, the former should be preferred, but if the
-// former has not finished matching, and the latter has, the latter should be
-// used (otherwise we'd give up even though we could have saved the password).
-//
-// Disabled on Mac and Linux due to flakiness: http://crbug.com/477812
-#if defined(OS_MACOSX) || defined(OS_LINUX)
-#define MAYBE_PreferPasswordFormManagerWhichFinishedMatching \
-  DISABLED_PreferPasswordFormManagerWhichFinishedMatching
-#else
-#define MAYBE_PreferPasswordFormManagerWhichFinishedMatching \
-  PreferPasswordFormManagerWhichFinishedMatching
-#endif
+// Fill out a form and click a button. The Javascript removes the form, creates
+// a similar one with another action, fills it out and submits. Chrome can
+// manage to detect the new one and create a complete matching
+// PasswordFormManager. Otherwise, the all-but-action matching PFM should be
+// used. Regardless of the internals the user sees the bubble in 100% cases.
 IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTestBase,
-                       MAYBE_PreferPasswordFormManagerWhichFinishedMatching) {
+                       PreferPasswordFormManagerWhichFinishedMatching) {
   NavigateToFile("/password/create_form_copy_on_submit.html");
 
   NavigationObserver observer(WebContents());
@@ -1373,6 +1390,7 @@
   ASSERT_TRUE(content::ExecuteScript(RenderViewHost(), submit));
   observer.Wait();
 
+  WaitForPasswordStore();
   EXPECT_TRUE(prompt_observer->IsShowingSavePrompt());
 }
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 3b4f230..cabebd5 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1529,6 +1529,18 @@
       "views/page_info/permission_selector_row.cc",
       "views/page_info/permission_selector_row.h",
       "views/page_info/permission_selector_row_observer.h",
+      "views/passwords/account_chooser_dialog_view.cc",
+      "views/passwords/account_chooser_dialog_view.h",
+      "views/passwords/auto_signin_first_run_dialog_view.cc",
+      "views/passwords/auto_signin_first_run_dialog_view.h",
+      "views/passwords/credentials_item_view.cc",
+      "views/passwords/credentials_item_view.h",
+      "views/passwords/credentials_selection_view.cc",
+      "views/passwords/credentials_selection_view.h",
+      "views/passwords/manage_password_items_view.cc",
+      "views/passwords/manage_password_items_view.h",
+      "views/passwords/manage_passwords_bubble_view.cc",
+      "views/passwords/manage_passwords_bubble_view.h",
       "views/payments/credit_card_editor_view_controller.cc",
       "views/payments/credit_card_editor_view_controller.h",
       "views/payments/cvc_unmask_view_controller.cc",
@@ -1822,18 +1834,6 @@
         "views/omnibox/omnibox_view_views.h",
         "views/outdated_upgrade_bubble_view.cc",
         "views/outdated_upgrade_bubble_view.h",
-        "views/passwords/account_chooser_dialog_view.cc",
-        "views/passwords/account_chooser_dialog_view.h",
-        "views/passwords/auto_signin_first_run_dialog_view.cc",
-        "views/passwords/auto_signin_first_run_dialog_view.h",
-        "views/passwords/credentials_item_view.cc",
-        "views/passwords/credentials_item_view.h",
-        "views/passwords/credentials_selection_view.cc",
-        "views/passwords/credentials_selection_view.h",
-        "views/passwords/manage_password_items_view.cc",
-        "views/passwords/manage_password_items_view.h",
-        "views/passwords/manage_passwords_bubble_view.cc",
-        "views/passwords/manage_passwords_bubble_view.h",
         "views/passwords/manage_passwords_icon_views.cc",
         "views/passwords/manage_passwords_icon_views.h",
         "views/permission_bubble/chooser_bubble_ui_view.cc",
@@ -2886,8 +2886,8 @@
         "cocoa/passwords/confirmation_password_saved_view_controller.mm",
         "cocoa/passwords/credential_item_button.h",
         "cocoa/passwords/credential_item_button.mm",
-        "cocoa/passwords/credentials_selection_view.h",
-        "cocoa/passwords/credentials_selection_view.mm",
+        "cocoa/passwords/credentials_selection_view_cocoa.h",
+        "cocoa/passwords/credentials_selection_view_cocoa.mm",
         "cocoa/passwords/manage_passwords_view_controller.h",
         "cocoa/passwords/manage_passwords_view_controller.mm",
         "cocoa/passwords/password_item_views.h",
diff --git a/chrome/browser/ui/cocoa/passwords/credentials_selection_view.h b/chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.h
similarity index 95%
rename from chrome/browser/ui/cocoa/passwords/credentials_selection_view.h
rename to chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.h
index e6d4b12..5718376 100644
--- a/chrome/browser/ui/cocoa/passwords/credentials_selection_view.h
+++ b/chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.h
@@ -1,8 +1,8 @@
 // Copyright 2015 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-#ifndef CHROME_BROWSER_UI_COCOA_PASSWORDS_CREDENTIALS_SELECTION_VIEW_H_
-#define CHROME_BROWSER_UI_COCOA_PASSWORDS_CREDENTIALS_SELECTION_VIEW_H_
+#ifndef CHROME_BROWSER_UI_COCOA_PASSWORDS_CREDENTIALS_SELECTION_VIEW_COCOA_H_
+#define CHROME_BROWSER_UI_COCOA_PASSWORDS_CREDENTIALS_SELECTION_VIEW_COCOA_H_
 
 #import <Cocoa/Cocoa.h>
 
@@ -24,4 +24,4 @@
 - (const autofill::PasswordForm*)getSelectedCredentials;
 @end
 
-#endif  // CHROME_BROWSER_UI_COCOA_PASSWORDS_CREDENTIALS_SELECTION_VIEW_H_
+#endif  // CHROME_BROWSER_UI_COCOA_PASSWORDS_CREDENTIALS_SELECTION_VIEW_COCOA_H_
diff --git a/chrome/browser/ui/cocoa/passwords/credentials_selection_view.mm b/chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.mm
similarity index 96%
rename from chrome/browser/ui/cocoa/passwords/credentials_selection_view.mm
rename to chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.mm
index b2af0e3..e6319c3 100644
--- a/chrome/browser/ui/cocoa/passwords/credentials_selection_view.mm
+++ b/chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.mm
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import "chrome/browser/ui/cocoa/passwords/credentials_selection_view.h"
+#import "chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.h"
 
 #include <stddef.h>
 
@@ -61,8 +61,8 @@
 
     // Create the pop up button with usernames and the password field.
     usernamePopUpButton_.reset([CreateUsernamesPopUpButton(
-        model_->local_credentials(),
-        model_->pending_password().username_value) retain]);
+        model_->local_credentials(), model_->pending_password().username_value)
+        retain]);
     passwordField_.reset(
         [PasswordLabel(model_->pending_password().password_value) retain]);
 
diff --git a/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller.mm b/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller.mm
index 3580d4e..24cfabb 100644
--- a/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller.mm
+++ b/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller.mm
@@ -4,7 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller.h"
 
-#import "chrome/browser/ui/cocoa/passwords/credentials_selection_view.h"
+#import "chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.h"
 #import "chrome/browser/ui/cocoa/passwords/passwords_list_view_controller.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
 #include "chrome/grit/generated_resources.h"
diff --git a/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller_unittest.mm b/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller_unittest.mm
index 2ffef89..e55ec0b 100644
--- a/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller_unittest.mm
@@ -9,7 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #import "chrome/browser/ui/cocoa/bubble_combobox.h"
 #include "chrome/browser/ui/cocoa/passwords/base_passwords_controller_test.h"
-#import "chrome/browser/ui/cocoa/passwords/credentials_selection_view.h"
+#import "chrome/browser/ui/cocoa/passwords/credentials_selection_view_cocoa.h"
 #import "chrome/browser/ui/cocoa/passwords/passwords_list_view_controller.h"
 #import "chrome/browser/ui/cocoa/passwords/update_pending_password_view_controller.h"
 #include "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h
index 980201b..c887dec 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h
+++ b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.h
@@ -20,6 +20,8 @@
       Profile* profile,
       const std::string& username,
       std::unique_ptr<ui::ProfileSigninConfirmationDelegate> delegate) override;
+  void ShowManagePasswordsBubble(bool user_action) override;
+  void HideManagePasswordsBubble() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TabDialogsViewsMac);
diff --git a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm
index d71c1f2..6cf7a6e 100644
--- a/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm
+++ b/chrome/browser/ui/cocoa/tab_dialogs_views_mac.mm
@@ -4,8 +4,20 @@
 
 #include "chrome/browser/ui/cocoa/tab_dialogs_views_mac.h"
 
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/cocoa/browser_window_controller.h"
+#import "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h"
+#import "chrome/browser/ui/cocoa/passwords/passwords_bubble_controller.h"
 #include "chrome/browser/ui/views/collected_cookies_views.h"
+#include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
 #include "chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.h"
+#include "content/public/browser/web_contents.h"
+#import "ui/base/cocoa/cocoa_base_utils.h"
+#include "ui/base/material_design/material_design_controller.h"
+#import "ui/gfx/mac/coordinate_conversion.h"
 
 TabDialogsViewsMac::TabDialogsViewsMac(content::WebContents* contents)
     : TabDialogsCocoa(contents) {}
@@ -25,3 +37,55 @@
   ProfileSigninConfirmationDialogViews::ShowDialog(browser, profile, username,
                                                    std::move(delegate));
 }
+
+void TabDialogsViewsMac::ShowManagePasswordsBubble(bool user_action) {
+  if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+    TabDialogsCocoa::ShowManagePasswordsBubble(user_action);
+    return;
+  }
+  NSWindow* window = [web_contents()->GetNativeView() window];
+  if (!window) {
+    // The tab isn't active right now.
+    return;
+  }
+
+  // Don't show the bubble again if it's already showing. A second click on the
+  // location icon in the omnibox will dismiss an open bubble. This behaviour is
+  // consistent with the non-Mac views implementation.
+  // Note that when the browser is toolkit-views, IsBubbleShown() is checked
+  // earlier because the bubble is shown on mouse release (but dismissed on
+  // mouse pressed). A Cocoa browser does both on mouse pressed, so a check
+  // when showing is sufficient.
+  if (ManagePasswordsBubbleView::manage_password_bubble())
+    return;
+
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+  BrowserWindowController* bwc =
+      [BrowserWindowController browserWindowControllerForWindow:window];
+  gfx::Point anchor_point =
+      gfx::ScreenPointFromNSPoint(ui::ConvertPointFromWindowToScreen(
+          browser->window()->GetNativeWindow(), [bwc bookmarkBubblePoint]));
+  gfx::NativeView parent =
+      platform_util::GetViewForWindow(browser->window()->GetNativeWindow());
+  DCHECK(parent);
+
+  LocationBarBubbleDelegateView::DisplayReason reason =
+      user_action ? LocationBarBubbleDelegateView::USER_GESTURE
+                  : LocationBarBubbleDelegateView::AUTOMATIC;
+  ManagePasswordsBubbleView* bubble_view = new ManagePasswordsBubbleView(
+      web_contents(), nullptr, anchor_point, reason);
+  bubble_view->set_arrow(views::BubbleBorder::TOP_RIGHT);
+  bubble_view->set_parent_window(parent);
+  views::BubbleDialogDelegateView::CreateBubble(bubble_view);
+  bubble_view->ShowForReason(reason);
+  KeepBubbleAnchored(bubble_view);
+}
+
+void TabDialogsViewsMac::HideManagePasswordsBubble() {
+  // Close toolkit-views bubble.
+  if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+    TabDialogsCocoa::HideManagePasswordsBubble();
+    return;
+  }
+  ManagePasswordsBubbleView::CloseCurrentBubble();
+}
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
index 27543b4..0d18c6b 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
@@ -49,6 +49,7 @@
 
 LocationBarBubbleDelegateView::LocationBarBubbleDelegateView(
     views::View* anchor_view,
+    const gfx::Point& anchor_point,
     content::WebContents* web_contents)
     : BubbleDialogDelegateView(anchor_view,
                                anchor_view ? views::BubbleBorder::TOP_RIGHT
@@ -61,13 +62,22 @@
         content::Source<FullscreenController>(
             browser->exclusive_access_manager()->fullscreen_controller()));
   }
+  if (!anchor_view)
+    SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
+
   // Compensate for built-in vertical padding in the anchor view's image.
   // In the case of Harmony, this is just compensating for the location bar's
   // border thickness, as the bubble's top border should overlap it.
+  // When anchor is controlled by the |anchor_point| this inset is ignored.
   set_anchor_view_insets(gfx::Insets(
       GetLayoutConstant(LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET), 0));
 }
 
+LocationBarBubbleDelegateView::LocationBarBubbleDelegateView(
+    views::View* anchor_view,
+    content::WebContents* web_contents)
+    : LocationBarBubbleDelegateView(anchor_view, gfx::Point(), web_contents) {}
+
 LocationBarBubbleDelegateView::~LocationBarBubbleDelegateView() {}
 
 void LocationBarBubbleDelegateView::ShowForReason(DisplayReason reason) {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h
index c83cd43..453d7e0 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h
@@ -34,6 +34,15 @@
     AUTOMATIC,
   };
 
+  // Constructs LocationBarBubbleDelegateView. Anchors the bubble to
+  // |anchor_view| when it is not nullptr or alternatively, to |anchor_point|.
+  // Registers with a fullscreen controller identified by |web_contents| to
+  // close the bubble if the fullscreen state changes.
+  LocationBarBubbleDelegateView(views::View* anchor_view,
+                                const gfx::Point& anchor_point,
+                                content::WebContents* web_contents);
+
+  // TODO(varkha): Delete this override and use the constructor above.
   LocationBarBubbleDelegateView(views::View* anchor_view,
                                 content::WebContents* web_contents);
   ~LocationBarBubbleDelegateView() override;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
index 5f5471b..62b185b 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -8,13 +8,15 @@
 #include "base/metrics/user_metrics.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/browser/ui/passwords/password_dialog_prompts.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/harmony/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/passwords/credentials_item_view.h"
 #include "chrome/browser/ui/views/passwords/credentials_selection_view.h"
 #include "chrome/browser/ui/views/passwords/manage_password_items_view.h"
@@ -24,6 +26,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_features.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/native_theme/native_theme.h"
@@ -39,6 +42,10 @@
 #include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#endif
+
 #if defined(OS_WIN)
 #include "chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.h"
 #endif
@@ -235,10 +242,15 @@
   Browser* browser =
       chrome::FindBrowserWithWebContents(parent_->web_contents());
   DCHECK(browser);
+
+// Sign-in dialogs opened for inactive browser windows do not auto-close on
+// MacOS. This matches existing Cocoa bubble behavior.
+// TODO(varkha): Remove the limitation as part of http://crbug/671916 .
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
   observed_browser_.Add(browser_view->GetWidget());
-
-  if (browser_view->IsActive())
+#endif
+  if (browser->window()->IsActive())
     timer_.Start(FROM_HERE, GetTimeout(), this, &AutoSigninView::OnTimer);
 }
 
@@ -697,6 +709,7 @@
 ManagePasswordsBubbleView* ManagePasswordsBubbleView::manage_passwords_bubble_ =
     NULL;
 
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 // static
 void ManagePasswordsBubbleView::ShowBubble(
     content::WebContents* web_contents,
@@ -718,8 +731,9 @@
           browser_view->GetLocationBarView()->manage_passwords_icon_view();
     }
   }
-  manage_passwords_bubble_ = new ManagePasswordsBubbleView(
-      web_contents, anchor_view, reason);
+  new ManagePasswordsBubbleView(web_contents, anchor_view, gfx::Point(),
+                                reason);
+  DCHECK(manage_passwords_bubble_);
 
   if (is_fullscreen)
     manage_passwords_bubble_->set_parent_window(web_contents->GetNativeView());
@@ -739,6 +753,7 @@
 
   manage_passwords_bubble_->ShowForReason(reason);
 }
+#endif  // !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
 
 // static
 void ManagePasswordsBubbleView::CloseCurrentBubble() {
@@ -760,18 +775,20 @@
 ManagePasswordsBubbleView::ManagePasswordsBubbleView(
     content::WebContents* web_contents,
     views::View* anchor_view,
+    const gfx::Point& anchor_point,
     DisplayReason reason)
-    : LocationBarBubbleDelegateView(anchor_view, web_contents),
+    : LocationBarBubbleDelegateView(anchor_view, anchor_point, web_contents),
       model_(PasswordsModelDelegateFromWebContents(web_contents),
              reason == AUTOMATIC ? ManagePasswordsBubbleModel::AUTOMATIC
                                  : ManagePasswordsBubbleModel::USER_ACTION),
       initially_focused_view_(nullptr) {
   mouse_handler_.reset(new WebContentMouseHandler(this, this->web_contents()));
+  manage_passwords_bubble_ = this;
 }
 
 ManagePasswordsBubbleView::~ManagePasswordsBubbleView() {
   if (manage_passwords_bubble_ == this)
-    manage_passwords_bubble_ = NULL;
+    manage_passwords_bubble_ = nullptr;
 }
 
 views::View* ManagePasswordsBubbleView::GetInitiallyFocusedView() {
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h
index 170b634..b584af2 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
+#include "ui/base/ui_features.h"
 
 namespace content {
 class WebContents;
@@ -25,9 +26,11 @@
  public:
   static constexpr int kDesiredBubbleWidth = 370;
 
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   // Shows the bubble.
   static void ShowBubble(content::WebContents* web_contents,
                          DisplayReason reason);
+#endif
 
   // Closes the existing bubble.
   static void CloseCurrentBubble();
@@ -40,6 +43,11 @@
     return manage_passwords_bubble_;
   }
 
+  ManagePasswordsBubbleView(content::WebContents* web_contents,
+                            views::View* anchor_view,
+                            const gfx::Point& anchor_point,
+                            DisplayReason reason);
+
   content::WebContents* web_contents() const;
 
 #if defined(UNIT_TEST)
@@ -62,9 +70,6 @@
   class SignInPromoView;
   class UpdatePendingView;
 
-  ManagePasswordsBubbleView(content::WebContents* web_contents,
-                            views::View* anchor_view,
-                            DisplayReason reason);
   ~ManagePasswordsBubbleView() override;
 
   // LocationBarBubbleDelegateView:
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc
index f3c3a6f..d664a1b 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc
@@ -4,9 +4,11 @@
 
 #include "chrome/browser/ui/views/passwords/manage_passwords_bubble_view.h"
 
+#include "base/command_line.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/passwords/manage_passwords_test.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "ui/base/ui_base_switches.h"
 
 class ManagePasswordsBubbleDialogViewTest
     : public SupportsTestDialog<ManagePasswordsTest> {
@@ -28,6 +30,13 @@
     }
   }
 
+  // content::BrowserTestBase:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+#if defined(OS_MACOSX)
+    command_line->AppendSwitch(switches::kExtendMdToSecondaryUi);
+#endif
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ManagePasswordsBubbleDialogViewTest);
 };
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
index 1579d11..8c6868c 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/passwords/manage_passwords_test.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
+#include "chrome/browser/ui/tab_dialogs.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h"
@@ -26,7 +27,8 @@
 #include "content/public/common/content_features.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "ui/views/test/widget_test.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/base/ui_features.h"
 
 using testing::Eq;
 using testing::Field;
@@ -63,9 +65,24 @@
 
 namespace metrics_util = password_manager::metrics_util;
 
-using ManagePasswordsBubbleViewTest = ManagePasswordsTest;
+class ManagePasswordsBubbleViewTest : public ManagePasswordsTest {
+ public:
+  ManagePasswordsBubbleViewTest() {}
+  ~ManagePasswordsBubbleViewTest() override {}
+
+  // content::BrowserTestBase:
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+#if defined(OS_MACOSX)
+    command_line->AppendSwitch(switches::kExtendMdToSecondaryUi);
+#endif
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ManagePasswordsBubbleViewTest);
+};
 
 IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, BasicOpenAndClose) {
+  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
   EXPECT_FALSE(IsBubbleShowing());
   SetupPendingPassword();
   EXPECT_TRUE(IsBubbleShowing());
@@ -75,11 +92,15 @@
   EXPECT_FALSE(bubble->GetFocusManager()->GetFocusedView());
   ManagePasswordsBubbleView::CloseCurrentBubble();
   EXPECT_FALSE(IsBubbleShowing());
+  // Drain message pump to ensure the bubble view is cleared so that it can be
+  // created again (it is checked on Mac to prevent re-opening the bubble when
+  // clicking the location bar button repeatedly).
+  content::RunAllPendingInMessageLoop();
 
   // And, just for grins, ensure that we can re-open the bubble.
-  ManagePasswordsBubbleView::ShowBubble(
-      browser()->tab_strip_model()->GetActiveWebContents(),
-      ManagePasswordsBubbleView::USER_GESTURE);
+  TabDialogs::FromWebContents(
+      browser()->tab_strip_model()->GetActiveWebContents())
+      ->ShowManagePasswordsBubble(true /* user_action */);
   EXPECT_TRUE(IsBubbleShowing());
   bubble = ManagePasswordsBubbleView::manage_password_bubble();
   EXPECT_TRUE(bubble->initially_focused_view());
@@ -92,6 +113,7 @@
 // Same as 'BasicOpenAndClose', but use the command rather than the static
 // method directly.
 IN_PROC_BROWSER_TEST_F(ManagePasswordsBubbleViewTest, CommandControlsBubble) {
+  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
   // The command only works if the icon is visible, so get into management mode.
   SetupManagingPasswords();
   EXPECT_FALSE(IsBubbleShowing());
@@ -104,6 +126,10 @@
             bubble->GetFocusManager()->GetFocusedView());
   ManagePasswordsBubbleView::CloseCurrentBubble();
   EXPECT_FALSE(IsBubbleShowing());
+  // Drain message pump to ensure the bubble view is cleared so that it can be
+  // created again (it is checked on Mac to prevent re-opening the bubble when
+  // clicking the location bar button repeatedly).
+  content::RunAllPendingInMessageLoop();
 
   // And, just for grins, ensure that we can re-open the bubble.
   ExecuteManagePasswordsCommand();
@@ -166,6 +192,11 @@
   SetupPendingPassword();
   EXPECT_TRUE(IsBubbleShowing());
   ManagePasswordsBubbleView::CloseCurrentBubble();
+  // Drain message pump to ensure the bubble view is cleared so that it can be
+  // created again (it is checked on Mac to prevent re-opening the bubble when
+  // clicking the location bar button repeatedly).
+  content::RunAllPendingInMessageLoop();
+
   // This opening should be measured as manual.
   ExecuteManagePasswordsCommand();
   EXPECT_TRUE(IsBubbleShowing());
@@ -317,24 +348,24 @@
   // Open another window with focus.
   Browser* focused_window = CreateBrowser(browser()->profile());
   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(focused_window));
-  content::RunAllPendingInMessageLoop();
 
-  gfx::NativeWindow window = browser()->window()->GetNativeWindow();
-  views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
-  ASSERT_NE(nullptr, widget);
-
-  views::test::WidgetActivationWaiter inactive_waiter(widget, false);
-  inactive_waiter.Wait();
   ManagePasswordsBubbleView::set_auto_signin_toast_timeout(0);
   SetupAutoSignin(std::move(local_credentials));
-  content::RunAllPendingInMessageLoop();
   EXPECT_TRUE(IsBubbleShowing());
 
   // Bring the first window back. The toast closes by timeout.
   focused_window->window()->Close();
   browser()->window()->Activate();
   content::RunAllPendingInMessageLoop();
-  views::test::WidgetActivationWaiter active_waiter(widget, true);
-  active_waiter.Wait();
+  ui_test_utils::BrowserActivationWaiter waiter(browser());
+  waiter.WaitForActivation();
+
+// Sign-in dialogs opened for inactive browser windows do not auto-close on
+// MacOS. This matches existing Cocoa bubble behavior.
+// TODO(varkha): Remove the limitation as part of http://crbug/671916 .
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
   EXPECT_FALSE(IsBubbleShowing());
+#else
+  EXPECT_TRUE(IsBubbleShowing());
+#endif
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 15cae0d..440b7ec 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -527,6 +527,7 @@
         "../browser/ui/views/menu_test_base.cc",
         "../browser/ui/views/menu_test_base.h",
         "../browser/ui/views/menu_view_drag_and_drop_test.cc",
+        "../browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc",
         "../browser/ui/views/status_icons/status_tray_state_changer_interactive_uitest_win.cc",
         "//ui/views/corewm/desktop_capture_controller_unittest.cc",
         "//ui/views/widget/desktop_aura/desktop_window_tree_host_x11_interactive_uitest.cc",
@@ -558,7 +559,6 @@
           "../browser/ui/views/location_bar/star_view_browsertest.cc",
           "../browser/ui/views/omnibox/omnibox_view_views_browsertest.cc",
           "../browser/ui/views/page_info/page_info_bubble_view_interactive_uitest.cc",
-          "../browser/ui/views/passwords/manage_passwords_bubble_view_interactive_uitest.cc",
           "../browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc",
           "../browser/ui/views/ssl_client_certificate_selector_browsertest.cc",
           "../browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc",
@@ -2144,6 +2144,7 @@
         "../browser/ui/views/frame/browser_non_client_frame_view_browsertest_win.cc",
         "../browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc",
         "../browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc",
+        "../browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc",
         "../browser/ui/views/payments/credit_card_editor_view_controller_browsertest.cc",
         "../browser/ui/views/payments/cvc_unmask_view_controller_browsertest.cc",
         "../browser/ui/views/payments/error_message_view_controller_browsertest.cc",
@@ -2187,7 +2188,6 @@
           "../browser/ui/views/frame/browser_view_browsertest.cc",
           "../browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc",
           "../browser/ui/views/media_router/media_router_ui_browsertest.cc",
-          "../browser/ui/views/passwords/manage_passwords_bubble_view_browsertest.cc",
           "../browser/ui/views/passwords/password_dialog_view_browsertest.cc",
           "../browser/ui/views/session_crashed_bubble_view_browsertest.cc",
           "../browser/ui/views/task_manager_view_browsertest.cc",
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h
index d7bb9d15..b3c7c00 100644
--- a/chrome/test/base/in_process_browser_test.h
+++ b/chrome/test/base/in_process_browser_test.h
@@ -18,6 +18,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/page_transition_types.h"
 
+#if defined(OS_MACOSX)
+#include "ui/base/test/scoped_fake_full_keyboard_access.h"
+#endif
+
 namespace base {
 
 class CommandLine;
@@ -264,6 +268,12 @@
 #if defined(OS_MACOSX)
   base::mac::ScopedNSAutoreleasePool* autorelease_pool_;
   std::unique_ptr<ScopedBundleSwizzlerMac> bundle_swizzler_;
+
+  // Enable fake full keyboard access by default, so that tests don't depend on
+  // system setting of the test machine. Also, this helps to make tests on Mac
+  // more consistent with other platforms, where most views are focusable by
+  // default.
+  ui::test::ScopedFakeFullKeyboardAccess faked_full_keyboard_access_;
 #endif  // OS_MACOSX
 
 #if defined(OS_WIN)
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
index c2deb62..05613c4 100644
--- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
+++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
@@ -9,6 +9,7 @@
 
 #include "base/files/file_path.h"
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/process/kill.h"
 #include "base/strings/string_util.h"
@@ -233,3 +234,155 @@
     int network_connection) {
   network_connection_ = network_connection;
 }
+
+Status ChromeDesktopImpl::GetWindowPosition(const std::string& target_id,
+                                            int* x,
+                                            int* y) {
+  Window window;
+  Status status = GetWindow(target_id, &window);
+  if (status.IsError())
+    return status;
+
+  *x = window.left;
+  *y = window.top;
+  return Status(kOk);
+}
+
+Status ChromeDesktopImpl::GetWindowSize(const std::string& target_id,
+                                        int* width,
+                                        int* height) {
+  Window window;
+  Status status = GetWindow(target_id, &window);
+  if (status.IsError())
+    return status;
+
+  *width = window.width;
+  *height = window.height;
+  return Status(kOk);
+}
+
+Status ChromeDesktopImpl::SetWindowPosition(const std::string& target_id,
+                                            int x,
+                                            int y) {
+  auto bounds = base::MakeUnique<base::DictionaryValue>();
+  bounds->SetInteger("left", x);
+  bounds->SetInteger("top", y);
+  return SetWindowBounds(target_id, std::move(bounds));
+}
+
+Status ChromeDesktopImpl::SetWindowSize(const std::string& target_id,
+                                        int width,
+                                        int height) {
+  auto bounds = base::MakeUnique<base::DictionaryValue>();
+  bounds->SetInteger("width", width);
+  bounds->SetInteger("height", height);
+  return SetWindowBounds(target_id, std::move(bounds));
+}
+
+Status ChromeDesktopImpl::MaximizeWindow(const std::string& target_id) {
+  Window window;
+  Status status = GetWindow(target_id, &window);
+  if (status.IsError())
+    return status;
+
+  if (window.state == "maximized")
+    return Status(kOk);
+
+  if (window.state != "normal") {
+    // always restore window to normal first, since chrome ui doesn't allow
+    // maximizing a minimized or fullscreen window.
+    status = SetWindowState(window.id, "normal");
+    if (status.IsError())
+      return status;
+  }
+
+  return SetWindowState(window.id, "maximized");
+}
+
+Status ChromeDesktopImpl::ParseWindow(
+    std::unique_ptr<base::DictionaryValue> params,
+    Window* window) {
+  if (!params->GetInteger("windowId", &window->id))
+    return Status(kUnknownError, "no window id in response");
+
+  const base::Value* value = nullptr;
+  const base::DictionaryValue* bounds_dict = nullptr;
+  if (!params->Get("bounds", &value) || !value->GetAsDictionary(&bounds_dict))
+    return Status(kUnknownError, "no window bounds in response");
+
+  if (!bounds_dict->GetString("windowState", &window->state))
+    return Status(kUnknownError, "no window state in window bounds");
+
+  if (!bounds_dict->GetInteger("left", &window->left))
+    return Status(kUnknownError, "no left offset in window bounds");
+  if (!bounds_dict->GetInteger("top", &window->top))
+    return Status(kUnknownError, "no top offset in window bounds");
+  if (!bounds_dict->GetInteger("width", &window->width))
+    return Status(kUnknownError, "no width in window bounds");
+  if (!bounds_dict->GetInteger("height", &window->height))
+    return Status(kUnknownError, "no height in window bounds");
+
+  return Status(kOk);
+}
+
+Status ChromeDesktopImpl::GetWindow(const std::string& target_id,
+                                    Window* window) {
+  Status status = devtools_websocket_client_->ConnectIfNecessary();
+  if (status.IsError())
+    return status;
+
+  base::DictionaryValue params;
+  params.SetString("targetId", target_id);
+  std::unique_ptr<base::DictionaryValue> result;
+  status = devtools_websocket_client_->SendCommandAndGetResult(
+      "Browser.getWindowForTarget", params, &result);
+  if (status.IsError())
+    return status;
+
+  return ParseWindow(std::move(result), window);
+}
+
+Status ChromeDesktopImpl::SetWindowState(int window_id,
+                                         const std::string& window_state) {
+  Status status = devtools_websocket_client_->ConnectIfNecessary();
+  if (status.IsError())
+    return status;
+
+  base::DictionaryValue params;
+  params.SetInteger("windowId", window_id);
+  auto bounds_object = base::MakeUnique<base::DictionaryValue>();
+  bounds_object->SetString("windowState", window_state);
+  params.Set("bounds", std::move(bounds_object));
+  status = devtools_websocket_client_->SendCommand("Browser.setWindowBounds",
+                                                   params);
+  if (status.IsError())
+    return status;
+
+  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
+  return Status(kOk);
+}
+
+Status ChromeDesktopImpl::SetWindowBounds(
+    const std::string& target_id,
+    std::unique_ptr<base::DictionaryValue> bounds) {
+  Window window;
+  Status status = GetWindow(target_id, &window);
+  if (status.IsError())
+    return status;
+
+  if (window.state != "normal") {
+    status = SetWindowState(window.id, "normal");
+    if (status.IsError())
+      return status;
+  }
+
+  base::DictionaryValue params;
+  params.SetInteger("windowId", window.id);
+  params.Set("bounds", std::move(bounds));
+  status = devtools_websocket_client_->SendCommand("Browser.setWindowBounds",
+                                                   params);
+  if (status.IsError())
+    return status;
+
+  return Status(kOk);
+}
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h
index a5a8ccc..c1f9974 100644
--- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h
+++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h
@@ -13,6 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/process/process.h"
+#include "base/values.h"
 #include "chrome/test/chromedriver/chrome/chrome_impl.h"
 
 namespace base {
@@ -66,7 +67,29 @@
   int GetNetworkConnection() const;
   void SetNetworkConnection(int network_connection);
 
+  Status GetWindowPosition(const std::string& target_id, int* x, int* y);
+  Status GetWindowSize(const std::string& target_id, int* width, int* height);
+  Status SetWindowPosition(const std::string& target_id, int x, int y);
+  Status SetWindowSize(const std::string& target_id, int width, int height);
+  Status MaximizeWindow(const std::string& target_id);
+
  private:
+  struct Window {
+    int id;
+    std::string state;
+    int left;
+    int top;
+    int width;
+    int height;
+  };
+  Status ParseWindow(std::unique_ptr<base::DictionaryValue> params,
+                     Window* window);
+
+  Status GetWindow(const std::string& target_id, Window* window);
+  Status SetWindowState(int window_id, const std::string& window_state);
+  Status SetWindowBounds(const std::string& target_id,
+                         std::unique_ptr<base::DictionaryValue> bounds);
+
   base::Process process_;
   base::CommandLine command_;
   base::ScopedTempDir user_data_dir_;
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc
index c6777a3..e6bd0bb 100644
--- a/chrome/test/chromedriver/session_commands.cc
+++ b/chrome/test/chromedriver/session_commands.cc
@@ -40,6 +40,10 @@
 
 namespace {
 
+// The minimium chrome build no that supports window management devtools
+// commands.
+const int kBrowserWindowDevtoolsBuildNo = 3076;
+
 const int kWifiMask = 0x2;
 const int k4GMask = 0x8;
 const int k3GMask = 0x10;
@@ -656,13 +660,19 @@
   if (status.IsError())
     return status;
 
-  AutomationExtension* extension = NULL;
-  status = desktop->GetAutomationExtension(&extension, session->w3c_compliant);
-  if (status.IsError())
-    return status;
-
   int x, y;
-  status = extension->GetWindowPosition(&x, &y);
+
+  if (desktop->GetBrowserInfo()->build_no >= kBrowserWindowDevtoolsBuildNo) {
+    status = desktop->GetWindowPosition(session->window, &x, &y);
+  } else {
+    AutomationExtension* extension = NULL;
+    status =
+        desktop->GetAutomationExtension(&extension, session->w3c_compliant);
+    if (status.IsError())
+      return status;
+
+    status = extension->GetWindowPosition(&x, &y);
+  }
   if (status.IsError())
     return status;
 
@@ -686,6 +696,11 @@
   if (status.IsError())
     return status;
 
+  if (desktop->GetBrowserInfo()->build_no >= kBrowserWindowDevtoolsBuildNo) {
+    return desktop->SetWindowPosition(session->window, static_cast<int>(x),
+                                      static_cast<int>(y));
+  }
+
   AutomationExtension* extension = NULL;
   status = desktop->GetAutomationExtension(&extension, session->w3c_compliant);
   if (status.IsError())
@@ -702,13 +717,19 @@
   if (status.IsError())
     return status;
 
-  AutomationExtension* extension = NULL;
-  status = desktop->GetAutomationExtension(&extension, session->w3c_compliant);
-  if (status.IsError())
-    return status;
-
   int width, height;
-  status = extension->GetWindowSize(&width, &height);
+
+  if (desktop->GetBrowserInfo()->build_no >= kBrowserWindowDevtoolsBuildNo) {
+    status = desktop->GetWindowSize(session->window, &width, &height);
+  } else {
+    AutomationExtension* extension = NULL;
+    status =
+        desktop->GetAutomationExtension(&extension, session->w3c_compliant);
+    if (status.IsError())
+      return status;
+
+    status = extension->GetWindowSize(&width, &height);
+  }
   if (status.IsError())
     return status;
 
@@ -733,6 +754,11 @@
   if (status.IsError())
     return status;
 
+  if (desktop->GetBrowserInfo()->build_no >= kBrowserWindowDevtoolsBuildNo) {
+    return desktop->SetWindowSize(session->window, static_cast<int>(width),
+                                  static_cast<int>(height));
+  }
+
   AutomationExtension* extension = NULL;
   status = desktop->GetAutomationExtension(&extension, session->w3c_compliant);
   if (status.IsError())
@@ -750,6 +776,9 @@
   if (status.IsError())
     return status;
 
+  if (desktop->GetBrowserInfo()->build_no >= kBrowserWindowDevtoolsBuildNo)
+    return desktop->MaximizeWindow(session->window);
+
   AutomationExtension* extension = NULL;
   status = desktop->GetAutomationExtension(&extension, session->w3c_compliant);
   if (status.IsError())
diff --git a/chrome/test/data/password/between_parsing_and_rendering.html b/chrome/test/data/password/between_parsing_and_rendering.html
index f7bb3e3..0941b11 100644
--- a/chrome/test/data/password/between_parsing_and_rendering.html
+++ b/chrome/test/data/password/between_parsing_and_rendering.html
@@ -9,9 +9,10 @@
    the form is not registered during form parsing stage
    (as in PasswordManager::OnPasswordFormsParsed).
 2. The form gets created before the rendering stage, so it gets
-   registered during PasswordManager::OnPasswordFormsRendered.
-3. The form gets created before the main frame loads. Therefore
-   the form is not registered during OnDynamicFormsSeen.
+   registered during PasswordManager::OnPasswordFormsRendered unless
+   it is hidden.
+3. The form gets created after the document loads. Therefore
+   the form is registered during OnDynamicFormsSeen.
 
 The goal is to make sure that there is enough time between the form
 creation and the frame load, so that OnDynamicFormsSeen is not
@@ -26,7 +27,10 @@
     <script src="form_utils.js"></script>
     <script>
 function onLoadHandler() {
-  document.body.appendChild(createSimplePasswordForm());
+  var form = createSimplePasswordForm();
+  if (location.search == '?hidden')
+    form.style.display = 'none';
+  document.body.appendChild(form);
 }
     </script>
     <style>
diff --git a/chrome/test/data/password/create_form_copy_on_submit.html b/chrome/test/data/password/create_form_copy_on_submit.html
index f3b2837..390647c 100644
--- a/chrome/test/data/password/create_form_copy_on_submit.html
+++ b/chrome/test/data/password/create_form_copy_on_submit.html
@@ -3,17 +3,6 @@
 On password form submit, the page's JavaScript deletes that form, creates
 another one, almost an exact copy of the deleted form, just with a different
 action, and submits the new one.
-
-The issue demonstrated here is that there is very little time between
-creating and submitting the second form. As observed in
-http://crbug.com/367768, PasswordManager is not able to process the form
-quickly enough in such cases: the PasswordFormManager associated with the
-created form has not enough time to asynchronously get matching results from
-the password store, and is hence not ready to provisionally save the new
-credential. This test checks that PasswordManager still makes use of the
-PasswordFormManager associated with the first form (which is a reasonable
-match for the credential, though worse than the newer PasswordFormManager)
-and works in this scenario.
 -->
 <html>
   <head>
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 8acb91f..8b97003 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -42,7 +42,7 @@
     "//net:net_unittests",
     "//sandbox/linux:sandbox_linux_unittests",
     "//sql:sql_unittests",
-    "//storage/browser:storage_unittests",
+    "//storage:storage_unittests",
     "//third_party/cacheinvalidation:cacheinvalidation_unittests",
     "//ui/base:ui_base_unittests",
   ]
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index 43da709..46bd261 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -21,6 +21,8 @@
 
 // Request from device to server to register a device, user or browser.
 message DeviceRegisterRequest {
+  reserved 5;
+
   // Reregister device without erasing server state.  It can be used
   // to refresh dmtoken etc.  Client MUST set this value to true if it
   // reuses an existing device id.
@@ -52,9 +54,6 @@
   // "Android", or "Chrome OS".
   optional string machine_model = 4;
 
-  // OBSOLETE: Legacy auto-enrollment is not longer supported.
-  optional bool OBSOLETE_auto_enrolled = 5 [deprecated = true];
-
   // Indicates a requisition of the registering entity that the server can act
   // upon. This allows clients to pass hints e.g. at device enrollment time
   // about the intended use of the device.
@@ -550,60 +549,6 @@
   optional int32 active_duration = 2;
 }
 
-// This captures launch events for one app/extension or other installments.
-message InstallableLaunch {
-  optional string install_id = 1;
-
-  // Time duration where this report covers. These are required
-  // and the record will be ignored if not set.
-  optional TimePeriod duration = 2;
-
-  // Client will send at most 50 timestamps to DM. All the rest
-  // launch activities will be summed into the total count.
-  // We will distribute the count evenly among the time span when
-  // doing time based aggregation.
-  repeated int64 timestamp = 3;
-  optional int64 total_count = 4;
-}
-
-// OBSOLETE: Used to report the device location.
-message OBSOLETE_DeviceLocation {
-  enum ErrorCode {
-    ERROR_CODE_NONE                 = 0;
-    ERROR_CODE_POSITION_UNAVAILABLE = 1;
-  }
-
-  // Latitude in decimal degrees north (WGS84 coordinate frame).
-  optional double latitude = 1;
-
-  // Longitude in decimal degrees west (WGS84 coordinate frame).
-  optional double longitude = 2;
-
-  // Altitude in meters (above WGS84 datum).
-  optional double altitude = 3;
-
-  // Accuracy of horizontal position in meters.
-  optional double accuracy = 4;
-
-  // Accuracy of altitude in meters.
-  optional double altitude_accuracy = 5;
-
-  // Heading in decimal degrees clockwise from true north.
-  optional double heading = 6;
-
-  // Horizontal component of device velocity in meters per second.
-  optional double speed = 7;
-
-  // Time of position measurement in milisecons since Epoch in UTC time.
-  optional int64 timestamp = 8;
-
-  // Error code, see enum above.
-  optional ErrorCode error_code = 9;
-
-  // Human-readable error message.
-  optional string error_message = 10;
-}
-
 // Details about a network interface.
 message NetworkInterface {
   // Indicates the type of network device.
@@ -707,6 +652,8 @@
 
 // Report device level status.
 message DeviceStatusReportRequest {
+  reserved 4, 7, 13;
+
   // The OS version reported by the device is a platform version
   // e.g. 1435.0.2011_12_16_1635.
   optional string os_version = 1;
@@ -716,10 +663,6 @@
   // If the mode is unknown, this field should not be set.
   optional string boot_mode = 3;
 
-  // OBSOLETE: Device active times collection since last report rpc call.
-  // No longer used -- use active_period instead.
-  repeated TimePeriod OBSOLETE_active_time = 4 [deprecated = true];
-
   // The browser version string as shown in the About dialog.
   // e.g. 17.0.963.18.
   optional string browser_version = 5;
@@ -727,10 +670,6 @@
   // A list of periods when the device was active, aggregated by day.
   repeated ActiveTimePeriod active_period = 6;
 
-  // OBSOLETE: The device location.
-  optional OBSOLETE_DeviceLocation OBSOLETE_device_location = 7
-    [deprecated = true];
-
   // List of network interfaces.
   repeated NetworkInterface network_interface = 8;
 
@@ -746,9 +685,6 @@
   // Samples of CPU utilization (0-100), sampled once every 120 seconds.
   repeated int32 cpu_utilization_pct = 12;
 
-  // OBSOLETE: Free RAM (unreliable due to GC).
-  optional int64 OBSOLETE_system_ram_free = 13 [deprecated = true];
-
   // Total RAM on the device.
   optional int64 system_ram_total = 14;
 
@@ -820,16 +756,7 @@
 
 // Report current active session (a user on one device) level status.
 message SessionStatusReportRequest {
-  // OBSOLETE: Installed apps for this user on this device.
-  // No longer used -- use installed_apps instead.
-  repeated string OBSOLETE_installed_app_id = 1 [deprecated = true];
-
-  // OBSOLETE: Installed extensions for this user on this device.
-  // No longer used -- use installed_extensions instead.
-  repeated string OBSOLETE_installed_extension_id = 2 [deprecated = true];
-
-  // One stat per app for top 30 apps.
-  repeated InstallableLaunch app_launch_stat = 3;
+  reserved 1, 2, 3, 6;
 
   // If this is a kiosk session, this is the device local account ID.
   optional string device_local_account_id = 4;
@@ -837,9 +764,6 @@
   // Information about installed apps for this user on this device.
   repeated AppStatus installed_apps = 5;
 
-  // Information about installed extensions for this user on this device.
-  repeated AppStatus installed_extensions = 6;
-
   // Information about ARC status.
   optional AndroidStatus android_status = 7;
 
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 6a09498..cc7b3fc 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -314,7 +314,7 @@
 
           The New Tab page is the page opened when new tabs are created (including the one opened in new windows).
 
-          This policy does not decide which pages are to be opened on start up. Those are controlled by the <ph name="RESTOREONSTARTUP_POLICY_NAME">RestoreOnStartup</ph> policies. Yet this policy does affect the Home Page if that is set to open the New Tab page, as well as the startup page if that is set to open the New Tab page.
+          This policy does not decide which pages are to be opened on start up. Those are controlled by the <ph name="RESTORE_ON_STARTUP_POLICY_NAME">RestoreOnStartup</ph> policies. Yet this policy does affect the Home Page if that is set to open the New Tab page, as well as the startup page if that is set to open the New Tab page.
 
           If the policy is not set or left empty the default new tab page is used.
 
@@ -438,7 +438,7 @@
       'id': 7,
       'caption': '''Enable network prediction''',
       'tags': [],
-      'desc': '''This policy is deprecated in M48 in favor of <ph name="NETWORKPREDICTIONOPTIONS_POLICY_NAME">NetworkPredictionOptions</ph>, and removed in M54.
+      'desc': '''This policy is deprecated in M48 in favor of <ph name="NETWORK_PREDICTION_OPTIONS_POLICY_NAME">NetworkPredictionOptions</ph>, and removed in M54.
 
       Enables network prediction in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> and prevents users from changing this setting.
 
@@ -938,7 +938,7 @@
 
           If this setting is enabled, then remote clients can use relay servers to connect to this machine when a direct connection is not available (e.g. due to firewall restrictions).
 
-          Note that if the policy <ph name="REMOTEACCESSHOSTFIREWALLTRAVERSAL_POLICY_NAME">RemoteAccessHostFirewallTraversal</ph> is disabled, this policy will be ignored.
+          Note that if the policy <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME">RemoteAccessHostFirewallTraversal</ph> is disabled, this policy will be ignored.
 
           If this policy is left not set the setting will be enabled.''',
         },
@@ -957,7 +957,7 @@
           'tags': [],
           'desc': '''Restricts the UDP port range used by the remote access host in this machine.
 
-          If this policy is left not set, or if it is set to an empty string, the remote access host will be allowed to use any available port, unless the policy <ph name="REMOTEACCESSHOSTFIREWALLTRAVERSAL_POLICY_NAME">RemoteAccessHostFirewallTraversal</ph> is disabled, in which case the remote access host will use UDP ports in the 12400-12409 range.''',
+          If this policy is left not set, or if it is set to an empty string, the remote access host will be allowed to use any available port, unless the policy <ph name="REMOTE_ACCESS_HOST_FIREWALL_TRAVERSAL_POLICY_NAME">RemoteAccessHostFirewallTraversal</ph> is disabled, in which case the remote access host will use UDP ports in the 12400-12409 range.''',
         },
         {
           'name': 'RemoteAccessHostMatchUsername',
@@ -1117,7 +1117,7 @@
       'id': 162,
       'caption': '''Force SafeSearch''',
       'tags': ['filtering'],
-      'desc': '''This policy is deprecated, please use <ph name="FORCEGOOGLESAFESEARCH_POLICY_NAME">ForceGoogleSafeSearch</ph> and <ph name="FORCEYOUTUBERESTRICT_POLICY_NAME">ForceYouTubeRestrict</ph> instead. This policy is ignored if either the <ph name="FORCEGOOGLESAFESEARCH_POLICY_NAME">ForceGoogleSafeSearch</ph>, the <ph name="FORCEYOUTUBERESTRICT_POLICY_NAME">ForceYouTubeRestrict</ph> or the (deprecated) <ph name="FORCEYOUTUBESAFETYMODE_POLICY_NAME">ForceYouTubeSafetyMode</ph> policies are set.
+      'desc': '''This policy is deprecated, please use <ph name="FORCE_GOOGLE_SAFE_SEARCH_POLICY_NAME">ForceGoogleSafeSearch</ph> and <ph name="FORCE_YOUTUBE_RESTRICT_POLICY_NAME">ForceYouTubeRestrict</ph> instead. This policy is ignored if either the <ph name="FORCE_GOOGLE_SAFE_SEARCH_POLICY_NAME">ForceGoogleSafeSearch</ph>, the <ph name="FORCE_YOUTUBE_RESTRICT_POLICY_NAME">ForceYouTubeRestrict</ph> or the (deprecated) <ph name="FORCE_YOUTUBE_SAFETY_MODE_POLICY_NAME">ForceYouTubeSafetyMode</ph> policies are set.
 
       Forces queries in Google Web Search to be done with SafeSearch set to active and prevents users from changing this setting. This setting also forces Moderate Restricted Mode on YouTube.
 
@@ -1160,7 +1160,7 @@
       'id': 283,
       'caption': '''Force YouTube Safety Mode''',
       'tags': ['filtering'],
-      'desc': '''This policy is deprecated. Consider using <ph name="FORCEYOUTUBERESTRICT_POLICY_NAME">ForceYouTubeRestrict</ph>, which overrides this policy and allows more fine-grained tuning.
+      'desc': '''This policy is deprecated. Consider using <ph name="FORCE_YOUTUBE_RESTRICT_POLICY_NAME">ForceYouTubeRestrict</ph>, which overrides this policy and allows more fine-grained tuning.
 
       Forces YouTube Moderate Restricted Mode and prevents users from changing this setting.
 
@@ -1363,7 +1363,7 @@
       'id': 19,
       'caption': '''Specify a list of disabled plugins''',
       'tags': [],
-      'desc': '''This policy is deprecated. Please use the <ph name="DEFAULT_PLUGINS_SETTING_POLICY">DefaultPluginsSetting</ph> to control the avalability of the Flash plugin and <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY">AlwaysOpenPdfExternally</ph> to control whether the integrated PDF viewer should be used for opening PDF files.
+      'desc': '''This policy is deprecated. Please use the <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME">DefaultPluginsSetting</ph> to control the avalability of the Flash plugin and <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME">AlwaysOpenPdfExternally</ph> to control whether the integrated PDF viewer should be used for opening PDF files.
 
       Specifies a list of plugins that are disabled in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> and prevents users from changing this setting.
 
@@ -1393,7 +1393,7 @@
       'id': 78,
       'caption': '''Specify a list of enabled plugins''',
       'tags': ['system-security'],
-      'desc': '''This policy is deprecated. Please use the <ph name="DEFAULT_PLUGINS_SETTING_POLICY">DefaultPluginsSetting</ph> to control the avalability of the Flash plugin and <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY">AlwaysOpenPdfExternally</ph> to control whether the integrated PDF viewer should be used for opening PDF files.
+      'desc': '''This policy is deprecated. Please use the <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME">DefaultPluginsSetting</ph> to control the avalability of the Flash plugin and <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME">AlwaysOpenPdfExternally</ph> to control whether the integrated PDF viewer should be used for opening PDF files.
 
       Specifies a list of plugins that are enabled in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> and prevents users from changing this setting.
 
@@ -1423,7 +1423,7 @@
       'id': 79,
       'caption': '''Specify a list of plugins that the user can enable or disable''',
       'tags': [],
-      'desc': '''This policy is deprecated. Please use the <ph name="DEFAULT_PLUGINS_SETTING_POLICY">DefaultPluginsSetting</ph> to control the avalability of the Flash plugin and <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY">AlwaysOpenPdfExternally</ph> to control whether the integrated PDF viewer should be used for opening PDF files.
+      'desc': '''This policy is deprecated. Please use the <ph name="DEFAULT_PLUGINS_SETTING_POLICY_NAME">DefaultPluginsSetting</ph> to control the avalability of the Flash plugin and <ph name="ALWAYS_OPEN_PDF_EXTERNALLY_POLICY_NAME">AlwaysOpenPdfExternally</ph> to control whether the integrated PDF viewer should be used for opening PDF files.
 
       Specifies a list of plugins that user can enable or disable in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.
 
@@ -1508,11 +1508,11 @@
       'id': 358,
       'caption': '''Enable the creation of roaming copies for <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> profile data''',
       'tags': ['local-data-access'],
-      'desc': '''If you enable this setting, the settings stored in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> profiles like bookmarks, autofill data, passwords, etc. will also be written to a file stored in the Roaming user profile folder or a location specified by the Administrator through the <ph name="ROAMINGPROFILELOCATION_POLICY_NAME">$1<ex>RoamingProfileLocation</ex></ph> policy.
+      'desc': '''If you enable this setting, the settings stored in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> profiles like bookmarks, autofill data, passwords, etc. will also be written to a file stored in the Roaming user profile folder or a location specified by the Administrator through the <ph name="ROAMING_PROFILE_LOCATION_POLICY_NAME">$1<ex>RoamingProfileLocation</ex></ph> policy.
 
       Google Sync is automatically disabled when this policy is enabled.
 
-      To prevent accidental data leaks it is advisable to also set the <ph name="SIGNINALLOWED_POLICY_NAME">$1<ex>SigninAllowed</ex></ph> policy to False.
+      To prevent accidental data leaks it is advisable to also set the <ph name="SIGNIN_ALLOWED_POLICY_NAME">$1<ex>SigninAllowed</ex></ph> policy to False.
 
       If this policy is disabled or left not set only the regular local profiles will be used.''',
       'label': '''Enable the creation of roaming copies for <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> profile data.''',
@@ -1532,7 +1532,7 @@
       'tags': ['local-data-access'],
       'desc': '''Configures the directory that <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will use for storing the roaming copy of the profiles.
 
-      If you set this policy, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will use the provided directory to store the roaming copy of the profiles if the <ph name="ROAMINGPROFILESUPPORTENABLED_POLICY_NAME">$1<ex>RoamingProfileSupportEnabled</ex></ph> policy has been enabled. If the <ph name="ROAMINGPROFILESUPPORTENABLED_POLICY_NAME">$1<ex>RoamingProfileSupportEnabled</ex></ph> policy is disabled or left unset the value stored in this policy is not used.
+      If you set this policy, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will use the provided directory to store the roaming copy of the profiles if the <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME">$1<ex>RoamingProfileSupportEnabled</ex></ph> policy has been enabled. If the <ph name="ROAMING_PROFILE_SUPPORT_ENABLED_POLICY_NAME">$1<ex>RoamingProfileSupportEnabled</ex></ph> policy is disabled or left unset the value stored in this policy is not used.
 
       See https://www.chromium.org/administrators/policy-list-3/user-data-directory-variables for a list of variables that can be used.
 
@@ -1893,7 +1893,7 @@
           If you enable this setting, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> ignores all proxy-related options specified from the command line.
 
           Leaving this policy not set will allow the users to choose the proxy settings on their own.''',
-          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY">ProxyMode</ph> policy for more details.',
+          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY_NAME">ProxyMode</ph> policy for more details.',
         },
         {
           'name': 'ProxyServer',
@@ -1921,7 +1921,7 @@
 
           For more options and detailed examples, visit:
           <ph name="PROXY_HELP_URL">https://www.chromium.org/developers/design-documents/network-settings#TOC-Command-line-options-for-proxy-sett<ex>https://www.chromium.org/developers/design-documents/network-settings#TOC-Command-line-options-for-proxy-sett</ex></ph>.''',
-          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY">ProxyMode</ph> policy for more details.',
+          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY_NAME">ProxyMode</ph> policy for more details.',
         },
         {
           'name': 'ProxyPacUrl',
@@ -1949,7 +1949,7 @@
 
           For detailed examples, visit:
           <ph name="PROXY_HELP_URL">https://www.chromium.org/developers/design-documents/network-settings#TOC-Command-line-options-for-proxy-sett<ex>https://www.chromium.org/developers/design-documents/network-settings#TOC-Command-line-options-for-proxy-sett</ex></ph>.''',
-          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY">ProxyMode</ph> policy for more details.',
+          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY_NAME">ProxyMode</ph> policy for more details.',
         },
         {
           'name': 'ProxyBypassList',
@@ -1978,7 +1978,7 @@
           For more detailed examples, visit:
           <ph name="PROXY_HELP_URL">https://www.chromium.org/developers/design-documents/network-settings#TOC-Command-line-options-for-proxy-sett<ex>https://www.chromium.org/developers/design-documents/network-settings#TOC-Command-line-options-for-proxy-sett</ex></ph>.''',
           'label': '''Comma-separated list of proxy bypass rules''',
-          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY">ProxyMode</ph> policy for more details.',
+          'arc_support': 'You cannot force Android apps to use a proxy. A subset of proxy settings is made available to Android apps, which they may voluntarily choose to honor. See the <ph name="PROXY_MODE_POLICY_NAME">ProxyMode</ph> policy for more details.',
         },
       ],
     },
@@ -2173,7 +2173,7 @@
       'name': 'Extensions',
       'type': 'group',
       'caption': '''Extensions''',
-      'desc': '''Configures extension-related policies. The user is not allowed to install blacklisted extensions unless they are whitelisted. You can also force <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> to automatically install extensions by specifying them in <ph name="EXTENSIONINSTALLFORCELIST_POLICY_NAME">ExtensionInstallForcelist</ph>. Force-installed extensions are installed regardless whether they are present in the blacklist.''',
+      'desc': '''Configures extension-related policies. The user is not allowed to install blacklisted extensions unless they are whitelisted. You can also force <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> to automatically install extensions by specifying them in <ph name="EXTENSION_INSTALL_FORCELIST_POLICY_NAME">ExtensionInstallForcelist</ph>. Force-installed extensions are installed regardless whether they are present in the blacklist.''',
       'policies': [
         {
           'name': 'ExtensionInstallBlacklist',
@@ -2253,7 +2253,7 @@
           domain, forced installation is limited to apps and extensions listed
           in the Chrome Web Store.
 
-          Note that the source code of any extension may be altered by users via Developer Tools (potentially rendering the extension dysfunctional). If this is a concern, the <ph name="DEVELOPER_TOOLS_POLICY">DeveloperToolsDisabled</ph> policy should be set.
+          Note that the source code of any extension may be altered by users via Developer Tools (potentially rendering the extension dysfunctional). If this is a concern, the <ph name="DEVELOPER_TOOLS_POLICY_NAME">DeveloperToolsDisabled</ph> policy should be set.
 
           Each list item of the policy is a string that contains an extension ID and an "update" URL separated by a semicolon (<ph name="SEMICOLON">;</ph>). The extension ID is the 32-letter string found e.g. on <ph name="CHROME_EXTENSIONS_LINK">chrome://extensions</ph> when in developer mode. The "update" URL should point to an Update Manifest XML document as described at <ph name="LINK_TO_EXTENSION_DOC1">https://developer.chrome.com/extensions/autoupdate</ph>. Note that the "update" URL set in this policy is only used for the initial installation; subsequent updates of the extension employ the update URL indicated in the extension's manifest.
 
@@ -4012,7 +4012,7 @@
           'tags': [],
           'desc': '''If this policy is set, the specified content types are handled by <ph name="PRODUCT_FRAME_NAME">$3<ex>Google Chrome Frame</ex></ph>.
 
-          If this policy is not set, the default renderer is used for all sites. (The <ph name="CHROMEFRAMERENDERERSETTINGS_POLICY_NAME">ChromeFrameRendererSettings</ph> policy may be used to configure the default renderer.)''',
+          If this policy is not set, the default renderer is used for all sites. (The <ph name="CHROME_FRAME_RENDERER_SETTINGS_POLICY_NAME">ChromeFrameRendererSettings</ph> policy may be used to configure the default renderer.)''',
         },
       ],
     },
@@ -5171,8 +5171,8 @@
       'tags': [],
       'desc': '''Defines the list of users that are allowed to login to the device. Entries are of the form <ph name="USER_WHITELIST_ENTRY_FORMAT">user@domain</ph>, such as <ph name="USER_WHITELIST_ENTRY_EXAMPLE">madmax@managedchrome.com</ph>. To allow arbitrary users on a domain, use entries of the form <ph name="USER_WHITELIST_ENTRY_WILDCARD">*@domain</ph>.
 
-      If this policy is not configured, there are no restrictions on which users are allowed to sign in. Note that creating new users still requires the <ph name="DEVICEALLOWNEWUSERS_POLICY_NAME">DeviceAllowNewUsers</ph> policy to be configured appropriately.''',
-      'arc_support': 'This policy controls who may start a <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph> session. It does not prevent users from signing in to additional Google accounts within Android. If you want to prevent this, configure the Android-specific <ph name="CLOUDDPC_ACCOUNT_MANAGEMENT_POLICY">accountTypesWithManagementDisabled</ph> policy as part of <ph name="ARC_POLICY">ArcPolicy</ph>.',
+      If this policy is not configured, there are no restrictions on which users are allowed to sign in. Note that creating new users still requires the <ph name="DEVICE_ALLOW_NEW_USERS_POLICY_NAME">DeviceAllowNewUsers</ph> policy to be configured appropriately.''',
+      'arc_support': 'This policy controls who may start a <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph> session. It does not prevent users from signing in to additional Google accounts within Android. If you want to prevent this, configure the Android-specific <ph name="ACCOUNT_TYPES_WITH_MANAGEMENT_DISABLED_CLOUDDPC_POLICY_NAME">accountTypesWithManagementDisabled</ph> policy as part of <ph name="ARC_POLICY_POLICY_NAME">ArcPolicy</ph>.',
     },
     {
       'name': 'DeviceAllowNewUsers',
@@ -5189,8 +5189,8 @@
       'tags': [],
       'desc': '''Controls whether <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> allows new user accounts to be created. If this policy is set to false, users that do not have an account already will not be able to login.
 
-      If this policy is set to true or not configured, new user accounts will be allowed to be created provided that <ph name="DEVICEUSERWHITELISTPROTO_POLICY_NAME">DeviceUserWhitelist</ph> does not prevent the user from logging in.''',
-      'arc_support': 'This policy controls whether new users can be added to <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph>. It does not prevent users from signing in to additional Google accounts within Android. If you want to prevent this, configure the Android-specific <ph name="CLOUDDPC_ACCOUNT_MANAGEMENT_POLICY">accountTypesWithManagementDisabled</ph> policy as part of <ph name="ARC_POLICY">ArcPolicy</ph>.',
+      If this policy is set to true or not configured, new user accounts will be allowed to be created provided that <ph name="DEVICE_USER_WHITELIST_POLICY_NAME">DeviceUserWhitelist</ph> does not prevent the user from logging in.''',
+      'arc_support': 'This policy controls whether new users can be added to <ph name="PRODUCT_OS_NAME">$2<ex>Chromium OS</ex></ph>. It does not prevent users from signing in to additional Google accounts within Android. If you want to prevent this, configure the Android-specific <ph name="ACCOUNT_TYPES_WITH_MANAGEMENT_DISABLED_CLOUDDPC_POLICY_NAME">accountTypesWithManagementDisabled</ph> policy as part of <ph name="ARC_POLICY_POLICY_NAME">ArcPolicy</ph>.',
     },
     {
       'name': 'DeviceGuestModeEnabled',
@@ -5224,7 +5224,7 @@
       'tags': [],
       'desc': '''If this policy is set to true or not configured, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will show existing users on the login screen and allow to pick one.
 
-      If this policy is set to false, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will not show existing users on the login screen. The normal sign-in screen (prompting for the user email and password or phone) or the SAML interstital screen (if enabled via the <ph name="LOGINAUTHENTICATIONBEHAVIOR_POLICY_NAME">LoginAuthenticationBehavior</ph> policy) will be shown, unless a Public Session is configured. When a Public Session is configured, only the Public Session accounts will be shown, allowing to pick one of them.
+      If this policy is set to false, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will not show existing users on the login screen. The normal sign-in screen (prompting for the user email and password or phone) or the SAML interstital screen (if enabled via the <ph name="LOGIN_AUTHENTICATION_BEHAVIOR_POLICY_NAME">LoginAuthenticationBehavior</ph> policy) will be shown, unless a Public Session is configured. When a Public Session is configured, only the Public Session accounts will be shown, allowing to pick one of them.
 
       Note that this policy does not affect whether the device keeps or discards the local user data.''',
     },
@@ -5672,7 +5672,7 @@
       If this policy is set to True, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will prevent the device from booting into developer mode. The system will refuse to boot and show an error screen when the developer switch is turned on.
 
       If this policy is unset or set to False, developer mode will remain available for the device.''',
-      'arc_support': 'This policy controls <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> developer mode only. If you want to prevent access to Android Developer Options, you need to set the <ph name="DEVELOPER_TOOLS_POLICY">DeveloperToolsDisabled</ph> policy.',
+      'arc_support': 'This policy controls <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> developer mode only. If you want to prevent access to Android Developer Options, you need to set the <ph name="DEVELOPER_TOOLS_DISABLED_POLICY_NAME">DeveloperToolsDisabled</ph> policy.',
     },
     {
       'name': 'BackgroundModeEnabled',
@@ -6526,7 +6526,7 @@
           'tags': [],
           'desc': '''Note that this policy is deprecated and will be removed in the future.
 
-          This policy provides a fallback value for the more-specific <ph name="IDLEACTIONAC_POLICY_NAME">IdleActionAC</ph> and <ph name="IDLEACTIONBATTERY_POLICY_NAME">IdleActionBattery</ph> policies. If this policy is set, its value gets used if the respective more-specific policy is not set.
+          This policy provides a fallback value for the more-specific <ph name="IDLE_ACTION_AC_POLICY_NAME">IdleActionAC</ph> and <ph name="IDLE_ACTION_BATTERY_POLICY_NAME">IdleActionBattery</ph> policies. If this policy is set, its value gets used if the respective more-specific policy is not set.
 
           When this policy is unset, behavior of the more-specific policies remains unaffected.''',
         },
@@ -9129,7 +9129,7 @@
 
       If this setting is not configured then users are able to turn Google Location Service on and off in the Android Settings app.
 
-      Note that this policy value may be overriden by the <ph name="DEFAULTGEOLOCATIONSETTING_POLICY_NAME">DefaultGeolocationSetting</ph> policy, when the latter is set to <ph name="BLOCK_GEOLOCATION_SETTING">BlockGeolocation</ph>.
+      Note that this policy value may be overriden by the <ph name="DEFAULT_GEOLOCATION_SETTING_POLICY_NAME">DefaultGeolocationSetting</ph> policy, when the latter is set to <ph name="BLOCK_GEOLOCATION_SETTING">BlockGeolocation</ph>.
 
       This policy is applicable only to the users that are able to run Android apps.''',
     },
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index f590676..f49f928 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -424,6 +424,7 @@
     "javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java",
     "javatests/src/org/chromium/content/browser/JavaBridgeTestBase.java",
     "javatests/src/org/chromium/content/browser/JavaBridgeTestCommon.java",
+    "javatests/src/org/chromium/content/browser/LocationProviderTest.java",
     "javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java",
     "javatests/src/org/chromium/content/browser/MediaSessionTest.java",
     "javatests/src/org/chromium/content/browser/NavigationTest.java",
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/LocationProviderTest.java b/content/public/android/javatests/src/org/chromium/content/browser/LocationProviderTest.java
new file mode 100644
index 0000000..c74b604
--- /dev/null
+++ b/content/public/android/javatests/src/org/chromium/content/browser/LocationProviderTest.java
@@ -0,0 +1,72 @@
+// Copyright 2012 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.
+
+package org.chromium.content.browser;
+
+import android.app.Activity;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.UiThreadTestRule;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.annotations.SuppressFBWarnings;
+import org.chromium.base.test.util.Feature;
+import org.chromium.content.browser.test.ContentJUnit4ClassRunner;
+import org.chromium.device.geolocation.LocationProviderAdapter;
+
+/**
+ * Test suite for LocationProvider.
+ */
+@RunWith(ContentJUnit4ClassRunner.class)
+public class LocationProviderTest {
+    private Activity mActivity;
+    private LocationProviderAdapter mLocationProvider;
+
+    @Rule
+    public UiThreadTestRule mRule = new UiThreadTestRule();
+
+    @Before
+    @SuppressFBWarnings("URF_UNREAD_FIELD")
+    public void setUp() {
+        mActivity = new Activity();
+        mLocationProvider = LocationProviderAdapter.create(
+                InstrumentationRegistry.getInstrumentation().getTargetContext());
+    }
+
+    /**
+     * Verify a normal start/stop call pair without any activity pauses.
+     */
+    @Test
+    @SmallTest
+    @UiThreadTest
+    @Feature({"Location"})
+    public void testStartStop() throws Exception {
+        mLocationProvider.start(false);
+        Assert.assertTrue("Should be running", mLocationProvider.isRunning());
+        mLocationProvider.stop();
+        Assert.assertFalse("Should have stopped", mLocationProvider.isRunning());
+    }
+
+    /**
+     * Verify a start/upgrade/stop call sequence without any activity pauses.
+     */
+    @Test
+    @SmallTest
+    @UiThreadTest
+    @Feature({"Location"})
+    public void testStartUpgradeStop() throws Exception {
+        mLocationProvider.start(false);
+        Assert.assertTrue("Should be running", mLocationProvider.isRunning());
+        mLocationProvider.start(true);
+        Assert.assertTrue("Should be running", mLocationProvider.isRunning());
+        mLocationProvider.stop();
+        Assert.assertFalse("Should have stopped", mLocationProvider.isRunning());
+    }
+}
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/OWNERS b/content/public/android/javatests/src/org/chromium/content/browser/OWNERS
index 60ede9c..05c5396 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/OWNERS
+++ b/content/public/android/javatests/src/org/chromium/content/browser/OWNERS
@@ -1,6 +1,9 @@
 # Device Motion / Orientation API related
 per-file DeviceSensorsTest.java=timvolodine@chromium.org
 
+# Geolocation API related
+per-file LocationProviderTest.java=timvolodine@chromium.org
+
 # Screen Orientation API related
 per-file ScreenOrientation*.java=mlamouri@chromium.org
 
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
index 4f5f078..72991bf 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -164,28 +164,6 @@
     observer.DeviceChanged(adapter, device);
 }
 
-void PerformCharacteristicReadValue(
-    MockBluetoothAdapter* adapter,
-    MockBluetoothGattCharacteristic* characteristic,
-    const BluetoothRemoteGattCharacteristic::ValueCallback& callback,
-    const std::vector<uint8_t>& value) {
-  for (auto& observer : adapter->GetObservers()) {
-    observer.GattCharacteristicValueChanged(adapter, characteristic, value);
-  }
-  callback.Run(value);
-}
-
-void PerformDescriptorReadValue(
-    MockBluetoothAdapter* adapter,
-    MockBluetoothGattDescriptor* descriptor,
-    const BluetoothRemoteGattDescriptor::ValueCallback& callback,
-    const std::vector<uint8_t>& value) {
-  for (auto& observer : adapter->GetObservers()) {
-    observer.GattDescriptorValueChanged(adapter, descriptor, value);
-  }
-  callback.Run(value);
-}
-
 }  // namespace
 
 namespace content {
@@ -724,15 +702,8 @@
       measurement_interval.get();
 
   ON_CALL(*measurement_interval, ReadRemoteCharacteristic(_, _))
-      .WillByDefault(RunCallbackWithResult<0 /* success_callback */>(
-          [adapter_ptr, measurement_ptr]() {
-            std::vector<uint8_t> interval({1});
-            for (auto& observer : adapter_ptr->GetObservers()) {
-              observer.GattCharacteristicValueChanged(
-                  adapter_ptr, measurement_ptr, interval);
-            }
-            return interval;
-          }));
+      .WillByDefault(
+          RunCallback<0 /* success_callback */>(std::vector<uint8_t>({1})));
 
   ON_CALL(*measurement_interval, WriteRemoteCharacteristic(_, _, _))
       .WillByDefault(RunCallback<1 /* success_callback */>());
@@ -1048,9 +1019,7 @@
               error_callback) {
         base::Closure pending;
         if (succeeds) {
-          pending = base::Bind(&PerformCharacteristicReadValue,
-                               base::RetainedRef(adapter_ptr), measurement_ptr,
-                               callback, std::vector<uint8_t>({1}));
+          pending = base::Bind(callback, std::vector<uint8_t>({1}));
         } else {
           pending = base::Bind(error_callback,
                                BluetoothRemoteGattService::GATT_ERROR_FAILED);
@@ -1125,9 +1094,7 @@
           const BluetoothRemoteGattDescriptor::ErrorCallback& error_callback) {
         base::Closure pending;
         if (succeeds) {
-          pending = base::Bind(
-              &PerformDescriptorReadValue, base::RetainedRef(adapter_ptr),
-              user_descriptor_ptr, callback, std::vector<uint8_t>({1}));
+          pending = base::Bind(callback, std::vector<uint8_t>({1}));
         } else {
           pending = base::Bind(error_callback,
                                BluetoothRemoteGattService::GATT_ERROR_FAILED);
@@ -1613,44 +1580,20 @@
       body_sensor_location_chest(GetBaseGATTCharacteristic(
           "Body Sensor Location Chest", heart_rate.get(), kBodySensorLocation,
           BluetoothRemoteGattCharacteristic::PROPERTY_READ));
-  BluetoothRemoteGattCharacteristic* location_chest_ptr =
-      body_sensor_location_chest.get();
 
   ON_CALL(*body_sensor_location_chest, ReadRemoteCharacteristic(_, _))
-      .WillByDefault(RunCallbackWithResult<0 /* success_callback */>(
-          [adapter, location_chest_ptr]() {
-            std::vector<uint8_t> location(1 /* size */);
-            location[0] = 1;  // Chest
-            // Read a characteristic has a side effect of
-            // GattCharacteristicValueChanged being called.
-            for (auto& observer : adapter->GetObservers()) {
-              observer.GattCharacteristicValueChanged(
-                  adapter, location_chest_ptr, location);
-            }
-            return location;
-          }));
+      .WillByDefault(RunCallback<0 /* success_callback */>(
+          std::vector<uint8_t>({1} /* Chest */)));
 
   // Body Sensor Location Characteristic (Wrist)
   std::unique_ptr<NiceMockBluetoothGattCharacteristic>
       body_sensor_location_wrist(GetBaseGATTCharacteristic(
           "Body Sensor Location Wrist", heart_rate.get(), kBodySensorLocation,
           BluetoothRemoteGattCharacteristic::PROPERTY_READ));
-  BluetoothRemoteGattCharacteristic* location_wrist_ptr =
-      body_sensor_location_wrist.get();
 
   ON_CALL(*body_sensor_location_wrist, ReadRemoteCharacteristic(_, _))
-      .WillByDefault(RunCallbackWithResult<0 /* success_callback */>(
-          [adapter, location_wrist_ptr]() {
-            std::vector<uint8_t> location(1 /* size */);
-            location[0] = 2;  // Wrist
-            // Read a characteristic has a side effect of
-            // GattCharacteristicValueChanged being called.
-            for (auto& observer : adapter->GetObservers()) {
-              observer.GattCharacteristicValueChanged(
-                  adapter, location_wrist_ptr, location);
-            }
-            return location;
-          }));
+      .WillByDefault(RunCallback<0 /* success_callback */>(
+          std::vector<uint8_t>({2} /* Wrist */)));
 
   heart_rate->AddMockCharacteristic(std::move(heart_rate_measurement));
   heart_rate->AddMockCharacteristic(std::move(body_sensor_location_chest));
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 5e3cc48..64f0c92 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1315,11 +1315,8 @@
     "../common/content_security_policy/csp_source_unittest.cc",
     "../common/cross_site_document_classifier_unittest.cc",
     "../common/cursors/webcursor_unittest.cc",
-    "../common/database_connections_unittest.cc",
-    "../common/database_identifier_unittest.cc",
     "../common/dom_storage/dom_storage_map_unittest.cc",
     "../common/feature_policy/feature_policy_unittest.cc",
-    "../common/fileapi/file_system_util_unittest.cc",
     "../common/indexed_db/indexed_db_key_unittest.cc",
     "../common/input/event_with_latency_info_unittest.cc",
     "../common/input/gesture_event_stream_validator_unittest.cc",
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 76074eb..1542a87 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -7,7 +7,6 @@
 import("//testing/test.gni")
 
 if (is_android) {
-  import("//build/config/android/config.gni")
   import("//build/config/android/rules.gni")  # For generate_jni().
 }
 
@@ -301,20 +300,14 @@
     java_files = [
       "gamepad/android/junit/src/org/chromium/device/gamepad/GamepadMappingsTest.java",
       "generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java",
-      "geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java",
       "nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java",
     ]
     deps = [
-      "$google_play_services_package:google_play_services_base_java",
-      "$google_play_services_package:google_play_services_basement_java",
-      "$google_play_services_package:google_play_services_location_java",
       "//base:base_java",
       "//base:base_java_test_support",
       "//device/gamepad:java",
       "//device/generic_sensor:java",
       "//device/generic_sensor/public/interfaces:interfaces_java",
-      "//device/geolocation:geolocation_java",
-      "//device/geolocation:geolocation_java_test_support",
       "//device/nfc:mojo_bindings_java",
       "//device/nfc/android:java",
       "//mojo/public/java:bindings_java",
diff --git a/device/geolocation/BUILD.gn b/device/geolocation/BUILD.gn
index 51b1284..19ba0bf 100644
--- a/device/geolocation/BUILD.gn
+++ b/device/geolocation/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/config/features.gni")
 
 if (is_android) {
-  import("//build/config/android/config.gni")
   import("//build/config/android/rules.gni")  # For generate_jni().
 }
 
@@ -128,15 +127,11 @@
       "android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java",
       "android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java",
       "android/java/src/org/chromium/device/geolocation/LocationProviderFactory.java",
-      "android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java",
     ]
 
     deps = [
       ":geolocation",
       ":geolocation_jni_headers",
-      "$google_play_services_package:google_play_services_base_java",
-      "$google_play_services_package:google_play_services_basement_java",
-      "$google_play_services_package:google_play_services_location_java",
       "//base:base_java",
     ]
   }
diff --git a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
index c735159..bd2ffb9 100644
--- a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
+++ b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
@@ -5,9 +5,7 @@
 package org.chromium.device.geolocation;
 
 import android.content.Context;
-import android.location.Location;
 
-import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -26,8 +24,6 @@
 @MainDex
 @VisibleForTesting
 public class LocationProviderAdapter {
-    private static final String TAG = "cr_LocationProvider";
-
     // Delegate handling the real work in the main thread.
     private LocationProviderFactory.LocationProvider mImpl;
 
@@ -79,15 +75,14 @@
         return mImpl.isRunning();
     }
 
-    public static void onNewLocationAvailable(Location location) {
-        nativeNewLocationAvailable(location.getLatitude(), location.getLongitude(),
-                location.getTime() / 1000.0, location.hasAltitude(), location.getAltitude(),
-                location.hasAccuracy(), location.getAccuracy(), location.hasBearing(),
-                location.getBearing(), location.hasSpeed(), location.getSpeed());
+    public static void newLocationAvailable(double latitude, double longitude, double timestamp,
+            boolean hasAltitude, double altitude, boolean hasAccuracy, double accuracy,
+            boolean hasHeading, double heading, boolean hasSpeed, double speed) {
+        nativeNewLocationAvailable(latitude, longitude, timestamp, hasAltitude, altitude,
+                hasAccuracy, accuracy, hasHeading, heading, hasSpeed, speed);
     }
 
     public static void newErrorAvailable(String message) {
-        Log.e(TAG, "newErrorAvailable %s", message);
         nativeNewErrorAvailable(message);
     }
 
diff --git a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java
index 68c4b46..261ce9d 100644
--- a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java
+++ b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAndroid.java
@@ -13,7 +13,6 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
-import org.chromium.base.VisibleForTesting;
 
 import java.util.List;
 
@@ -38,20 +37,17 @@
 
     @Override
     public void start(boolean enableHighAccuracy) {
-        ThreadUtils.assertOnUiThread();
         unregisterFromLocationUpdates();
         registerForLocationUpdates(enableHighAccuracy);
     }
 
     @Override
     public void stop() {
-        ThreadUtils.assertOnUiThread();
         unregisterFromLocationUpdates();
     }
 
     @Override
     public boolean isRunning() {
-        ThreadUtils.assertOnUiThread();
         return mIsRunning;
     }
 
@@ -61,7 +57,7 @@
         // possible that we receive callbacks after unregistering. At this point, the
         // native object will no longer exist.
         if (mIsRunning) {
-            LocationProviderAdapter.onNewLocationAvailable(location);
+            updateNewLocation(location);
         }
     }
 
@@ -74,12 +70,7 @@
     @Override
     public void onProviderDisabled(String provider) {}
 
-    @VisibleForTesting
-    public void setLocationManagerForTesting(LocationManager manager) {
-        mLocationManager = manager;
-    }
-
-    private void createLocationManagerIfNeeded() {
+    private void ensureLocationManagerCreated() {
         if (mLocationManager != null) return;
         mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
         if (mLocationManager == null) {
@@ -91,7 +82,7 @@
      * Registers this object with the location service.
      */
     private void registerForLocationUpdates(boolean enableHighAccuracy) {
-        createLocationManagerIfNeeded();
+        ensureLocationManagerCreated();
         if (usePassiveOneShotLocation()) return;
 
         assert !mIsRunning;
@@ -112,8 +103,8 @@
             unregisterFromLocationUpdates();
             // Propagate an error to JavaScript, this can happen in case of WebView
             // when the embedding app does not have sufficient permissions.
-            LocationProviderAdapter.newErrorAvailable(
-                    "application does not have sufficient geolocation permissions.");
+            LocationProviderAdapter.newErrorAvailable("application does not have sufficient "
+                    + "geolocation permissions.");
         } catch (IllegalArgumentException e) {
             Log.e(TAG, "Caught IllegalArgumentException registering for location updates.");
             unregisterFromLocationUpdates();
@@ -125,26 +116,33 @@
      * Unregisters this object from the location service.
      */
     private void unregisterFromLocationUpdates() {
-        if (!mIsRunning) return;
-        mIsRunning = false;
-        mLocationManager.removeUpdates(this);
+        if (mIsRunning) {
+            mIsRunning = false;
+            mLocationManager.removeUpdates(this);
+        }
+    }
+
+    private void updateNewLocation(Location location) {
+        LocationProviderAdapter.newLocationAvailable(location.getLatitude(),
+                location.getLongitude(), location.getTime() / 1000.0, location.hasAltitude(),
+                location.getAltitude(), location.hasAccuracy(), location.getAccuracy(),
+                location.hasBearing(), location.getBearing(), location.hasSpeed(),
+                location.getSpeed());
     }
 
     private boolean usePassiveOneShotLocation() {
-        if (!isOnlyPassiveLocationProviderEnabled()) {
-            return false;
-        }
+        if (!isOnlyPassiveLocationProviderEnabled()) return false;
 
         // Do not request a location update if the only available location provider is
         // the passive one. Make use of the last known location and call
-        // onNewLocationAvailable directly.
+        // onLocationChanged directly.
         final Location location =
                 mLocationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
         if (location != null) {
             ThreadUtils.runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
-                    LocationProviderAdapter.onNewLocationAvailable(location);
+                    updateNewLocation(location);
                 }
             });
         }
@@ -156,7 +154,7 @@
      * in the system.
      */
     private boolean isOnlyPassiveLocationProviderEnabled() {
-        final List<String> providers = mLocationManager.getProviders(true);
+        List<String> providers = mLocationManager.getProviders(true);
         return providers != null && providers.size() == 1
                 && providers.get(0).equals(LocationManager.PASSIVE_PROVIDER);
     }
diff --git a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderFactory.java b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderFactory.java
index 956dd67..3ffc36a 100644
--- a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderFactory.java
+++ b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderFactory.java
@@ -9,7 +9,8 @@
 import org.chromium.base.VisibleForTesting;
 
 /**
- * Factory to create a LocationProvider to allow us to inject a mock for tests.
+ * Factory to create a LocationProvider to allow us to inject
+ * a mock for tests.
  */
 public class LocationProviderFactory {
     private static LocationProviderFactory.LocationProvider sProviderImpl;
@@ -19,9 +20,8 @@
      */
     public interface LocationProvider {
         /**
-         * Start listening for location updates. Calling several times before stop() is interpreted
-         * as restart.
-         * @param enableHighAccuracy Whether or not to enable high accuracy location.
+         * Start listening for location updates.
+         * @param enableHighAccuracy Whether or not to enable high accuracy location providers.
          */
         public void start(boolean enableHighAccuracy);
 
@@ -40,15 +40,12 @@
 
     @VisibleForTesting
     public static void setLocationProviderImpl(LocationProviderFactory.LocationProvider provider) {
+        assert sProviderImpl == null;
         sProviderImpl = provider;
     }
 
     public static LocationProvider create(Context context) {
-        if (sProviderImpl != null) return sProviderImpl;
-
-        if (LocationProviderGmsCore.isGooglePlayServicesAvailable(context)) {
-            sProviderImpl = new LocationProviderGmsCore(context);
-        } else {
+        if (sProviderImpl == null) {
             sProviderImpl = new LocationProviderAndroid(context);
         }
         return sProviderImpl;
diff --git a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java b/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java
deleted file mode 100644
index aed6822..0000000
--- a/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderGmsCore.java
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.device.geolocation;
-
-import android.content.Context;
-import android.location.Location;
-import android.os.Bundle;
-
-import com.google.android.gms.common.ConnectionResult;
-import com.google.android.gms.common.GoogleApiAvailability;
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
-import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
-import com.google.android.gms.location.FusedLocationProviderApi;
-import com.google.android.gms.location.LocationListener;
-import com.google.android.gms.location.LocationRequest;
-import com.google.android.gms.location.LocationServices;
-
-import org.chromium.base.Log;
-import org.chromium.base.ThreadUtils;
-
-/**
- * This is a LocationProvider using Google Play Services.
- *
- * https://developers.google.com/android/reference/com/google/android/gms/location/package-summary
- */
-public class LocationProviderGmsCore implements ConnectionCallbacks, OnConnectionFailedListener,
-                                                LocationListener,
-                                                LocationProviderFactory.LocationProvider {
-    private static final String TAG = "cr_LocationProvider";
-
-    // Values for the LocationRequest's setInterval for normal and high accuracy, respectively.
-    private static final long UPDATE_INTERVAL_MS = 1000;
-    private static final long UPDATE_INTERVAL_FAST_MS = 500;
-
-    private final GoogleApiClient mGoogleApiClient;
-    private FusedLocationProviderApi mLocationProviderApi = LocationServices.FusedLocationApi;
-
-    private boolean mEnablehighAccuracy;
-    private LocationRequest mLocationRequest;
-
-    public static boolean isGooglePlayServicesAvailable(Context context) {
-        return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
-                == ConnectionResult.SUCCESS;
-    }
-
-    LocationProviderGmsCore(Context context) {
-        Log.i(TAG, "Google Play Services");
-        mGoogleApiClient = new GoogleApiClient.Builder(context)
-                                   .addApi(LocationServices.API)
-                                   .addConnectionCallbacks(this)
-                                   .addOnConnectionFailedListener(this)
-                                   .build();
-        assert mGoogleApiClient != null;
-    }
-
-    LocationProviderGmsCore(GoogleApiClient client, FusedLocationProviderApi locationApi) {
-        mGoogleApiClient = client;
-        mLocationProviderApi = locationApi;
-    }
-
-    // ConnectionCallbacks implementation
-    @Override
-    public void onConnected(Bundle connectionHint) {
-        ThreadUtils.assertOnUiThread();
-
-        mLocationRequest = LocationRequest.create();
-        if (mEnablehighAccuracy) {
-            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
-                    .setInterval(UPDATE_INTERVAL_FAST_MS);
-        } else {
-            mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
-                    .setInterval(UPDATE_INTERVAL_MS);
-        }
-
-        final Location location = mLocationProviderApi.getLastLocation(mGoogleApiClient);
-        if (location != null) {
-            LocationProviderAdapter.onNewLocationAvailable(location);
-        }
-
-        try {
-            // Request updates on UI Thread replicating LocationProviderAndroid's behaviour.
-            mLocationProviderApi.requestLocationUpdates(
-                    mGoogleApiClient, mLocationRequest, this, ThreadUtils.getUiThreadLooper());
-        } catch (IllegalStateException e) {
-            // Happens "If this method is executed in a thread that has not called Looper.prepare()"
-            Log.e(TAG, "Unexpected exception " + e);
-            assert false;
-        }
-    }
-
-    @Override
-    public void onConnectionSuspended(int cause) {}
-
-    // OnConnectionFailedListener implementation
-    @Override
-    public void onConnectionFailed(ConnectionResult result) {
-        LocationProviderAdapter.newErrorAvailable(
-                "Failed to connect to Google Play Services: " + result.toString());
-    }
-
-    // LocationProviderFactory.LocationProvider implementation
-    @Override
-    public void start(boolean enableHighAccuracy) {
-        ThreadUtils.assertOnUiThread();
-        if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
-
-        mEnablehighAccuracy = enableHighAccuracy;
-        mGoogleApiClient.connect(); // Should return via onConnected().
-    }
-
-    @Override
-    public void stop() {
-        ThreadUtils.assertOnUiThread();
-        if (!mGoogleApiClient.isConnected()) return;
-
-        mLocationProviderApi.removeLocationUpdates(mGoogleApiClient, this);
-
-        mGoogleApiClient.disconnect();
-    }
-
-    @Override
-    public boolean isRunning() {
-        assert ThreadUtils.runningOnUiThread();
-        if (mGoogleApiClient == null) return false;
-        return mGoogleApiClient.isConnecting() || mGoogleApiClient.isConnected();
-    }
-
-    // LocationListener implementation
-    @Override
-    public void onLocationChanged(Location location) {
-        LocationProviderAdapter.onNewLocationAvailable(location);
-    }
-}
diff --git a/device/geolocation/android/javatests/src/org/chromium/device/geolocation/MockLocationProvider.java b/device/geolocation/android/javatests/src/org/chromium/device/geolocation/MockLocationProvider.java
index 2ed205d..ae99afb 100644
--- a/device/geolocation/android/javatests/src/org/chromium/device/geolocation/MockLocationProvider.java
+++ b/device/geolocation/android/javatests/src/org/chromium/device/geolocation/MockLocationProvider.java
@@ -4,7 +4,6 @@
 
 package org.chromium.device.geolocation;
 
-import android.location.Location;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
@@ -78,9 +77,7 @@
     }
 
     private void newLocation() {
-        Location location = new Location("MockLocationProvider");
-        location.setTime(System.currentTimeMillis());
-        location.setAccuracy(0.5f);
-        LocationProviderAdapter.onNewLocationAvailable(location);
+        LocationProviderAdapter.newLocationAvailable(
+                0, 0, System.currentTimeMillis() / 1000.0, false, 0, true, 0.5, false, 0, false, 0);
     }
 };
diff --git a/device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java b/device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java
deleted file mode 100644
index 5b09459..0000000
--- a/device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.device.geolocation;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doAnswer;
-
-import android.content.Context;
-import android.location.LocationManager;
-
-import com.google.android.gms.common.api.GoogleApiClient;
-import com.google.android.gms.location.FusedLocationProviderApi;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.robolectric.ParameterizedRobolectricTestRunner;
-import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-import org.robolectric.internal.Shadow;
-import org.robolectric.shadows.ShadowLocationManager;
-import org.robolectric.shadows.ShadowLog; // remove me ?
-
-import org.chromium.base.ThreadUtils;
-import org.chromium.base.test.util.Feature;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * Test suite for Java Geolocation.
- */
-@RunWith(ParameterizedRobolectricTestRunner.class)
-@Config(sdk = 21, manifest = Config.NONE)
-public class LocationProviderTest {
-    public static enum LocationProviderType { MOCK, ANDROID, GMS_CORE }
-
-    @Parameters
-    public static Collection<Object[]> data() {
-        return Arrays.asList(new Object[][] {{LocationProviderType.MOCK},
-                {LocationProviderType.ANDROID}, {LocationProviderType.GMS_CORE}});
-    }
-
-    @Mock
-    private Context mContext;
-
-    // Member variables for LocationProviderType.GMS_CORE case.
-    @Mock
-    private GoogleApiClient mGoogleApiClient;
-    private boolean mGoogleApiClientIsConnected;
-
-    // Member variables for LocationProviderType.ANDROID case.
-    private LocationManager mLocationManager;
-    private ShadowLocationManager mShadowLocationManager;
-
-    private LocationProviderAdapter mLocationProviderAdapter;
-
-    private final LocationProviderType mApi;
-
-    public LocationProviderTest(LocationProviderType api) {
-        mApi = api;
-    }
-
-    @Before
-    public void setUp() {
-        ShadowLog.stream = System.out;
-        MockitoAnnotations.initMocks(this);
-
-        mContext = Mockito.mock(Context.class);
-    }
-
-    /**
-     * Verify a normal start/stop call pair with the given LocationProvider.
-     */
-    @Test
-    @Feature({"Location"})
-    public void testStartStop() {
-        assertTrue("Should be on UI thread", ThreadUtils.runningOnUiThread());
-
-        setLocationProvider();
-
-        createLocationProviderAdapter();
-        startLocationProviderAdapter(false);
-        stopLocationProviderAdapter();
-    }
-
-    /**
-     * Verify a start/upgrade/stop call sequencewith the given LocationProvider.
-     */
-    @Test
-    @Feature({"Location"})
-    public void testStartUpgradeStop() {
-        assertTrue("Should be on UI thread", ThreadUtils.runningOnUiThread());
-
-        setLocationProvider();
-
-        createLocationProviderAdapter();
-        startLocationProviderAdapter(false);
-        startLocationProviderAdapter(true);
-        stopLocationProviderAdapter();
-    }
-
-    private void createLocationProviderAdapter() {
-        mLocationProviderAdapter = LocationProviderAdapter.create(mContext);
-        assertNotNull("LocationProvider", mLocationProviderAdapter);
-    }
-
-    private void setLocationProvider() {
-        if (mApi == LocationProviderType.MOCK) {
-            setLocationProviderMock();
-        } else if (mApi == LocationProviderType.ANDROID) {
-            setLocationProviderAndroid();
-        } else if (mApi == LocationProviderType.GMS_CORE) {
-            setLocationProviderGmsCore();
-        } else {
-            assert false;
-        }
-    }
-
-    private void setLocationProviderMock() {
-        LocationProviderFactory.setLocationProviderImpl(new MockLocationProvider());
-    }
-
-    private void setLocationProviderAndroid() {
-        LocationProviderAndroid locationProviderAndroid = new LocationProviderAndroid(mContext);
-
-        // Robolectric has a ShadowLocationManager class that mocks the behaviour of the real
-        // class very closely. Use it here.
-        mLocationManager = Shadow.newInstanceOf(LocationManager.class);
-        mShadowLocationManager = Shadows.shadowOf(mLocationManager);
-        locationProviderAndroid.setLocationManagerForTesting(mLocationManager);
-        LocationProviderFactory.setLocationProviderImpl(locationProviderAndroid);
-    }
-
-    private void setLocationProviderGmsCore() {
-        // Robolectric has a ShadowGoogleApiClientBuilder class that mocks the behaviour of the real
-        // class very closely, but it's not available in our build
-        mGoogleApiClient = Mockito.mock(GoogleApiClient.class);
-        mGoogleApiClientIsConnected = false;
-        doAnswer(new Answer<Boolean>() {
-            public Boolean answer(InvocationOnMock invocation) {
-                return mGoogleApiClientIsConnected;
-            }
-        })
-                .when(mGoogleApiClient)
-                .isConnected();
-
-        doAnswer(new Answer<Void>() {
-            public Void answer(InvocationOnMock invocation) {
-                mGoogleApiClientIsConnected = true;
-                return null;
-            }
-        })
-                .when(mGoogleApiClient)
-                .connect();
-
-        doAnswer(new Answer<Void>() {
-            public Void answer(InvocationOnMock invocation) {
-                mGoogleApiClientIsConnected = false;
-                return null;
-            }
-        })
-                .when(mGoogleApiClient)
-                .disconnect();
-
-        FusedLocationProviderApi fusedLocationProviderApi =
-                Mockito.mock(FusedLocationProviderApi.class);
-
-        LocationProviderGmsCore locationProviderGmsCore =
-                new LocationProviderGmsCore(mGoogleApiClient, fusedLocationProviderApi);
-
-        LocationProviderFactory.setLocationProviderImpl(locationProviderGmsCore);
-    }
-
-    private void startLocationProviderAdapter(boolean highResolution) {
-        mLocationProviderAdapter.start(highResolution);
-        assertTrue("Should be running", mLocationProviderAdapter.isRunning());
-    }
-
-    private void stopLocationProviderAdapter() {
-        mLocationProviderAdapter.stop();
-        assertFalse("Should have stopped", mLocationProviderAdapter.isRunning());
-    }
-}
diff --git a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm
index e572762..b010c60 100644
--- a/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm
+++ b/ios/chrome/browser/ui/first_run/welcome_to_chrome_view.mm
@@ -14,6 +14,7 @@
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h"
 #import "ios/chrome/browser/ui/util/label_link_controller.h"
+#import "ios/chrome/browser/ui/util/label_observer.h"
 #include "ios/chrome/common/string_util.h"
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
@@ -92,8 +93,12 @@
 @property(strong, nonatomic, readonly) UIImageView* imageView;
 // The "Terms of Service" label.
 @property(strong, nonatomic, readonly) UILabel* TOSLabel;
+// Observer for setting the size of the TOSLabel with cr_lineHeight.
+@property(strong, nonatomic) LabelObserver* TOSObserver;
 // The stats reporting opt-in label.
 @property(strong, nonatomic, readonly) UILabel* optInLabel;
+// Observer for setting the size of the optInLabel with cr_lineHeight.
+@property(strong, nonatomic) LabelObserver* optInObserver;
 // The stats reporting opt-in checkbox button.
 @property(strong, nonatomic, readonly) UIButton* checkBoxButton;
 // The "Accept & Continue" button.
@@ -135,6 +140,8 @@
 @implementation WelcomeToChromeView
 
 @synthesize delegate = _delegate;
+@synthesize TOSObserver = _TOSObserver;
+@synthesize optInObserver = _optInObserver;
 
 - (instancetype)initWithFrame:(CGRect)frame {
   self = [super initWithFrame:frame];
@@ -179,6 +186,11 @@
                    completion:nil];
 }
 
+- (void)dealloc {
+  [self.TOSObserver stopObserving];
+  [self.optInObserver stopObserving];
+}
+
 #pragma mark - Accessors
 
 - (BOOL)isCheckBoxSelected {
@@ -223,6 +235,10 @@
 - (UILabel*)TOSLabel {
   if (!_TOSLabel) {
     _TOSLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    // Add an observer to the label to be able to keep the cr_lineHeight.
+    self.TOSObserver = [LabelObserver observerForLabel:_TOSLabel];
+    [self.TOSObserver startObserving];
+
     [_TOSLabel setNumberOfLines:0];
     [_TOSLabel setTextAlignment:NSTextAlignmentCenter];
   }
@@ -232,6 +248,10 @@
 - (UILabel*)optInLabel {
   if (!_optInLabel) {
     _optInLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    // Add an observer to the label to be able to keep the cr_lineHeight.
+    self.optInObserver = [LabelObserver observerForLabel:_optInLabel];
+    [self.optInObserver startObserving];
+
     [_optInLabel setNumberOfLines:0];
     [_optInLabel
         setText:l10n_util::GetNSString(IDS_IOS_FIRSTRUN_NEW_OPT_IN_LABEL)];
diff --git a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h
index 9cacede..97f4b9b 100644
--- a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h
+++ b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h
@@ -8,11 +8,11 @@
 #import <UIKit/UIKit.h>
 
 @interface UILabel (CRUILabelAttributeUtils)
+// The height of the label.
+// Make sure to create a LabelObserver for this label and start observing before
+// setting this property.
 @property(nonatomic, assign, setter=cr_setLineHeight:) CGFloat cr_lineHeight;
 
-// Adjusts the line height of the receiver so that the lines will evenly f
-- (void)cr_adjustLineHeightForMaximimumLines:(NSUInteger)maximumLines;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_UTIL_CRUILABEL_ATTRIBUTEUTILS_H_
diff --git a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.mm b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.mm
index dee9ac4..56bf04a 100644
--- a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.mm
+++ b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.mm
@@ -74,21 +74,4 @@
   self.attributedText = newString;
 }
 
-- (void)cr_adjustLineHeightForMaximimumLines:(NSUInteger)maximumLines {
-  CGSize labelSize = self.bounds.size;
-  CGFloat lineHeight = self.cr_lineHeight;
-  CGFloat numberOfLines = floorf(labelSize.height / lineHeight);
-  CGSize maxSize = CGSizeMake(labelSize.width, CGFLOAT_MAX);
-  CGSize textSize = [self sizeThatFits:maxSize];
-
-  // |textSize.height| should be a multiple of |lineHeight|. If this is not the
-  // case, then it is safer to fit one more line to ensure that the text of the
-  // label is not cropped.
-  CGFloat requiredNumberOfLines = ceilf(textSize.height / lineHeight);
-  if (requiredNumberOfLines > numberOfLines) {
-    requiredNumberOfLines = MIN(requiredNumberOfLines, maximumLines);
-    self.cr_lineHeight = floorf(labelSize.height / requiredNumberOfLines);
-  }
-}
-
 @end
diff --git a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils_unittest.mm b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils_unittest.mm
index 875ca6a..255a873 100644
--- a/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils_unittest.mm
+++ b/ios/chrome/browser/ui/util/CRUILabel+AttributeUtils_unittest.mm
@@ -5,6 +5,7 @@
 #include "ios/chrome/browser/ui/util/CRUILabel+AttributeUtils.h"
 
 #import "base/mac/scoped_nsobject.h"
+#import "ios/chrome/browser/ui/util/label_observer.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
@@ -15,8 +16,13 @@
   void SetUp() override {
     PlatformTest::SetUp();
     _scopedLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]);
+    _observer.reset(
+        [[LabelObserver observerForLabel:_scopedLabel.get()] retain]);
+    [_observer startObserving];
   }
 
+  ~UILabelAttributeUtilsTest() override { [_observer stopObserving]; }
+
   void CheckLabelLineHeight(CGFloat expected_height) {
     UILabel* label = _scopedLabel.get();
     EXPECT_NE(nil, label.attributedText);
@@ -29,15 +35,34 @@
     EXPECT_EQ(expected_height, label.cr_lineHeight);
   }
   base::scoped_nsobject<UILabel> _scopedLabel;
+  base::scoped_nsobject<LabelObserver> _observer;
 };
 }
 
-TEST_F(UILabelAttributeUtilsTest, CleanupTest) {
+TEST_F(UILabelAttributeUtilsTest, TwoObservers) {
   UILabel* label = _scopedLabel.get();
-  // Setting a lineheight will create an observer object.
+  label.text = @"sample text";
+
+  // Add a second observer.
+  base::scoped_nsobject<LabelObserver> secondObserver(
+      [[LabelObserver observerForLabel:label] retain]);
+  [secondObserver startObserving];
+
+  // Modify the line height with two observers.
   label.cr_lineHeight = 18.0;
-  // The observer should stop observing cleanly when the label is deallocated.
-  EXPECT_NO_FATAL_FAILURE(_scopedLabel.reset());
+  CheckLabelLineHeight(18.0);
+  [secondObserver stopObserving];
+  secondObserver.reset();
+
+  // Even when one observer is stopped, the second is still observing.
+  label.cr_lineHeight = 21.0;
+  CheckLabelLineHeight(21.0);
+
+  // Once both are stopped, the height isn't persisted when the text changes.
+  [_observer stopObserving];
+  label.cr_lineHeight = 25.0;
+  label.text = @"longer sample text";
+  CheckLabelLineHeight(0);
 }
 
 TEST_F(UILabelAttributeUtilsTest, SettingTests) {
diff --git a/ios/chrome/browser/ui/util/label_link_controller.h b/ios/chrome/browser/ui/util/label_link_controller.h
index 35e8928..2fab753 100644
--- a/ios/chrome/browser/ui/util/label_link_controller.h
+++ b/ios/chrome/browser/ui/util/label_link_controller.h
@@ -45,8 +45,8 @@
 // attributed text accordingly.
 @property(nonatomic, retain) UIFont* linkFont;
 
-// Creates a new controller for |label|, whose lifetime is expected to exceed
-// that of the receiver. |action| is the block called for any tapped link.
+// Creates a new controller for |label|, keeping a strong reference. |action| is
+// the block called for any tapped link.
 - (instancetype)initWithLabel:(UILabel*)label
                        action:(ProceduralBlockWithURL)action;
 
diff --git a/ios/chrome/browser/ui/util/label_link_controller.mm b/ios/chrome/browser/ui/util/label_link_controller.mm
index 7820ead..a34d189 100644
--- a/ios/chrome/browser/ui/util/label_link_controller.mm
+++ b/ios/chrome/browser/ui/util/label_link_controller.mm
@@ -133,7 +133,7 @@
 @implementation LabelLinkController {
   // Ivars immutable for the lifetime of the object.
   base::mac::ScopedBlock<ProceduralBlockWithURL> _action;
-  base::WeakNSObject<UILabel> _label;  // weak
+  base::scoped_nsobject<UILabel> _label;
   base::scoped_nsobject<UITapGestureRecognizer> _linkTapRecognizer;
 
   // Ivas backing properties.
@@ -151,6 +151,7 @@
   // Internal tracking.
   BOOL _justUpdatedStyles;
   base::scoped_nsobject<NSMutableArray> _linkButtons;
+  base::scoped_nsobject<LabelObserver> _labelObserver;
 }
 
 @synthesize showTapAreas = _showTapAreas;
@@ -161,11 +162,13 @@
                        action:(ProceduralBlockWithURL)action {
   if ((self = [super init])) {
     DCHECK(label);
-    _label.reset(label);
+    _label.reset([label retain]);
     _action.reset(action, base::scoped_policy::RETAIN);
     _linkUnderlineStyle = NSUnderlineStyleNone;
     [self reset];
 
+    _labelObserver.reset([[LabelObserver observerForLabel:_label] retain]);
+    [_labelObserver startObserving];
     [self addLabelObserverActions];
 
     self.textMapperClass = [CoreTextRegionMapper class];
@@ -183,9 +186,8 @@
 }
 
 - (void)addLabelObserverActions {
-  LabelObserver* observer = [LabelObserver observerForLabel:_label];
   base::WeakNSObject<LabelLinkController> weakSelf(self);
-  [observer addStyleChangedAction:^(UILabel* label) {
+  [_labelObserver addStyleChangedAction:^(UILabel* label) {
     // One of the style properties has been changed, which will silently
     // update the label's attributedText.
     if (!weakSelf)
@@ -193,7 +195,7 @@
     base::scoped_nsobject<LabelLinkController> strongSelf([weakSelf retain]);
     [strongSelf labelStyleInvalidated];
   }];
-  [observer addTextChangedAction:^(UILabel* label) {
+  [_labelObserver addTextChangedAction:^(UILabel* label) {
     if (!weakSelf)
       return;
     base::scoped_nsobject<LabelLinkController> strongSelf([weakSelf retain]);
@@ -207,7 +209,7 @@
       [strongSelf reset];
     }
   }];
-  [observer addLayoutChangedAction:^(UILabel* label) {
+  [_labelObserver addLayoutChangedAction:^(UILabel* label) {
     if (!weakSelf)
       return;
     base::scoped_nsobject<LabelLinkController> strongSelf([weakSelf retain]);
@@ -223,6 +225,7 @@
 
 - (void)dealloc {
   [self clearTapButtons];
+  [_labelObserver stopObserving];
   [super dealloc];
 }
 
diff --git a/ios/chrome/browser/ui/util/label_observer.h b/ios/chrome/browser/ui/util/label_observer.h
index f102efb..198c620 100644
--- a/ios/chrome/browser/ui/util/label_observer.h
+++ b/ios/chrome/browser/ui/util/label_observer.h
@@ -16,13 +16,21 @@
 @interface LabelObserver : NSObject
 
 // Returns the LabelObserver for |label|, laziliy instantiating one if
-// necessary.  LabelObservers are associated with the label, and will be
-// deallocated upon |label|'s deallocation.
+// necessary. LabelObservers are associated with label but must be kept alive by
+// the caller. |-startObserving| must be called before the |label| is observed.
 + (instancetype)observerForLabel:(UILabel*)label;
 
 // LabelObservers should be created via |+observerForLabel:|.
 - (instancetype)init NS_UNAVAILABLE;
 
+// Starts observing the label. For each call to this function, |-stopObserving|
+// should be called before |label| is deallocated.
+- (void)startObserving;
+
+// Stops observing the label. The label stop being observed once the number of
+// call to this function match the number of call to |-startObserving|.
+- (void)stopObserving;
+
 // Block type that takes a label.  Blocks registered for a label will be called
 // when property values are updated.
 typedef void (^LabelObserverAction)(UILabel* label);
diff --git a/ios/chrome/browser/ui/util/label_observer.mm b/ios/chrome/browser/ui/util/label_observer.mm
index 4fa5c84..06510b0 100644
--- a/ios/chrome/browser/ui/util/label_observer.mm
+++ b/ios/chrome/browser/ui/util/label_observer.mm
@@ -38,9 +38,19 @@
 // property on |_label|.
 @property(nonatomic, assign, getter=isRespondingToKVO) BOOL respondingToKVO;
 
+// The number of times this observer has been asked to observe the label. When
+// reaching zero, the label stops being observed.
+@property(nonatomic, assign) NSInteger observingCount;
+
 // Initializes a LabelObserver that observes |label|.
 - (instancetype)initWithLabel:(UILabel*)label NS_DESIGNATED_INITIALIZER;
 
+// Adds |self| as observer for the |_label|.
+- (void)registerAsObserver;
+
+// Removes |self| as observer for the |_label|.
+- (void)removeObserver;
+
 // Performs all LabelObserverActions in |actions|.
 - (void)performActions:(NSArray*)actions;
 
@@ -62,6 +72,7 @@
 @implementation LabelObserver
 
 @synthesize respondingToKVO = _respondingToKVO;
+@synthesize observingCount = _observingCount;
 
 + (void)initialize {
   if (self == [LabelObserver class]) {
@@ -79,25 +90,14 @@
   if ((self = [super init])) {
     DCHECK(label);
     _label.reset(label);
-    for (NSSet* keySet in @[ styleKeys, layoutKeys, textKeys ]) {
-      for (NSString* key in keySet) {
-        [_label addObserver:self
-                 forKeyPath:key
-                    options:NSKeyValueObservingOptionNew
-                    context:nullptr];
-      }
-    }
     [self resetLabelAttributes];
   }
   return self;
 }
 
 - (void)dealloc {
-  for (NSSet* keySet in @[ styleKeys, layoutKeys, textKeys ]) {
-    for (NSString* key in keySet) {
-      [_label removeObserver:self forKeyPath:key];
-    }
-  }
+  objc_setAssociatedObject(_label, kLabelObserverKey, nil,
+                           OBJC_ASSOCIATION_ASSIGN);
   [super dealloc];
 }
 
@@ -110,12 +110,29 @@
   if (!observer) {
     observer = [[LabelObserver alloc] initWithLabel:label];
     objc_setAssociatedObject(label, kLabelObserverKey, observer,
-                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-    [observer release];
+                             OBJC_ASSOCIATION_ASSIGN);
+    [observer autorelease];
   }
   return observer;
 }
 
+- (void)startObserving {
+  if (self.observingCount == 0) {
+    [self registerAsObserver];
+  }
+  self.observingCount++;
+}
+
+- (void)stopObserving {
+  if (self.observingCount == 0)
+    return;
+
+  self.observingCount--;
+  if (self.observingCount == 0) {
+    [self removeObserver];
+  }
+}
+
 - (void)addStyleChangedAction:(LabelObserverAction)action {
   DCHECK(action);
   if (!_styleActions)
@@ -142,6 +159,25 @@
 
 #pragma mark -
 
+- (void)registerAsObserver {
+  for (NSSet* keySet in @[ styleKeys, layoutKeys, textKeys ]) {
+    for (NSString* key in keySet) {
+      [_label addObserver:self
+               forKeyPath:key
+                  options:NSKeyValueObservingOptionNew
+                  context:nullptr];
+    }
+  }
+}
+
+- (void)removeObserver {
+  for (NSSet* keySet in @[ styleKeys, layoutKeys, textKeys ]) {
+    for (NSString* key in keySet) {
+      [_label removeObserver:self forKeyPath:key];
+    }
+  };
+}
+
 - (void)performActions:(NSArray*)actions {
   for (LabelObserverAction action in actions)
     action(_label);
diff --git a/ios/chrome/browser/ui/util/label_observer_unittest.mm b/ios/chrome/browser/ui/util/label_observer_unittest.mm
index 56119f6..ea86334 100644
--- a/ios/chrome/browser/ui/util/label_observer_unittest.mm
+++ b/ios/chrome/browser/ui/util/label_observer_unittest.mm
@@ -17,12 +17,17 @@
  protected:
   void SetUp() override {
     label_.reset([[UILabel alloc] initWithFrame:CGRectZero]);
+    observer_.reset([[LabelObserver observerForLabel:label_.get()] retain]);
+    [observer_ startObserving];
   }
 
+  ~LabelObserverTest() override { [observer_ stopObserving]; }
+
   UILabel* label() { return label_.get(); }
-  LabelObserver* observer() { return [LabelObserver observerForLabel:label()]; }
+  LabelObserver* observer() { return observer_.get(); }
 
   base::scoped_nsobject<UILabel> label_;
+  base::scoped_nsobject<LabelObserver> observer_;
 };
 
 // Tests that all types of LabelObserverActions are successfully called.
diff --git a/ios/chrome/browser/ui/webui/BUILD.gn b/ios/chrome/browser/ui/webui/BUILD.gn
index 2838f39..3298cd7 100644
--- a/ios/chrome/browser/ui/webui/BUILD.gn
+++ b/ios/chrome/browser/ui/webui/BUILD.gn
@@ -56,6 +56,7 @@
 }
 
 source_set("webui_internal") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "chrome_web_ui_ios_controller_factory.h",
     "chrome_web_ui_ios_controller_factory.mm",
diff --git a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
index 4e181cd..16672e0 100644
--- a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
+++ b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
@@ -23,6 +23,10 @@
 #include "ios/chrome/browser/ui/webui/version_ui.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 using web::WebUIIOS;
 using web::WebUIIOSController;
 
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 8d13fe4..e50fb2a 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -168,6 +168,7 @@
 }
 
 source_set("web_internal") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "auto_reload_bridge.h",
     "auto_reload_bridge.mm",
diff --git a/ios/chrome/browser/web/auto_reload_bridge.mm b/ios/chrome/browser/web/auto_reload_bridge.mm
index 1d968f2..e8a48cf4 100644
--- a/ios/chrome/browser/web/auto_reload_bridge.mm
+++ b/ios/chrome/browser/web/auto_reload_bridge.mm
@@ -6,19 +6,21 @@
 
 #include <memory>
 
-#include "base/ios/weak_nsobject.h"
-#include "base/mac/scoped_nsobject.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/web/public/navigation_manager.h"
 #include "net/base/network_change_notifier.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 class NetworkChangeObserverBridge;
 }  // namespace
 
 @interface AutoReloadBridge () {
-  base::WeakNSObject<Tab> _tab;
-  base::scoped_nsobject<AutoReloadController> _controller;
+  __weak Tab* _tab;
+  AutoReloadController* _controller;
   std::unique_ptr<NetworkChangeObserverBridge> _networkBridge;
 }
 
@@ -44,7 +46,7 @@
   }
 
  private:
-  AutoReloadBridge* bridge_;
+  __weak AutoReloadBridge* bridge_;
 };
 
 }  // namespace
@@ -55,9 +57,9 @@
   DCHECK(tab);
   if ((self = [super init])) {
     BOOL online = !net::NetworkChangeNotifier::IsOffline();
-    _tab.reset(tab);
-    _controller.reset([[AutoReloadController alloc] initWithDelegate:self
-                                                        onlineStatus:online]);
+    _tab = tab;
+    _controller = [[AutoReloadController alloc] initWithDelegate:self
+                                                    onlineStatus:online];
     _networkBridge.reset(new NetworkChangeObserverBridge(self));
   }
   return self;
diff --git a/ios/chrome/browser/web/auto_reload_controller.mm b/ios/chrome/browser/web/auto_reload_controller.mm
index 73f0453..2e64ca9 100644
--- a/ios/chrome/browser/web/auto_reload_controller.mm
+++ b/ios/chrome/browser/web/auto_reload_controller.mm
@@ -6,11 +6,13 @@
 
 #include <memory>
 
-#include "base/ios/weak_nsobject.h"
 #include "base/mac/bind_objc_block.h"
-#include "base/mac/scoped_nsobject.h"
 #include "base/timer/timer.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 base::TimeDelta GetAutoReloadTime(size_t reload_count) {
@@ -29,7 +31,7 @@
   int _reloadCount;
   BOOL _shouldReload;
   BOOL _online;
-  id<AutoReloadDelegate> _delegate;
+  __weak id<AutoReloadDelegate> _delegate;
   std::unique_ptr<base::Timer> _timer;
 }
 
@@ -102,11 +104,10 @@
 }
 
 - (void)startTimer {
-  base::WeakNSObject<AutoReloadController> weakSelf(self);
+  __weak AutoReloadController* weakSelf = self;
   base::TimeDelta delay = GetAutoReloadTime(_reloadCount);
-  _timer->Start(FROM_HERE, delay, base::BindBlock(^{
-                  base::scoped_nsobject<AutoReloadController> strongSelf(
-                      [weakSelf retain]);
+  _timer->Start(FROM_HERE, delay, base::BindBlockArc(^{
+                  AutoReloadController* strongSelf = weakSelf;
                   // self owns the timer owns this closure, so self must outlive
                   // this closure.
                   DCHECK(strongSelf);
diff --git a/ios/chrome/browser/web/blocked_popup_tab_helper.mm b/ios/chrome/browser/web/blocked_popup_tab_helper.mm
index 7595d28e..e3bd545 100644
--- a/ios/chrome/browser/web/blocked_popup_tab_helper.mm
+++ b/ios/chrome/browser/web/blocked_popup_tab_helper.mm
@@ -27,6 +27,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/image/image.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 DEFINE_WEB_STATE_USER_DATA_KEY(BlockedPopupTabHelper);
 
 namespace {
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm
index bc8433e..0c9883b 100644
--- a/ios/chrome/browser/web/chrome_web_client.mm
+++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -34,6 +34,10 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 // Returns an autoreleased string containing the JavaScript loaded from a
 // bundled resource file with the given name (excluding extension).
diff --git a/ios/chrome/browser/web/error_page_content.mm b/ios/chrome/browser/web/error_page_content.mm
index 0fe4543..754576d 100644
--- a/ios/chrome/browser/web/error_page_content.mm
+++ b/ios/chrome/browser/web/error_page_content.mm
@@ -6,12 +6,15 @@
 
 #include <memory>
 
-#import "base/mac/scoped_nsobject.h"
 #import "ios/chrome/browser/web/error_page_generator.h"
 #include "ios/web/public/referrer.h"
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 @implementation ErrorPageContent
 
 #pragma mark -
@@ -35,13 +38,13 @@
               isPost:(BOOL)isPost
          isIncognito:(BOOL)isIncognito {
   ErrorPageGenerator* generator =
-      [[[ErrorPageGenerator alloc] initWithError:error
-                                          isPost:isPost
-                                     isIncognito:isIncognito] autorelease];
+      [[ErrorPageGenerator alloc] initWithError:error
+                                         isPost:isPost
+                                    isIncognito:isIncognito];
 
-  base::scoped_nsobject<StaticHtmlViewController> HTMLViewController(
+  StaticHtmlViewController* HTMLViewController =
       [[StaticHtmlViewController alloc] initWithGenerator:generator
-                                             browserState:browserState]);
+                                             browserState:browserState];
   return [super initWithLoader:loader
       staticHTMLViewController:HTMLViewController
                            URL:url];
diff --git a/ios/chrome/browser/web/error_page_generator.mm b/ios/chrome/browser/web/error_page_generator.mm
index 239c3cb..473bddb 100644
--- a/ios/chrome/browser/web/error_page_generator.mm
+++ b/ios/chrome/browser/web/error_page_generator.mm
@@ -6,7 +6,6 @@
 
 #import "base/ios/ns_error_util.h"
 #include "base/logging.h"
-#import "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/values.h"
 #include "components/error_page/common/error_page_params.h"
@@ -19,9 +18,13 @@
 #include "ui/base/webui/jstemplate_builder.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 @implementation ErrorPageGenerator {
   // Stores the HTML generated from the NSError in the initializer.
-  base::scoped_nsobject<NSString> html_;
+  NSString* _HTML;
 }
 
 - (instancetype)initWithError:(NSError*)error
@@ -60,7 +63,7 @@
       NOTREACHED() << "unable to load template. ID: " << IDR_NET_ERROR_HTML;
     std::string errorHTML = webui::GetTemplatesHtml(
         templateHTML, &errorStrings, "t" /* IDR_NET_ERROR_HTML root id */);
-    html_.reset([base::SysUTF8ToNSString(errorHTML) retain]);
+    _HTML = base::SysUTF8ToNSString(errorHTML);
   }
   return self;
 }
@@ -68,7 +71,7 @@
 #pragma mark - HtmlGenerator
 
 - (void)generateHtml:(HtmlCallback)callback {
-  callback(html_.get());
+  callback(_HTML);
 }
 
 @end
diff --git a/ios/chrome/browser/web/external_app_launcher.mm b/ios/chrome/browser/web/external_app_launcher.mm
index 75c0136..9489a55 100644
--- a/ios/chrome/browser/web/external_app_launcher.mm
+++ b/ios/chrome/browser/web/external_app_launcher.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/web/external_app_launcher.h"
 
 #include "base/ios/ios_util.h"
-#include "base/ios/weak_nsobject.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/sys_string_conversions.h"
@@ -17,6 +16,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 typedef void (^AlertHandler)(UIAlertAction* action);
@@ -27,11 +30,11 @@
   static dispatch_once_t once;
   dispatch_once(&once, ^{
     schemes =
-        [[NSSet setWithObjects:@"itms", @"itmss", @"itms-apps", @"itms-appss",
-                               // There's no evidence that itms-bookss is
-                               // actually supported, but over-inclusion
-                               // costs less than under-inclusion.
-                               @"itms-books", @"itms-bookss", nil] retain];
+        [NSSet setWithObjects:@"itms", @"itmss", @"itms-apps", @"itms-appss",
+                              // There's no evidence that itms-bookss is
+                              // actually supported, but over-inclusion
+                              // costs less than under-inclusion.
+                              @"itms-books", @"itms-bookss", nil];
   });
   return schemes;
 }
diff --git a/ios/chrome/browser/web/print_observer.mm b/ios/chrome/browser/web/print_observer.mm
index 0be1238..c883008 100644
--- a/ios/chrome/browser/web/print_observer.mm
+++ b/ios/chrome/browser/web/print_observer.mm
@@ -6,13 +6,16 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#import "base/mac/scoped_nsobject.h"
 #include "base/values.h"
 #import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h"
 #import "ios/chrome/browser/ui/commands/generic_chrome_command.h"
 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
 #import "ios/web/public/web_state/web_state.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 // Prefix for print JavaScript command.
 const char kPrintCommandPrefix[] = "print";
@@ -36,8 +39,8 @@
 bool PrintObserver::OnPrintCommand(const base::DictionaryValue&,
                                    const GURL&,
                                    bool) {
-  base::scoped_nsobject<GenericChromeCommand> print_command(
-      [[GenericChromeCommand alloc] initWithTag:IDC_PRINT]);
+  GenericChromeCommand* print_command =
+      [[GenericChromeCommand alloc] initWithTag:IDC_PRINT];
   [web_state()->GetView() chromeExecuteCommand:print_command];
   return true;
 }
diff --git a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm
index 05ffac8..d439a85 100644
--- a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_coordinator.mm
@@ -61,7 +61,7 @@
   [dispatcher startDispatchingToTarget:self
                            forSelector:@selector(hideFindInPage)];
 
-  _mediator = [[FindInPageMediator alloc]
+  self.mediator = [[FindInPageMediator alloc]
       initWithWebStateList:(&self.browser->web_state_list())provider:self
                 dispatcher:static_cast<id>(dispatcher)];
   [dispatcher startDispatchingToTarget:self.mediator
@@ -76,6 +76,7 @@
   CommandDispatcher* dispatcher = self.browser->dispatcher();
   [dispatcher stopDispatchingToTarget:self];
   [dispatcher stopDispatchingToTarget:self.mediator];
+  self.mediator = nil;
 }
 
 - (void)start {
diff --git a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm
index 645e739..4f1be95 100644
--- a/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm
+++ b/ios/clean/chrome/browser/ui/find_in_page/find_in_page_mediator.mm
@@ -16,6 +16,10 @@
 #import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h"
 #include "ios/web/public/web_state/web_state.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 @interface FindInPageMediator ()<FindInPageSearchCommands,
                                  WebStateListObserving>
 
diff --git a/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm b/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm
index 7cf4c32..2880d51 100644
--- a/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/omnibox/location_bar_coordinator.mm
@@ -36,20 +36,21 @@
 
   Browser* browser = self.browser;
 
-  _mediator = [[LocationBarMediator alloc]
+  self.mediator = [[LocationBarMediator alloc]
       initWithWebStateList:&(browser->web_state_list())];
   std::unique_ptr<LocationBarController> locationBar =
       base::MakeUnique<LocationBarControllerImpl>(
           self.viewController.omnibox, browser->browser_state(),
           nil /* PreloadProvider */, nil /* OmniboxPopupPositioner */,
-          _mediator);
-  [_mediator setLocationBar:std::move(locationBar)];
+          self.mediator);
+  [self.mediator setLocationBar:std::move(locationBar)];
   [super start];
 }
 
 - (void)stop {
   [super stop];
   self.viewController = nil;
+  self.mediator = nil;
 }
 
 @end
diff --git a/storage/BUILD.gn b/storage/BUILD.gn
new file mode 100644
index 0000000..d6208ef
--- /dev/null
+++ b/storage/BUILD.gn
@@ -0,0 +1,11 @@
+# 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.
+import("//testing/test.gni")
+
+test("storage_unittests") {
+  deps = [
+    "//storage/browser:unittests",
+    "//storage/common:unittests",
+  ]
+}
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn
index b4658f9..905c773 100644
--- a/storage/browser/BUILD.gn
+++ b/storage/browser/BUILD.gn
@@ -222,7 +222,9 @@
   ]
 }
 
-test("storage_unittests") {
+source_set("unittests") {
+  testonly = true
+
   sources = [
     # This target is in the process of being populated. See
     # http://crbug.com/653751
diff --git a/storage/common/BUILD.gn b/storage/common/BUILD.gn
index 1f15f48..bf662ab 100644
--- a/storage/common/BUILD.gn
+++ b/storage/common/BUILD.gn
@@ -47,3 +47,21 @@
     "//url",
   ]
 }
+
+source_set("unittests") {
+  testonly = true
+
+  sources = [
+    "database/database_connections_unittest.cc",
+    "database/database_identifier_unittest.cc",
+    "fileapi/file_system_util_unittest.cc",
+  ]
+
+  deps = [
+    ":common",
+    "//base/test:run_all_unittests",
+    "//base/test:test_support",
+    "//testing/gtest",
+    "//url",
+  ]
+}
diff --git a/content/common/database_connections_unittest.cc b/storage/common/database/database_connections_unittest.cc
similarity index 100%
rename from content/common/database_connections_unittest.cc
rename to storage/common/database/database_connections_unittest.cc
diff --git a/content/common/database_identifier_unittest.cc b/storage/common/database/database_identifier_unittest.cc
similarity index 100%
rename from content/common/database_identifier_unittest.cc
rename to storage/common/database/database_identifier_unittest.cc
diff --git a/content/common/fileapi/file_system_util_unittest.cc b/storage/common/fileapi/file_system_util_unittest.cc
similarity index 100%
rename from content/common/fileapi/file_system_util_unittest.cc
rename to storage/common/fileapi/file_system_util_unittest.cc
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 52d09ec..e20726a 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -868,7 +868,7 @@
     "type": "console_test_launcher",
   },
   "storage_unittests": {
-    "label": "//storage/browser:storage_unittests",
+    "label": "//storage:storage_unittests",
     "type": "console_test_launcher",
   },
   "swiftshader_unittests": {
diff --git a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-geometry-logging.js b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-geometry-logging.js
index 53937e8..e2ce067 100644
--- a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-geometry-logging.js
+++ b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-geometry-logging.js
@@ -20,7 +20,7 @@
         testRunner.dumpAsText();
     }
 
-    paintWorklet.import('resources/paint-logging-green.js').then(function() {
+    paintWorklet.addModule('resources/paint-logging-green.js').then(function() {
         tests.reduce(function(chain, obj) {
             return chain.then(function() {
                 console.log('The worklet should log: \'width: ' + obj.expected.width + ', height: ' + obj.expected.height + '\'');
diff --git a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js
index 87e1928..f139834 100644
--- a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js
+++ b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-invalidation-logging.js
@@ -32,7 +32,7 @@
         }
     `;
 
-    paintWorklet.import(URL.createObjectURL(new Blob([workletCode]))).then(function() {
+    paintWorklet.addModule(URL.createObjectURL(new Blob([workletCode]))).then(function() {
         for (let i = 0; i < tests.length; i++) {
             tests[i].paintName = 'paint-' + i;
             registerTest(imageType, tests[i]);
diff --git a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-helper.js b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-helper.js
index d5bd770..e7aec3d 100644
--- a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-helper.js
+++ b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-helper.js
@@ -19,7 +19,7 @@
                 console.log('The worklet should not throw an error.');
             }
             var blob = new Blob([obj.script], {type: 'text/javascript'});
-            return paintWorklet.import(URL.createObjectURL(blob));
+            return paintWorklet.addModule(URL.createObjectURL(blob));
         });
     }, Promise.resolve()).then(function() {
         if (window.testRunner) {
diff --git a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js
index 323b6a3..bb1dfef 100644
--- a/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js
+++ b/third_party/WebKit/LayoutTests/csspaint/resources/test-runner-paint-worklet.js
@@ -10,7 +10,7 @@
     }
 
     var blob = new Blob([code]);
-    paintWorklet.import(URL.createObjectURL(blob)).then(function() {
+    paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
         runAfterLayoutAndPaint(function() {
             if (window.testRunner) {
                 testRunner.notifyDone();
diff --git a/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html b/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html
index 2113285..7bb5bcd 100644
--- a/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html
+++ b/third_party/WebKit/LayoutTests/csspaint/valid-image-after-load.html
@@ -28,7 +28,7 @@
 }
 
 var blob = new Blob([document.getElementById('code').textContent]);
-paintWorklet.import(URL.createObjectURL(blob)).then(function() {
+paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
     var el = document.getElementById('output');
     el.style.backgroundImage = 'paint(green)';
     runAfterLayoutAndPaint(function() {
diff --git a/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html b/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html
index ff8b32a..3a6eacf 100644
--- a/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html
+++ b/third_party/WebKit/LayoutTests/csspaint/valid-image-before-load.html
@@ -31,7 +31,7 @@
 el.style.backgroundImage = 'paint(green)';
 
 var blob = new Blob([document.getElementById('code').textContent]);
-paintWorklet.import(URL.createObjectURL(blob)).then(function() {
+paintWorklet.addModule(URL.createObjectURL(blob)).then(function() {
     runAfterLayoutAndPaint(function() {
         if (window.testRunner) {
             testRunner.notifyDone();
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row-expected.txt b/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row-expected.txt
index 29f48bc..4a2670a 100644
--- a/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row-expected.txt
@@ -1,6 +1,6 @@
-crbug.com/637811: There should be a green box below.
+crbug.com/637811: There should be no box below.
 
 PASS
-crbug.com/637811: There should be a green box below.
+crbug.com/637811: There should be no box below.
 
 PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row.html b/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row.html
index f0873da..3f862ae 100644
--- a/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row.html
+++ b/third_party/WebKit/LayoutTests/fast/table/percent-height-content-in-percent-height-cell-with-height-from-row.html
@@ -10,25 +10,25 @@
     width: 100%;
 }
 </style>
-<p>crbug.com/637811: There should be a green box below.</p>
+<p>crbug.com/637811: There should be no box below.</p>
 <table style="width: 100px;">
     <tr>
         <td>
             <div style="height: 50px; width: 50px;"></div>
         </td>
         <td class="full">
-            <table id="test" class="full" data-expected-height=50 data-expected-width=40></table>
+            <table id="test" class="full" data-expected-height=0 data-expected-width=40></table>
         </td>
     </tr>
 </table>
-<p>crbug.com/637811: There should be a green box below.</p>
+<p>crbug.com/637811: There should be no box below.</p>
 <table style="width: 100px;">
     <tr>
         <td>
             <div style="height: 50px; width: 50px;"></div>
         </td>
         <td class="full">
-            <div id="test" class="full" data-expected-height=50 data-expected-width=40></div>
+            <div id="test" class="full" data-expected-height=0 data-expected-width=40></div>
         </td>
     </tr>
 </table>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked.html
index ec11a1a..de879a3 100644
--- a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked.html
+++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/worklet-import-blocked.html
@@ -10,9 +10,9 @@
 <script>
     promise_test(function() {
 
-        return paintWorklet.import('/resources/worklet.js').then(
+        return paintWorklet.addModule('/resources/worklet.js').then(
             function(undefined_arg) {
-                assert_unreached('import should fail.')
+                assert_unreached('addModule should fail.')
             },
             function(error) {
                 assert_equals(error.name, 'NetworkError', 'error should be a NetworkError.');
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/import-on-detached-iframe.html b/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/import-on-detached-iframe.html
index bbba102..de70b50 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/import-on-detached-iframe.html
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/chromium/import-on-detached-iframe.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>Worklet: import() on a detached iframe</title>
+<title>Worklet: addModule() on a detached iframe</title>
 <body>
 </body>
 <script src="../../resources/testharness.js"></script>
@@ -18,7 +18,7 @@
 }
 
 // This test should be in chromium/ because the spec does not define behavior in
-// the case where import() is called from a detached frame.
+// the case where addModule() is called from a detached frame.
 promise_test(t => {
   const kFrameUrl = 'resources/blank.html';
   const kScriptUrl = 'resources/empty-worklet-script.js';
@@ -27,10 +27,10 @@
     .then(frame => {
         let worklet = frame.contentWindow.paintWorklet;
         frame.remove();
-        return worklet.import(kScriptUrl);
+        return worklet.addModule(kScriptUrl);
       })
-    .then(() => assert_unreached('import() should fail.'))
+    .then(() => assert_unreached('addModule() should fail.'))
     .catch(e => assert_equals(e.name, 'InvalidStateError', e));
-}, 'import() on a detached iframe should be rejected.');
+}, 'addModule() on a detached iframe should be rejected.');
 
 </script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js b/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js
index ea341b8..2ce11fe 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/resources/import-tests.js
@@ -6,38 +6,38 @@
     const path = opt_path || '';
 
     promise_test(function() {
-        return worklet.import(path + 'resources/empty-worklet-script.js').then(function(undefined_arg) {
+        return worklet.addModule(path + 'resources/empty-worklet-script.js').then(function(undefined_arg) {
             assert_equals(undefined_arg, undefined, 'Promise should resolve with no arguments.');
         });
     }, 'Importing a script resolves the given promise.');
 
     promise_test(function() {
         return Promise.all([
-            worklet.import(path + 'resources/empty-worklet-script.js?1'),
-            worklet.import(path + 'resources/empty-worklet-script.js?2'),
-            worklet.import(path + 'resources/empty-worklet-script.js?3')
+            worklet.addModule(path + 'resources/empty-worklet-script.js?1'),
+            worklet.addModule(path + 'resources/empty-worklet-script.js?2'),
+            worklet.addModule(path + 'resources/empty-worklet-script.js?3')
         ]).then(function(undefined_args) {
             assert_array_equals(undefined_args, [undefined, undefined, undefined], 'Promise should resolve with no arguments.');
         });
     }, 'Importing scripts resolves all the given promises.');
 
     promise_test(function() {
-        return worklet.import(path + 'resources/throwing-worklet-script.js').then(function(undefined_arg) {
+        return worklet.addModule(path + 'resources/throwing-worklet-script.js').then(function(undefined_arg) {
             assert_equals(undefined_arg, undefined, 'Promise should resolve with no arguments.');
         });
     }, 'Importing a script which throws should still resolve the given promise.');
 
     promise_test(function() {
-        return worklet.import(path + 'non-existant-worklet-script.js').then(function() {
-            assert_unreached('import should fail.');
+        return worklet.addModule(path + 'non-existant-worklet-script.js').then(function() {
+            assert_unreached('addModule should fail.');
         }).catch(function(error) {
             assert_equals(error.name, 'NetworkError', 'error should be a NetworkError.');
         });
     }, 'Importing a non-existant script rejects the given promise with a NetworkError.');
 
     promise_test(function() {
-        return worklet.import('http://invalid:123$').then(function() {
-            assert_unreached('import should fail.');
+        return worklet.addModule('http://invalid:123$').then(function() {
+            assert_unreached('addModule should fail.');
         }).catch(function(error) {
             assert_equals(error.name, 'SyntaxError', 'error should be a SyntaxError.');
         });
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet.html b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet.html
index 31ecd2c..7b4b11e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet.html
+++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet.html
@@ -7,7 +7,7 @@
         testRunner.dumpAsText();
     }
 
-    paintWorklet.import('resources/global-interface-listing-worklet.js').then(function() {
+    paintWorklet.addModule('resources/global-interface-listing-worklet.js').then(function() {
         if (window.testRunner) {
             testRunner.notifyDone();
         }
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-on-paint-worklet.html b/third_party/WebKit/LayoutTests/inspector/console/console-on-paint-worklet.html
index 3565c06..7cbdd11 100644
--- a/third_party/WebKit/LayoutTests/inspector/console/console-on-paint-worklet.html
+++ b/third_party/WebKit/LayoutTests/inspector/console/console-on-paint-worklet.html
@@ -5,7 +5,7 @@
 <script>
 function importWorklet()
 {
-    paintWorklet.import('console-worklet-script.js');
+    paintWorklet.addModule('console-worklet-script.js');
 }
 
 function test()
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
index b439824..d308738 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.txt
index dc6f5f4..e7d6628 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug131020-3-expected.txt
@@ -1,4 +1,4 @@
-layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 2362
+layer at (0,0) size 800x600 clip at (0,0) size 785x600 scrollHeight 2665
   LayoutView at (0,0) size 800x600
 layer at (0,0) size 785x2362 backgroundClip at (0,0) size 785x600 clip at (0,0) size 785x600
   LayoutBlockFlow {HTML} at (0,0) size 785x2362
@@ -167,17 +167,17 @@
               LayoutTable {TABLE} at (3,3) size 734x424 [bgcolor=#FFA500] [border: (1px outset #808080)]
                 LayoutTableSection {TBODY} at (1,1) size 732x422
                   LayoutTableRow {TR} at (0,0) size 732x422
-                    LayoutTableCell {TD} at (0,0) size 732x422 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
+                    LayoutTableCell {TD} at (0,0) size 732x742 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
                       LayoutBlockFlow (anonymous) at (1,1) size 730x20
                         LayoutText {#text} at (0,0) size 8x19
                           text run at (0,0) width 8: "x"
-                      LayoutTable {TABLE} at (1,21) size 730x100 [bgcolor=#FFFF00]
-                        LayoutTableSection {TBODY} at (0,0) size 730x100
-                          LayoutTableRow {TR} at (0,0) size 730x100
-                            LayoutTableCell {TD} at (0,40) size 730x20 [r=0 c=0 rs=1 cs=1]
+                      LayoutTable {TABLE} at (1,21) size 730x420 [bgcolor=#FFFF00]
+                        LayoutTableSection {TBODY} at (0,0) size 730x420
+                          LayoutTableRow {TR} at (0,0) size 730x420
+                            LayoutTableCell {TD} at (0,200) size 730x20 [r=0 c=0 rs=1 cs=1]
                               LayoutText {#text} at (0,0) size 4x19
                                 text run at (0,0) width 4: " "
-                      LayoutTable {TABLE} at (1,121) size 730x300
+                      LayoutTable {TABLE} at (1,441) size 730x300
                         LayoutTableSection {TBODY} at (0,0) size 730x300
                           LayoutTableRow {TR} at (0,0) size 730x300
                             LayoutTableCell {TD} at (0,0) size 730x300 [bgcolor=#E0FFFF] [r=0 c=0 rs=1 cs=1]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
index f939935..9cc4e45 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.txt
index 5a3c5c2..81aa1c2 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/tables/mozilla_expected_failures/bugs/bug32205-4-expected.txt
@@ -27,15 +27,15 @@
                 LayoutBlockFlow {IMG} at (1,1) size 10x200
                 LayoutText {#text} at (11,186) size 50x19
                   text run at (11,186) width 50: "Cell A1"
-              LayoutTableCell {TD} at (62,0) size 63x207 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
-                LayoutTable {TABLE} at (1,1) size 61x205 [border: (2px outset #808080)]
-                  LayoutTableSection {TBODY} at (2,2) size 57x201
+              LayoutTableCell {TD} at (62,70) size 63x66 [border: (1px inset #808080)] [r=0 c=1 rs=1 cs=1]
+                LayoutTable {TABLE} at (1,1) size 61x64 [border: (2px outset #808080)]
+                  LayoutTableSection {TBODY} at (2,2) size 57x60
                     LayoutTableRow {TR} at (0,2) size 57x30
                       LayoutTableCell {TD} at (2,5) size 53x24 [border: (1px inset #808080)] [r=0 c=0 rs=1 cs=1]
                         LayoutText {#text} at (2,2) size 49x19
                           text run at (2,2) width 49: "Cell B1"
-                    LayoutTableRow {TR} at (0,34) size 57x165
-                      LayoutTableCell {TD} at (2,104) size 53x24 [bgcolor=#99CC99] [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
+                    LayoutTableRow {TR} at (0,34) size 57x24
+                      LayoutTableCell {TD} at (2,34) size 53x24 [bgcolor=#99CC99] [border: (1px inset #808080)] [r=1 c=0 rs=1 cs=1]
                         LayoutText {#text} at (2,2) size 49x19
                           text run at (2,2) width 49: "Cell B2"
 layer at (10,158) size 10x200 clip at (11,159) size 8x198 scrollWidth 17
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
index 708e772..93f4660 100644
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png b/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
index f3a73cb..d884617 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png b/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
index c3dc1b5..910e63c 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/mac/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png b/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
index 4909f7c..d02fbd85 100644
--- a/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug131020-3-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png b/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
index 1bb85e1..7b475d1 100644
--- a/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/tables/mozilla_expected_failures/bugs/bug32205-4-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
index 65655ea..dc46af4 100644
--- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -8576,8 +8576,8 @@
     setter onmessage
 interface Worklet
     attribute @@toStringTag
+    method addModule
     method constructor
-    method import
 interface WritableStream
     getter locked
     method abort
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index b4001d3..e29d2d3 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -8584,8 +8584,8 @@
     setter onmessage
 interface Worklet
     attribute @@toStringTag
+    method addModule
     method constructor
-    method import
 interface WritableStream
     getter locked
     method abort
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
index e4f01b6..4b21ebd 100644
--- a/third_party/WebKit/Source/core/dom/Document.cpp
+++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -4038,14 +4038,12 @@
   SetAnnotatedRegionsDirty(false);
 }
 
-bool Document::SetFocusedElement(Element* prp_new_focused_element,
+bool Document::SetFocusedElement(Element* new_focused_element,
                                  const FocusParams& params) {
   DCHECK(!lifecycle_.InDetach());
 
   clear_focused_element_timer_.Stop();
 
-  Element* new_focused_element = prp_new_focused_element;
-
   // Make sure newFocusedNode is actually in this document
   if (new_focused_element && (new_focused_element->GetDocument() != this))
     return true;
@@ -6371,7 +6369,7 @@
 }
 
 void Document::DidAssociateFormControl(Element* element) {
-  if (!GetFrame() || !GetFrame()->GetPage() || !LoadEventFinished())
+  if (!GetFrame() || !GetFrame()->GetPage() || !HasFinishedParsing())
     return;
 
   // We add a slight delay because this could be called rapidly.
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index c38ab51..cd529ad 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -787,8 +787,8 @@
   return layout_selection_->HasPendingSelection();
 }
 
-void FrameSelection::CommitAppearanceIfNeeded(LayoutView& layout_view) {
-  return layout_selection_->Commit(layout_view);
+void FrameSelection::CommitAppearanceIfNeeded() {
+  return layout_selection_->Commit();
 }
 
 void FrameSelection::DidLayout() {
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h
index befd406..2017153 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.h
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -185,7 +185,7 @@
 
   void DidLayout();
   bool NeedsLayoutSelectionUpdate() const;
-  void CommitAppearanceIfNeeded(LayoutView&);
+  void CommitAppearanceIfNeeded();
   void SetCaretVisible(bool caret_is_visible);
   void ScheduleVisualUpdate() const;
   void ScheduleVisualUpdateForPaintInvalidationIfNeeded() const;
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
index 772eaad..718f97a 100644
--- a/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/LayoutSelection.cpp
@@ -45,23 +45,6 @@
   return frame_selection_->ComputeVisibleSelectionInDOMTree();
 }
 
-static bool IsSelectionInDocument(
-    const VisibleSelectionInFlatTree& visible_selection,
-    const Document& document) {
-  const PositionInFlatTree& start = visible_selection.Start();
-  if (start.IsNotNull() &&
-      (!start.IsConnected() || start.GetDocument() != document))
-    return false;
-  const PositionInFlatTree& end = visible_selection.end();
-  if (end.IsNotNull() && (!end.IsConnected() || end.GetDocument() != document))
-    return false;
-  const PositionInFlatTree extent = visible_selection.Extent();
-  if (extent.IsNotNull() &&
-      (!extent.IsConnected() || extent.GetDocument() != document))
-    return false;
-  return true;
-}
-
 SelectionInFlatTree LayoutSelection::CalcVisibleSelection(
     const VisibleSelectionInFlatTree& original_selection) const {
   const PositionInFlatTree& start = original_selection.Start();
@@ -324,7 +307,7 @@
 }
 
 void LayoutSelection::SelectionStartEnd(int& start_pos, int& end_pos) {
-  Commit(*frame_selection_->GetDocument().GetLayoutView());
+  Commit();
   start_pos = selection_start_pos_;
   end_pos = selection_end_pos_;
 }
@@ -346,19 +329,14 @@
     force_hide_ = false;
 }
 
-void LayoutSelection::Commit(LayoutView& layout_view) {
+void LayoutSelection::Commit() {
   if (!HasPendingSelection())
     return;
-  DCHECK(!layout_view.NeedsLayout());
   has_pending_selection_ = false;
 
   const VisibleSelectionInFlatTree& original_selection =
       frame_selection_->ComputeVisibleSelectionInFlatTree();
 
-  // Skip if pending VisibilePositions became invalid before we reach here.
-  if (!IsSelectionInDocument(original_selection, layout_view.GetDocument()))
-    return;
-
   // Construct a new VisibleSolution, since visibleSelection() is not
   // necessarily valid, and the following steps assume a valid selection. See
   // <https://bugs.webkit.org/show_bug.cgi?id=69563> and
@@ -397,8 +375,7 @@
   LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject();
   if (!start_layout_object || !end_layout_object)
     return;
-  DCHECK(layout_view == start_layout_object->View());
-  DCHECK(layout_view == end_layout_object->View());
+  DCHECK(start_layout_object->View() == end_layout_object->View());
   SetSelection(start_layout_object, start_pos.ComputeEditingOffset(),
                end_layout_object, end_pos.ComputeEditingOffset());
 }
@@ -429,7 +406,7 @@
   typedef HashSet<const LayoutBlock*> VisitedContainingBlockSet;
   VisitedContainingBlockSet visited_containing_blocks;
 
-  Commit(*frame_selection_->GetDocument().GetLayoutView());
+  Commit();
   LayoutObject* os = selection_start_;
   LayoutObject* stop =
       LayoutObjectAfterPosition(selection_end_, selection_end_pos_);
diff --git a/third_party/WebKit/Source/core/editing/LayoutSelection.h b/third_party/WebKit/Source/core/editing/LayoutSelection.h
index 3b64034..ac5b3c0 100644
--- a/third_party/WebKit/Source/core/editing/LayoutSelection.h
+++ b/third_party/WebKit/Source/core/editing/LayoutSelection.h
@@ -29,7 +29,6 @@
 namespace blink {
 
 class FrameSelection;
-class LayoutView;
 
 class LayoutSelection final : public GarbageCollected<LayoutSelection> {
  public:
@@ -41,7 +40,7 @@
 
   bool HasPendingSelection() const { return has_pending_selection_; }
   void SetHasPendingSelection(PaintHint);
-  void Commit(LayoutView&);
+  void Commit();
 
   IntRect SelectionBounds();
   void InvalidatePaintForSelection();
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
index e977cdb..6a17603 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
@@ -167,7 +167,7 @@
   }
 }
 
-void DocumentMarkerController::RemoveMarkers(
+void DocumentMarkerController::RemoveMarkersInRange(
     const EphemeralRange& range,
     DocumentMarker::MarkerTypes marker_types) {
   DCHECK(!document_->NeedsLayoutTreeUpdate());
@@ -252,15 +252,14 @@
   MarkerLists* dst_markers = markers_.at(dst_node);
 
   bool doc_dirty = false;
-  for (size_t marker_list_index = 0; marker_list_index < src_markers->size();
-       ++marker_list_index) {
-    MarkerList* src_list = src_markers->at(marker_list_index);
+  for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+    MarkerList* src_list = ListForType(src_markers, type);
     if (!src_list)
       continue;
 
-    if (!dst_markers->at(marker_list_index))
-      dst_markers->at(marker_list_index) = new MarkerList;
-    MarkerList* dst_list = dst_markers->at(marker_list_index);
+    if (!ListForType(dst_markers, type))
+      ListForType(dst_markers, type) = new MarkerList;
+    MarkerList* dst_list = ListForType(dst_markers, type);
 
     if (DocumentMarkerListEditor::MoveMarkers(src_list, length, dst_list))
       doc_dirty = true;
@@ -291,17 +290,15 @@
 
   bool doc_dirty = false;
   size_t empty_lists_count = 0;
-  for (size_t marker_list_index = 0;
-       marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-       ++marker_list_index) {
-    Member<MarkerList>& list = (*markers)[marker_list_index];
+  for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+    Member<MarkerList>& list = ListForType(markers, type);
     if (!list || list->IsEmpty()) {
       if (list.Get() && list->IsEmpty())
         list.Clear();
       ++empty_lists_count;
       continue;
     }
-    if (!marker_types.Contains((*list->begin())->GetType()))
+    if (!marker_types.Contains(type))
       continue;
 
     if (DocumentMarkerListEditor::RemoveMarkers(list, start_offset, length))
@@ -335,10 +332,8 @@
   if (!markers)
     return result;
 
-  for (size_t marker_list_index = 0;
-       marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-       ++marker_list_index) {
-    Member<MarkerList>& list = (*markers)[marker_list_index];
+  for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+    Member<MarkerList>& list = ListForType(markers, type);
     if (!list || list->IsEmpty() ||
         !marker_types.Contains((*list->begin())->GetType()))
       continue;
@@ -359,10 +354,8 @@
   DocumentMarkerVector result;
   for (MarkerMap::iterator i = markers_.begin(); i != markers_.end(); ++i) {
     MarkerLists* markers = i->value.Get();
-    for (size_t marker_list_index = 0;
-         marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-         ++marker_list_index) {
-      Member<MarkerList>& list = (*markers)[marker_list_index];
+    for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+      Member<MarkerList>& list = ListForType(markers, type);
       for (size_t j = 0; list.Get() && j < list->size(); ++j)
         result.push_back(list->at(j).Get());
     }
@@ -423,12 +416,9 @@
     if (!node.isConnected())
       continue;
     MarkerLists* markers = node_iterator->value.Get();
-    for (size_t marker_list_index = 0;
-         marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-         ++marker_list_index) {
-      Member<MarkerList>& list = (*markers)[marker_list_index];
-      if (!list || list->IsEmpty() ||
-          (*list->begin())->GetType() != marker_type)
+    for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+      Member<MarkerList>& list = ListForType(markers, type);
+      if (!list || list->IsEmpty() || type != marker_type)
         continue;
       for (unsigned marker_index = 0; marker_index < list->size();
            ++marker_index) {
@@ -514,11 +504,9 @@
     const Node& node = *node_markers.key;
     if (!node.IsTextNode())  // MarkerRemoverPredicate requires a Text node.
       continue;
-    MarkerLists& markers = *node_markers.value;
-    for (size_t marker_list_index = 0;
-         marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-         ++marker_list_index) {
-      Member<MarkerList>& list = markers[marker_list_index];
+    MarkerLists* markers = node_markers.value;
+    for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+      Member<MarkerList>& list = ListForType(markers, type);
       if (!list)
         continue;
       bool removed_markers = false;
@@ -529,8 +517,7 @@
           removed_markers = true;
         }
       }
-      if (removed_markers &&
-          marker_list_index == DocumentMarker::kTextMatchMarkerIndex)
+      if (removed_markers && type == DocumentMarker::kTextMatch)
         InvalidatePaintForTickmarks(node);
     }
   }
@@ -567,17 +554,15 @@
   } else {
     MarkerLists* markers = iterator->value.Get();
 
-    for (size_t marker_list_index = 0;
-         marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-         ++marker_list_index) {
-      Member<MarkerList>& list = (*markers)[marker_list_index];
+    for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+      Member<MarkerList>& list = ListForType(markers, type);
       if (!list || list->IsEmpty()) {
         if (list.Get() && list->IsEmpty())
           list.Clear();
         ++empty_lists_count;
         continue;
       }
-      if (marker_types.Contains((*list->begin())->GetType())) {
+      if (marker_types.Contains(type)) {
         list->clear();
         list.Clear();
         ++empty_lists_count;
@@ -618,12 +603,9 @@
 
     // inner loop: process each marker in the current node
     MarkerLists* markers = i->value.Get();
-    for (size_t marker_list_index = 0;
-         marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-         ++marker_list_index) {
-      Member<MarkerList>& list = (*markers)[marker_list_index];
-      if (!list || list->IsEmpty() ||
-          !marker_types.Contains((*list->begin())->GetType()))
+    for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+      Member<MarkerList>& list = ListForType(markers, type);
+      if (!list || list->IsEmpty() || !marker_types.Contains(type))
         continue;
 
       // cause the node to be redrawn
@@ -707,10 +689,8 @@
     const Node* node = node_iterator->key;
     builder.Append(String::Format("%p", node));
     MarkerLists* markers = markers_.at(node);
-    for (size_t marker_list_index = 0;
-         marker_list_index < DocumentMarker::kMarkerTypeIndexesCount;
-         ++marker_list_index) {
-      Member<MarkerList>& list = (*markers)[marker_list_index];
+    for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) {
+      Member<MarkerList>& list = ListForType(markers, type);
       for (unsigned marker_index = 0; list.Get() && marker_index < list->size();
            ++marker_index) {
         DocumentMarker* marker = list->at(marker_index).Get();
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h
index 06ca1fd2..a5490d1 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h
@@ -77,9 +77,7 @@
   void MoveMarkers(Node* src_node, int length, Node* dst_node);
 
   void PrepareForDestruction();
-  void RemoveMarkers(
-      const EphemeralRange&,
-      DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
+  void RemoveMarkersInRange(const EphemeralRange&, DocumentMarker::MarkerTypes);
   void RemoveMarkers(
       Node*,
       unsigned start_offset,
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
index 7b6148b..9d4938f 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
@@ -278,8 +278,8 @@
 
   // Remove markers that overlap "a"
   marker_range = EphemeralRange(Position(text, 0), Position(text, 1));
-  GetDocument().Markers().RemoveMarkers(marker_range,
-                                        DocumentMarker::AllMarkers());
+  GetDocument().Markers().RemoveMarkersInRange(marker_range,
+                                               DocumentMarker::AllMarkers());
 
   EXPECT_EQ(0u, MarkerController().Markers().size());
 }
@@ -298,8 +298,8 @@
 
   // Remove markers that overlap "b"
   marker_range = EphemeralRange(Position(text, 1), Position(text, 2));
-  GetDocument().Markers().RemoveMarkers(marker_range,
-                                        DocumentMarker::AllMarkers());
+  GetDocument().Markers().RemoveMarkersInRange(marker_range,
+                                               DocumentMarker::AllMarkers());
 
   EXPECT_EQ(0u, MarkerController().Markers().size());
 }
@@ -318,8 +318,8 @@
 
   // Remove markers that overlap "c"
   marker_range = EphemeralRange(Position(text, 2), Position(text, 3));
-  GetDocument().Markers().RemoveMarkers(marker_range,
-                                        DocumentMarker::AllMarkers());
+  GetDocument().Markers().RemoveMarkersInRange(marker_range,
+                                               DocumentMarker::AllMarkers());
 
   EXPECT_EQ(0u, MarkerController().Markers().size());
 }
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp b/third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp
index 001a775..b8a8f14 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/HotModeSpellCheckRequester.cpp
@@ -108,7 +108,7 @@
   const EphemeralRange& current_word =
       CurrentWordIfTypingInPartialWord(*root_editable);
   if (current_word.IsNotNull()) {
-    root_editable->GetDocument().Markers().RemoveMarkers(
+    root_editable->GetDocument().Markers().RemoveMarkersInRange(
         current_word, DocumentMarker::MisspellingMarkers());
     return;
   }
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
index 3878129..484e522 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
@@ -266,7 +266,7 @@
         DocumentMarker::SpellCheckClientMarkers();
     if (processing_request_->IsValid()) {
       Range* checking_range = processing_request_->CheckingRange();
-      GetFrame().GetDocument()->Markers().RemoveMarkers(
+      GetFrame().GetDocument()->Markers().RemoveMarkersInRange(
           EphemeralRange(checking_range), markers);
     }
   }
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
index 2679d87..d2ae2ab 100644
--- a/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
+++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellChecker.cpp
@@ -763,8 +763,8 @@
   // as well. So we need to get the continous range of of marker that contains
   // the word in question, and remove marker on that whole range.
   const EphemeralRange word_range(remove_marker_start, remove_marker_end);
-  document->Markers().RemoveMarkers(word_range,
-                                    DocumentMarker::MisspellingMarkers());
+  document->Markers().RemoveMarkersInRange(
+      word_range, DocumentMarker::MisspellingMarkers());
 }
 
 void SpellChecker::DidEndEditingOnTextField(Element* e) {
@@ -1032,7 +1032,7 @@
   if (range.IsNull())
     return;
 
-  GetFrame().GetDocument()->Markers().RemoveMarkers(range, marker_types);
+  GetFrame().GetDocument()->Markers().RemoveMarkersInRange(range, marker_types);
 }
 
 // TODO(xiaochengh): This function is only used by unit tests. We should move it
diff --git a/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.h b/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.h
index c052494..c4bb493 100644
--- a/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.h
+++ b/third_party/WebKit/Source/core/layout/GridTrackSizingAlgorithm.h
@@ -21,8 +21,6 @@
 class GridTrackSizingAlgorithmStrategy;
 class LayoutGrid;
 
-enum MarginDirection;
-
 enum SizingOperation { kTrackSizing, kIntrinsicSizeComputation };
 
 enum TrackSizeComputationPhase {
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
index 872e197..5705062 100644
--- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1454,6 +1454,7 @@
 }
 
 void LayoutObject::SelectionStartEnd(int& start_pos, int& end_pos) const {
+  DCHECK(!View()->NeedsLayout());
   GetFrame()->Selection().LayoutSelectionStartEnd(start_pos, end_pos);
 }
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index 49cbfa6..2899bc5 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -1114,9 +1114,18 @@
   return extra_logical_height - remaining_extra_logical_height;
 }
 
+bool CellHasExplicitlySpecifiedHeight(const LayoutTableCell& cell) {
+  if (cell.Style()->LogicalHeight().IsFixed())
+    return true;
+  LayoutBlock* cb = cell.ContainingBlock();
+  if (cb->AvailableLogicalHeightForPercentageComputation() == -1)
+    return false;
+  return true;
+}
+
 static bool ShouldFlexCellChild(const LayoutTableCell& cell,
                                 LayoutObject* cell_descendant) {
-  if (!cell.Style()->LogicalHeight().IsSpecified())
+  if (!CellHasExplicitlySpecifiedHeight(cell))
     return false;
   if (cell_descendant->Style()->OverflowY() == EOverflow::kVisible ||
       cell_descendant->Style()->OverflowY() == EOverflow::kHidden)
@@ -1961,7 +1970,7 @@
   // can't hope to match the behavior perfectly, but we'll continue to refine it
   // as we discover new bugs. :)
   bool cell_children_flex = false;
-  bool flex_all_children = cell.Style()->LogicalHeight().IsSpecified() ||
+  bool flex_all_children = CellHasExplicitlySpecifiedHeight(cell) ||
                            (!Table()->Style()->LogicalHeight().IsAuto() &&
                             row_height != cell.LogicalHeight());
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp
index 5121862..343bec1 100644
--- a/third_party/WebKit/Source/core/layout/LayoutView.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -615,7 +615,8 @@
 
 void LayoutView::CommitPendingSelection() {
   TRACE_EVENT0("blink", "LayoutView::commitPendingSelection");
-  frame_view_->GetFrame().Selection().CommitAppearanceIfNeeded(*this);
+  DCHECK(!NeedsLayout());
+  frame_view_->GetFrame().Selection().CommitAppearanceIfNeeded();
 }
 
 bool LayoutView::ShouldUsePrintingLayout() const {
diff --git a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
index 614317a..240f59d 100644
--- a/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
+++ b/third_party/WebKit/Source/core/loader/ThreadableLoaderTest.cpp
@@ -181,7 +181,7 @@
       CrossOriginRequestPolicy cross_origin_request_policy) override {
     std::unique_ptr<WaitableEvent> completion_event =
         WTF::MakeUnique<WaitableEvent>();
-    PostTaskToWorkerGlobalScope(
+    worker_loading_task_runner_->PostTask(
         BLINK_FROM_HERE,
         CrossThreadBind(&WorkerThreadableLoaderTestHelper::WorkerCreateLoader,
                         CrossThreadUnretained(this),
@@ -194,7 +194,7 @@
   void StartLoader(const ResourceRequest& request) override {
     std::unique_ptr<WaitableEvent> completion_event =
         WTF::MakeUnique<WaitableEvent>();
-    PostTaskToWorkerGlobalScope(
+    worker_loading_task_runner_->PostTask(
         BLINK_FROM_HERE,
         CrossThreadBind(&WorkerThreadableLoaderTestHelper::WorkerStartLoader,
                         CrossThreadUnretained(this),
@@ -231,7 +231,7 @@
 
     std::unique_ptr<WaitableEvent> completion_event =
         WTF::MakeUnique<WaitableEvent>();
-    PostTaskToWorkerGlobalScope(
+    worker_loading_task_runner_->PostTask(
         BLINK_FROM_HERE,
         CrossThreadBind(&WorkerThreadableLoaderTestHelper::WorkerCallCheckpoint,
                         CrossThreadUnretained(this),
@@ -252,17 +252,19 @@
                                         "//fake source code",
                                         parent_frame_task_runners_.Get());
     worker_thread_->WaitForInit();
+    worker_loading_task_runner_ =
+        TaskRunnerHelper::Get(TaskType::kUnspecedLoading, worker_thread_.get());
   }
 
   void OnServeRequests() override { testing::RunPendingTasks(); }
 
   void OnTearDown() override {
-    PostTaskToWorkerGlobalScope(
+    worker_loading_task_runner_->PostTask(
         BLINK_FROM_HERE,
         CrossThreadBind(&WorkerThreadableLoaderTestHelper::ClearLoader,
                         CrossThreadUnretained(this)));
     WaitableEvent event;
-    PostTaskToWorkerGlobalScope(
+    worker_loading_task_runner_->PostTask(
         BLINK_FROM_HERE,
         CrossThreadBind(&WaitableEvent::Signal, CrossThreadUnretained(&event)));
     event.Wait();
@@ -320,23 +322,6 @@
   }
 
   // WorkerLoaderProxyProvider methods.
-  void PostTaskToLoader(
-      const WebTraceLocation& location,
-      std::unique_ptr<WTF::CrossThreadClosure> task) override {
-    DCHECK(worker_thread_);
-    DCHECK(worker_thread_->IsCurrentThread());
-    parent_frame_task_runners_->Get(TaskType::kNetworking)
-        ->PostTask(BLINK_FROM_HERE, std::move(task));
-  }
-
-  void PostTaskToWorkerGlobalScope(
-      const WebTraceLocation& location,
-      std::unique_ptr<WTF::CrossThreadClosure> task) override {
-    DCHECK(worker_thread_);
-    TaskRunnerHelper::Get(TaskType::kNetworking, worker_thread_.get())
-        ->PostTask(location, std::move(task));
-  }
-
   ThreadableLoadingContext* GetThreadableLoadingContext() override {
     return loading_context_.Get();
   }
@@ -348,6 +333,7 @@
   std::unique_ptr<DummyPageHolder> dummy_page_holder_;
   // Accessed cross-thread when worker thread posts tasks to the parent.
   CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
+  RefPtr<WebTaskRunner> worker_loading_task_runner_;
   Checkpoint checkpoint_;
   // |m_loader| must be touched only from the worker thread only.
   CrossThreadPersistent<ThreadableLoader> loader_;
diff --git a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
index 0a5d0dd..a63be36 100644
--- a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.cpp
@@ -65,8 +65,8 @@
 class WorkerThreadableLoader::AsyncTaskForwarder final
     : public WorkerThreadableLoader::TaskForwarder {
  public:
-  explicit AsyncTaskForwarder(PassRefPtr<WorkerLoaderProxy> loader_proxy)
-      : loader_proxy_(std::move(loader_proxy)) {
+  explicit AsyncTaskForwarder(RefPtr<WebTaskRunner> worker_loading_task_runner)
+      : worker_loading_task_runner_(std::move(worker_loading_task_runner)) {
     DCHECK(IsMainThread());
   }
   ~AsyncTaskForwarder() override { DCHECK(IsMainThread()); }
@@ -74,18 +74,18 @@
   void ForwardTask(const WebTraceLocation& location,
                    std::unique_ptr<CrossThreadClosure> task) override {
     DCHECK(IsMainThread());
-    loader_proxy_->PostTaskToWorkerGlobalScope(location, std::move(task));
+    worker_loading_task_runner_->PostTask(location, std::move(task));
   }
   void ForwardTaskWithDoneSignal(
       const WebTraceLocation& location,
       std::unique_ptr<CrossThreadClosure> task) override {
     DCHECK(IsMainThread());
-    loader_proxy_->PostTaskToWorkerGlobalScope(location, std::move(task));
+    worker_loading_task_runner_->PostTask(location, std::move(task));
   }
   void Abort() override { DCHECK(IsMainThread()); }
 
  private:
-  RefPtr<WorkerLoaderProxy> loader_proxy_;
+  RefPtr<WebTaskRunner> worker_loading_task_runner_;
 };
 
 struct WorkerThreadableLoader::TaskWithLocation final {
@@ -199,6 +199,8 @@
     : worker_global_scope_(&worker_global_scope),
       worker_loader_proxy_(
           worker_global_scope.GetThread()->GetWorkerLoaderProxy()),
+      parent_frame_task_runners_(
+          worker_global_scope.GetThread()->GetParentFrameTaskRunners()),
       client_(client),
       threadable_loader_options_(options),
       resource_loader_options_(resource_loader_options),
@@ -235,15 +237,19 @@
   if (blocking_behavior_ == kLoadSynchronously)
     event_with_tasks = WaitableEventWithTasks::Create();
 
-  worker_loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE,
-      CrossThreadBind(
-          &MainThreadLoaderHolder::CreateAndStart,
-          WrapCrossThreadPersistent(this), worker_loader_proxy_,
-          WrapCrossThreadPersistent(worker_global_scope_->GetThread()
-                                        ->GetWorkerThreadLifecycleContext()),
-          request, threadable_loader_options_, resource_loader_options_,
-          event_with_tasks));
+  RefPtr<WebTaskRunner> worker_loading_task_runner = TaskRunnerHelper::Get(
+      TaskType::kUnspecedLoading, worker_global_scope_.Get());
+  parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&MainThreadLoaderHolder::CreateAndStart,
+                          WrapCrossThreadPersistent(this), worker_loader_proxy_,
+                          std::move(worker_loading_task_runner),
+                          WrapCrossThreadPersistent(
+                              worker_global_scope_->GetThread()
+                                  ->GetWorkerThreadLifecycleContext()),
+                          request, threadable_loader_options_,
+                          resource_loader_options_, event_with_tasks));
 
   if (blocking_behavior_ == kLoadAsynchronously)
     return;
@@ -271,18 +277,20 @@
   DCHECK(!IsMainThread());
   if (!main_thread_loader_holder_)
     return;
-  worker_loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE,
-      CrossThreadBind(&MainThreadLoaderHolder::OverrideTimeout,
-                      main_thread_loader_holder_, timeout_milliseconds));
+  parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&MainThreadLoaderHolder::OverrideTimeout,
+                          main_thread_loader_holder_, timeout_milliseconds));
 }
 
 void WorkerThreadableLoader::Cancel() {
   DCHECK(!IsMainThread());
   if (main_thread_loader_holder_) {
-    worker_loader_proxy_->PostTaskToLoader(
-        BLINK_FROM_HERE, CrossThreadBind(&MainThreadLoaderHolder::Cancel,
-                                         main_thread_loader_holder_));
+    parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
+        ->PostTask(BLINK_FROM_HERE,
+                   CrossThreadBind(&MainThreadLoaderHolder::Cancel,
+                                   main_thread_loader_holder_));
     main_thread_loader_holder_ = nullptr;
   }
 
@@ -306,10 +314,11 @@
   DCHECK(main_thread_loader_holder);
   if (!client_) {
     // The thread is terminating.
-    worker_loader_proxy_->PostTaskToLoader(
-        BLINK_FROM_HERE,
-        CrossThreadBind(&MainThreadLoaderHolder::Cancel,
-                        WrapCrossThreadPersistent(main_thread_loader_holder)));
+    parent_frame_task_runners_->Get(TaskType::kUnspecedLoading)
+        ->PostTask(BLINK_FROM_HERE,
+                   CrossThreadBind(
+                       &MainThreadLoaderHolder::Cancel,
+                       WrapCrossThreadPersistent(main_thread_loader_holder)));
     return;
   }
 
@@ -429,6 +438,7 @@
 void WorkerThreadableLoader::MainThreadLoaderHolder::CreateAndStart(
     WorkerThreadableLoader* worker_loader,
     RefPtr<WorkerLoaderProxy> loader_proxy,
+    RefPtr<WebTaskRunner> worker_loading_task_runner,
     WorkerThreadLifecycleContext* worker_thread_lifecycle_context,
     std::unique_ptr<CrossThreadResourceRequestData> request,
     const ThreadableLoaderOptions& options,
@@ -443,7 +453,7 @@
   if (event_with_tasks)
     forwarder = new SyncTaskForwarder(std::move(event_with_tasks));
   else
-    forwarder = new AsyncTaskForwarder(std::move(loader_proxy));
+    forwarder = new AsyncTaskForwarder(std::move(worker_loading_task_runner));
 
   MainThreadLoaderHolder* main_thread_loader_holder =
       new MainThreadLoaderHolder(forwarder, worker_thread_lifecycle_context);
diff --git a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h
index cdbf3aa..10ec0f7 100644
--- a/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h
+++ b/third_party/WebKit/Source/core/loader/WorkerThreadableLoader.h
@@ -142,6 +142,7 @@
    public:
     static void CreateAndStart(WorkerThreadableLoader*,
                                RefPtr<WorkerLoaderProxy>,
+                               RefPtr<WebTaskRunner>,
                                WorkerThreadLifecycleContext*,
                                std::unique_ptr<CrossThreadResourceRequestData>,
                                const ThreadableLoaderOptions&,
@@ -211,6 +212,7 @@
 
   Member<WorkerGlobalScope> worker_global_scope_;
   RefPtr<WorkerLoaderProxy> worker_loader_proxy_;
+  CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
   ThreadableLoaderClient* client_;
 
   ThreadableLoaderOptions threadable_loader_options_;
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
index 4842fbc..1da848b 100644
--- a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
+++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -92,10 +92,10 @@
     WorkerObjectProxy().next_interval_in_sec_ = kNextIntervalInSec;
     WorkerObjectProxy().max_interval_in_sec_ = kMaxIntervalInSec;
 
-    mock_worker_loader_proxy_provider_ =
-        WTF::MakeUnique<MockWorkerLoaderProxyProvider>();
+    worker_loader_proxy_provider_ =
+        WTF::MakeUnique<WorkerLoaderProxyProvider>();
     worker_thread_ = WTF::WrapUnique(new DedicatedWorkerThreadForTest(
-        mock_worker_loader_proxy_provider_.get(), WorkerObjectProxy()));
+        worker_loader_proxy_provider_.get(), WorkerObjectProxy()));
     mock_worker_thread_lifecycle_observer_ =
         new MockWorkerThreadLifecycleObserver(
             worker_thread_->GetWorkerThreadLifecycleContext());
@@ -107,7 +107,7 @@
   ~InProcessWorkerMessagingProxyForTest() override {
     EXPECT_FALSE(blocking_);
     worker_thread_->GetWorkerLoaderProxy()->DetachProvider(
-        mock_worker_loader_proxy_provider_.get());
+        worker_loader_proxy_provider_.get());
   }
 
   void StartWithSourceCode(const String& source) {
@@ -192,8 +192,7 @@
   }
 
  private:
-  std::unique_ptr<MockWorkerLoaderProxyProvider>
-      mock_worker_loader_proxy_provider_;
+  std::unique_ptr<WorkerLoaderProxyProvider> worker_loader_proxy_provider_;
   Persistent<MockWorkerThreadLifecycleObserver>
       mock_worker_thread_lifecycle_observer_;
   RefPtr<SecurityOrigin> security_origin_;
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
index 2adcdb0..d57fa30 100644
--- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
@@ -176,11 +176,15 @@
   if (worker_object_->DispatchEvent(event) != DispatchEventResult::kNotCanceled)
     return;
 
-  PostTaskToWorkerGlobalScope(
-      BLINK_FROM_HERE,
-      CrossThreadBind(&InProcessWorkerObjectProxy::ProcessUnhandledException,
-                      CrossThreadUnretained(worker_object_proxy_.get()),
-                      exception_id, CrossThreadUnretained(GetWorkerThread())));
+  // The HTML spec requires to queue an error event using the DOM manipulation
+  // task source.
+  // https://html.spec.whatwg.org/multipage/workers.html#runtime-script-errors-2
+  TaskRunnerHelper::Get(TaskType::kDOMManipulation, GetWorkerThread())
+      ->PostTask(BLINK_FROM_HERE,
+                 CrossThreadBind(
+                     &InProcessWorkerObjectProxy::ProcessUnhandledException,
+                     CrossThreadUnretained(worker_object_proxy_.get()),
+                     exception_id, CrossThreadUnretained(GetWorkerThread())));
 }
 
 void InProcessWorkerMessagingProxy::WorkerThreadCreated() {
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
index d58013c..d294921 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorklet.cpp
@@ -17,8 +17,8 @@
 
 MainThreadWorklet::MainThreadWorklet(LocalFrame* frame) : Worklet(frame) {}
 
-ScriptPromise MainThreadWorklet::import(ScriptState* script_state,
-                                        const String& url) {
+ScriptPromise MainThreadWorklet::addModule(ScriptState* script_state,
+                                           const String& url) {
   DCHECK(IsMainThread());
   if (!GetExecutionContext()) {
     return ScriptPromise::RejectWithDOMException(
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorklet.h b/third_party/WebKit/Source/core/workers/MainThreadWorklet.h
index 858d1e9..67e8186 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorklet.h
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorklet.h
@@ -29,7 +29,7 @@
   virtual ~MainThreadWorklet() = default;
 
   // Worklet
-  ScriptPromise import(ScriptState*, const String& url) final;
+  ScriptPromise addModule(ScriptState*, const String& url) final;
 
   // WorkletScriptLoader::Client
   void NotifyWorkletScriptLoadingFinished(WorkletScriptLoader*,
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
index fb8241d..e122721 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
@@ -67,24 +67,6 @@
   WorkerThreadCreated();
 }
 
-void ThreadedMessagingProxyBase::PostTaskToWorkerGlobalScope(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  if (asked_to_terminate_)
-    return;
-
-  DCHECK(worker_thread_);
-  TaskRunnerHelper::Get(TaskType::kNetworking, worker_thread_.get())
-      ->PostTask(location, std::move(task));
-}
-
-void ThreadedMessagingProxyBase::PostTaskToLoader(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(BLINK_FROM_HERE, std::move(task));
-}
-
 ThreadableLoadingContext*
 ThreadedMessagingProxyBase::GetThreadableLoadingContext() {
   DCHECK(IsParentContextThread());
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
index a6a31d1..ed21b16 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
@@ -80,13 +80,6 @@
   bool IsParentContextThread() const;
 
   // WorkerLoaderProxyProvider
-  // These methods are called on different threads to schedule loading
-  // requests and to send callbacks back to WorkerGlobalScope.
-  void PostTaskToLoader(const WebTraceLocation&,
-                        std::unique_ptr<WTF::CrossThreadClosure>) override;
-  void PostTaskToWorkerGlobalScope(
-      const WebTraceLocation&,
-      std::unique_ptr<WTF::CrossThreadClosure>) override;
   ThreadableLoadingContext* GetThreadableLoadingContext() override;
 
  private:
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorklet.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorklet.cpp
index d60cded..58497b5 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorklet.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorklet.cpp
@@ -17,8 +17,8 @@
 
 ThreadedWorklet::ThreadedWorklet(LocalFrame* frame) : Worklet(frame) {}
 
-ScriptPromise ThreadedWorklet::import(ScriptState* script_state,
-                                      const String& url) {
+ScriptPromise ThreadedWorklet::addModule(ScriptState* script_state,
+                                         const String& url) {
   DCHECK(IsMainThread());
   if (!GetExecutionContext()) {
     return ScriptPromise::RejectWithDOMException(
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorklet.h b/third_party/WebKit/Source/core/workers/ThreadedWorklet.h
index 24155c8..bb418d1 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorklet.h
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorklet.h
@@ -30,7 +30,7 @@
   virtual ~ThreadedWorklet() = default;
 
   // Worklet
-  ScriptPromise import(ScriptState*, const String& url) final;
+  ScriptPromise addModule(ScriptState*, const String& url) final;
 
   // WorkletScriptLoader::Client
   void NotifyWorkletScriptLoadingFinished(WorkletScriptLoader*,
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
index 7acd313..cf38c7b 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
@@ -7,6 +7,7 @@
 #include "bindings/core/v8/ScriptSourceCode.h"
 #include "core/dom/Document.h"
 #include "core/dom/SecurityContext.h"
+#include "core/dom/TaskRunnerHelper.h"
 #include "core/frame/csp/ContentSecurityPolicy.h"
 #include "core/origin_trials/OriginTrialContext.h"
 #include "core/workers/ThreadedWorkletObjectProxy.h"
@@ -58,12 +59,13 @@
 
 void ThreadedWorkletMessagingProxy::EvaluateScript(
     const ScriptSourceCode& script_source_code) {
-  PostTaskToWorkerGlobalScope(
-      BLINK_FROM_HERE,
-      CrossThreadBind(&ThreadedWorkletObjectProxy::EvaluateScript,
-                      CrossThreadUnretained(worklet_object_proxy_.get()),
-                      script_source_code.Source(), script_source_code.Url(),
-                      CrossThreadUnretained(GetWorkerThread())));
+  TaskRunnerHelper::Get(TaskType::kMiscPlatformAPI, GetWorkerThread())
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&ThreadedWorkletObjectProxy::EvaluateScript,
+                          CrossThreadUnretained(worklet_object_proxy_.get()),
+                          script_source_code.Source(), script_source_code.Url(),
+                          CrossThreadUnretained(GetWorkerThread())));
 }
 
 void ThreadedWorkletMessagingProxy::TerminateWorkletGlobalScope() {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
index 61b5b91..b979310 100644
--- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
+++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -91,16 +91,16 @@
  public:
   ThreadedWorkletMessagingProxyForTest(ExecutionContext* execution_context)
       : ThreadedWorkletMessagingProxy(execution_context) {
-    mock_worker_loader_proxy_provider_ =
-        WTF::MakeUnique<MockWorkerLoaderProxyProvider>();
+    worker_loader_proxy_provider_ =
+        WTF::MakeUnique<WorkerLoaderProxyProvider>();
     worker_thread_ = WTF::MakeUnique<ThreadedWorkletThreadForTest>(
-        mock_worker_loader_proxy_provider_.get(), WorkletObjectProxy());
+        worker_loader_proxy_provider_.get(), WorkletObjectProxy());
     ThreadedWorkletThreadForTest::EnsureSharedBackingThread();
   }
 
   ~ThreadedWorkletMessagingProxyForTest() override {
     worker_thread_->GetWorkerLoaderProxy()->DetachProvider(
-        mock_worker_loader_proxy_provider_.get());
+        worker_loader_proxy_provider_.get());
     worker_thread_->TerminateAndWait();
     ThreadedWorkletThreadForTest::ClearSharedBackingThread();
   };
@@ -136,8 +136,7 @@
  private:
   friend class ThreadedWorkletTest;
 
-  std::unique_ptr<MockWorkerLoaderProxyProvider>
-      mock_worker_loader_proxy_provider_;
+  std::unique_ptr<WorkerLoaderProxyProvider> worker_loader_proxy_provider_;
   RefPtr<SecurityOrigin> security_origin_;
 };
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp
index 1f7f960..59b65a0 100644
--- a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.cpp
@@ -18,36 +18,13 @@
 
 void WorkerLoaderProxy::DetachProvider(
     WorkerLoaderProxyProvider* proxy_provider) {
-  MutexLocker locker(lock_);
   DCHECK(IsMainThread());
   DCHECK_EQ(proxy_provider, loader_proxy_provider_);
   loader_proxy_provider_ = nullptr;
 }
 
-void WorkerLoaderProxy::PostTaskToLoader(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  MutexLocker locker(lock_);
-  DCHECK(!IsMainThread());
-  if (!loader_proxy_provider_)
-    return;
-  loader_proxy_provider_->PostTaskToLoader(location, std::move(task));
-}
-
-void WorkerLoaderProxy::PostTaskToWorkerGlobalScope(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  DCHECK(IsMainThread());
-  // Note: No locking needed for the access from the main thread.
-  if (!loader_proxy_provider_)
-    return;
-  loader_proxy_provider_->PostTaskToWorkerGlobalScope(location,
-                                                      std::move(task));
-}
-
 ThreadableLoadingContext* WorkerLoaderProxy::GetThreadableLoadingContext() {
   DCHECK(IsMainThread());
-  // Note: No locking needed for the access from the main thread.
   if (!loader_proxy_provider_)
     return nullptr;
   DCHECK(
diff --git a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h
index b64fe0f..d82caf7 100644
--- a/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h
+++ b/third_party/WebKit/Source/core/workers/WorkerLoaderProxy.h
@@ -36,49 +36,33 @@
 #include "platform/wtf/Functional.h"
 #include "platform/wtf/PassRefPtr.h"
 #include "platform/wtf/ThreadSafeRefCounted.h"
-#include "platform/wtf/ThreadingPrimitives.h"
 #include "public/platform/WebTraceLocation.h"
 
 namespace blink {
 
 class ThreadableLoadingContext;
 
-// The WorkerLoaderProxy is a proxy to the loader context. Normally, the
-// document on the main thread provides loading services for the subordinate
-// workers. WorkerLoaderProxy provides 2-way communications to the Document
-// context and back to the worker.
-//
-// Note that in multi-process browsers, the Worker object context and the
-// Document context can be distinct.
-
-// The abstract interface providing the methods for actually posting tasks;
-// separated from the thread-safe & ref-counted WorkerLoaderProxy object which
-// keeps a protected reference to the provider object. This to support
-// non-overlapping lifetimes, the provider may be destructed before all
-// references to the WorkerLoaderProxy object have been dropped.
+// The abstract interface to provider ThreadableLoadingContext; separated from
+// the thread-safe & ref-counted WorkerLoaderProxy object which keeps a
+// protected reference to the provider object. This to support non-overlapping
+// lifetimes, the provider may be destructed before all references to the
+// WorkerLoaderProxy object have been dropped.
 //
 // A provider implementation must detach itself when finalizing by calling
 // WorkerLoaderProxy::detachProvider(). This stops the WorkerLoaderProxy from
 // accessing the now-dead object, but it will remain alive while ref-ptrs are
 // still kept to it.
+//
+// TODO(nhiroki): Clean up or remove this class (https://crbug.com/694914).
 class CORE_EXPORT WorkerLoaderProxyProvider {
  public:
   virtual ~WorkerLoaderProxyProvider() {}
 
-  // Posts a task to the thread which runs the loading code (normally, the main
-  // thread). This must be called from a worker thread.
-  virtual void PostTaskToLoader(const WebTraceLocation&,
-                                std::unique_ptr<WTF::CrossThreadClosure>) = 0;
-
-  // Posts callbacks from loading code to the WorkerGlobalScope. This must be
-  // called from the main thread.
-  virtual void PostTaskToWorkerGlobalScope(
-      const WebTraceLocation&,
-      std::unique_ptr<WTF::CrossThreadClosure>) = 0;
-
   // It is guaranteed that this gets accessed only on the thread where
   // the loading context is bound.
-  virtual ThreadableLoadingContext* GetThreadableLoadingContext() = 0;
+  virtual ThreadableLoadingContext* GetThreadableLoadingContext() {
+    return nullptr;
+  }
 };
 
 class CORE_EXPORT WorkerLoaderProxy final
@@ -91,14 +75,6 @@
 
   ~WorkerLoaderProxy();
 
-  // This must be called from a worker thread.
-  void PostTaskToLoader(const WebTraceLocation&,
-                        std::unique_ptr<WTF::CrossThreadClosure>);
-
-  // This must be called from the main thread.
-  void PostTaskToWorkerGlobalScope(const WebTraceLocation&,
-                                   std::unique_ptr<WTF::CrossThreadClosure>);
-
   // This may return nullptr.
   // This must be called from the main thread (== the thread of the
   // loading context).
@@ -112,7 +88,6 @@
  private:
   explicit WorkerLoaderProxy(WorkerLoaderProxyProvider*);
 
-  WTF::Mutex lock_;
   WorkerLoaderProxyProvider* loader_proxy_provider_;
 };
 
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
index aff8ef3..f141dab 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
@@ -67,7 +67,7 @@
   WorkerThreadTest() {}
 
   void SetUp() override {
-    loader_proxy_provider_ = WTF::MakeUnique<MockWorkerLoaderProxyProvider>();
+    loader_proxy_provider_ = WTF::MakeUnique<WorkerLoaderProxyProvider>();
     reporting_proxy_ = WTF::MakeUnique<MockWorkerReportingProxy>();
     security_origin_ =
         SecurityOrigin::Create(KURL(kParsedURLString, "http://fake.url/"));
@@ -143,7 +143,7 @@
   ExitCode GetExitCode() { return worker_thread_->GetExitCodeForTesting(); }
 
   RefPtr<SecurityOrigin> security_origin_;
-  std::unique_ptr<MockWorkerLoaderProxyProvider> loader_proxy_provider_;
+  std::unique_ptr<WorkerLoaderProxyProvider> loader_proxy_provider_;
   std::unique_ptr<MockWorkerReportingProxy> reporting_proxy_;
   std::unique_ptr<WorkerThreadForTest> worker_thread_;
   Persistent<MockWorkerThreadLifecycleObserver> lifecycle_observer_;
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
index b0e58710..d646ffd 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
+++ b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
@@ -35,28 +35,6 @@
 
 namespace blink {
 
-class MockWorkerLoaderProxyProvider : public WorkerLoaderProxyProvider {
- public:
-  MockWorkerLoaderProxyProvider() {}
-  ~MockWorkerLoaderProxyProvider() override {}
-
-  void PostTaskToLoader(const WebTraceLocation&,
-                        std::unique_ptr<WTF::CrossThreadClosure>) override {
-    NOTIMPLEMENTED();
-  }
-
-  void PostTaskToWorkerGlobalScope(
-      const WebTraceLocation&,
-      std::unique_ptr<WTF::CrossThreadClosure>) override {
-    NOTIMPLEMENTED();
-  }
-
-  ThreadableLoadingContext* GetThreadableLoadingContext() override {
-    NOTIMPLEMENTED();
-    return nullptr;
-  }
-};
-
 class MockWorkerThreadLifecycleObserver final
     : public GarbageCollectedFinalized<MockWorkerThreadLifecycleObserver>,
       public WorkerThreadLifecycleObserver {
@@ -73,12 +51,10 @@
 
 class WorkerThreadForTest : public WorkerThread {
  public:
-  WorkerThreadForTest(
-      WorkerLoaderProxyProvider* mock_worker_loader_proxy_provider,
-      WorkerReportingProxy& mock_worker_reporting_proxy)
-      : WorkerThread(
-            WorkerLoaderProxy::Create(mock_worker_loader_proxy_provider),
-            mock_worker_reporting_proxy),
+  WorkerThreadForTest(WorkerLoaderProxyProvider* worker_loader_proxy_provider,
+                      WorkerReportingProxy& mock_worker_reporting_proxy)
+      : WorkerThread(WorkerLoaderProxy::Create(worker_loader_proxy_provider),
+                     mock_worker_reporting_proxy),
         worker_backing_thread_(
             WorkerBackingThread::CreateForTest("Test thread")) {}
 
diff --git a/third_party/WebKit/Source/core/workers/Worklet.h b/third_party/WebKit/Source/core/workers/Worklet.h
index f482229..07122bd 100644
--- a/third_party/WebKit/Source/core/workers/Worklet.h
+++ b/third_party/WebKit/Source/core/workers/Worklet.h
@@ -34,8 +34,8 @@
   virtual bool IsInitialized() const { return true; }
 
   // Worklet.idl
-  // import() imports ES6 module scripts.
-  virtual ScriptPromise import(ScriptState*, const String& url) = 0;
+  // addModule() imports ES6 module scripts.
+  virtual ScriptPromise addModule(ScriptState*, const String& url) = 0;
 
   // Returns a proxy to WorkletGlobalScope on the context thread.
   virtual WorkletGlobalScopeProxy* GetWorkletGlobalScopeProxy() const = 0;
diff --git a/third_party/WebKit/Source/core/workers/Worklet.idl b/third_party/WebKit/Source/core/workers/Worklet.idl
index f3e1b5a..07613f5 100644
--- a/third_party/WebKit/Source/core/workers/Worklet.idl
+++ b/third_party/WebKit/Source/core/workers/Worklet.idl
@@ -8,5 +8,5 @@
     DependentLifetime,
     RuntimeEnabled=Worklet,
 ] interface Worklet {
-    [CallWith=ScriptState] Promise<void> import(DOMString url);
+    [CallWith=ScriptState] Promise<void> addModule(DOMString url);
 };
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
index eee22ee..73c1e71 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.cpp
@@ -162,10 +162,12 @@
 
 Peer::Peer(Bridge* bridge,
            PassRefPtr<WorkerLoaderProxy> loader_proxy,
+           RefPtr<WebTaskRunner> worker_networking_task_runner,
            WorkerThreadLifecycleContext* worker_thread_lifecycle_context)
     : WorkerThreadLifecycleObserver(worker_thread_lifecycle_context),
       bridge_(bridge),
       loader_proxy_(std::move(loader_proxy)),
+      worker_networking_task_runner_(std::move(worker_networking_task_runner)),
       main_web_socket_channel_(nullptr) {
   DCHECK(IsMainThread());
 }
@@ -242,7 +244,7 @@
 
 void Peer::DidConnect(const String& subprotocol, const String& extensions) {
   DCHECK(IsMainThread());
-  loader_proxy_->PostTaskToWorkerGlobalScope(
+  worker_networking_task_runner_->PostTask(
       BLINK_FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidConnect, bridge_,
                                        subprotocol, extensions));
 }
@@ -255,7 +257,7 @@
 
 void Peer::DidReceiveTextMessage(const String& payload) {
   DCHECK(IsMainThread());
-  loader_proxy_->PostTaskToWorkerGlobalScope(
+  worker_networking_task_runner_->PostTask(
       BLINK_FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidReceiveTextMessage,
                                        bridge_, payload));
 }
@@ -269,7 +271,7 @@
 
 void Peer::DidReceiveBinaryMessage(std::unique_ptr<Vector<char>> payload) {
   DCHECK(IsMainThread());
-  loader_proxy_->PostTaskToWorkerGlobalScope(
+  worker_networking_task_runner_->PostTask(
       BLINK_FROM_HERE,
       CrossThreadBind(&WorkerGlobalScopeDidReceiveBinaryMessage, bridge_,
                       WTF::Passed(std::move(payload))));
@@ -283,7 +285,7 @@
 
 void Peer::DidConsumeBufferedAmount(uint64_t consumed) {
   DCHECK(IsMainThread());
-  loader_proxy_->PostTaskToWorkerGlobalScope(
+  worker_networking_task_runner_->PostTask(
       BLINK_FROM_HERE,
       CrossThreadBind(&WorkerGlobalScopeDidConsumeBufferedAmount, bridge_,
                       consumed));
@@ -296,7 +298,7 @@
 
 void Peer::DidStartClosingHandshake() {
   DCHECK(IsMainThread());
-  loader_proxy_->PostTaskToWorkerGlobalScope(
+  worker_networking_task_runner_->PostTask(
       BLINK_FROM_HERE,
       CrossThreadBind(&WorkerGlobalScopeDidStartClosingHandshake, bridge_));
 }
@@ -320,7 +322,7 @@
     main_web_socket_channel_->Disconnect();
     main_web_socket_channel_ = nullptr;
   }
-  loader_proxy_->PostTaskToWorkerGlobalScope(
+  worker_networking_task_runner_->PostTask(
       BLINK_FROM_HERE,
       CrossThreadBind(&WorkerGlobalScopeDidClose, bridge_,
                       closing_handshake_completion, code, reason));
@@ -333,7 +335,7 @@
 
 void Peer::DidError() {
   DCHECK(IsMainThread());
-  loader_proxy_->PostTaskToWorkerGlobalScope(
+  worker_networking_task_runner_->PostTask(
       BLINK_FROM_HERE, CrossThreadBind(&WorkerGlobalScopeDidError, bridge_));
 }
 
@@ -356,8 +358,9 @@
                WorkerGlobalScope& worker_global_scope)
     : client_(client),
       worker_global_scope_(worker_global_scope),
-      loader_proxy_(worker_global_scope_->GetThread()->GetWorkerLoaderProxy()) {
-}
+      loader_proxy_(worker_global_scope_->GetThread()->GetWorkerLoaderProxy()),
+      parent_frame_task_runners_(
+          worker_global_scope_->GetThread()->GetParentFrameTaskRunners()) {}
 
 Bridge::~Bridge() {
   DCHECK(!peer_);
@@ -366,6 +369,7 @@
 void Bridge::ConnectOnMainThread(
     std::unique_ptr<SourceLocation> location,
     RefPtr<WorkerLoaderProxy> loader_proxy,
+    RefPtr<WebTaskRunner> worker_networking_task_runner,
     WorkerThreadLifecycleContext* worker_thread_lifecycle_context,
     const KURL& url,
     const String& protocol,
@@ -376,7 +380,9 @@
       loader_proxy->GetThreadableLoadingContext();
   if (!loading_context)
     return;
-  Peer* peer = new Peer(this, loader_proxy_, worker_thread_lifecycle_context);
+  Peer* peer =
+      new Peer(this, loader_proxy_, std::move(worker_networking_task_runner),
+               worker_thread_lifecycle_context);
   if (peer->Initialize(std::move(location), loading_context)) {
     peer_ = peer;
     sync_helper->SetConnectRequestResult(peer_->Connect(url, protocol));
@@ -390,14 +396,19 @@
   // Wait for completion of the task on the main thread because the mixed
   // content check must synchronously be conducted.
   WebSocketChannelSyncHelper sync_helper;
-  loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE,
-      CrossThreadBind(
-          &Bridge::ConnectOnMainThread, WrapCrossThreadPersistent(this),
-          WTF::Passed(location->Clone()), loader_proxy_,
-          WrapCrossThreadPersistent(worker_global_scope_->GetThread()
-                                        ->GetWorkerThreadLifecycleContext()),
-          url, protocol, CrossThreadUnretained(&sync_helper)));
+  RefPtr<WebTaskRunner> worker_networking_task_runner =
+      TaskRunnerHelper::Get(TaskType::kNetworking, worker_global_scope_.Get());
+  parent_frame_task_runners_->Get(TaskType::kNetworking)
+      ->PostTask(
+          BLINK_FROM_HERE,
+          CrossThreadBind(&Bridge::ConnectOnMainThread,
+                          WrapCrossThreadPersistent(this),
+                          WTF::Passed(location->Clone()), loader_proxy_,
+                          std::move(worker_networking_task_runner),
+                          WrapCrossThreadPersistent(
+                              worker_global_scope_->GetThread()
+                                  ->GetWorkerThreadLifecycleContext()),
+                          url, protocol, CrossThreadUnretained(&sync_helper)));
   sync_helper.Wait();
   return sync_helper.ConnectRequestResult();
 }
@@ -410,9 +421,10 @@
     memcpy(data->data(), static_cast<const char*>(message.data()),
            message.length());
 
-  loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE, CrossThreadBind(&Peer::SendTextAsCharVector, peer_,
-                                       WTF::Passed(std::move(data))));
+  parent_frame_task_runners_->Get(TaskType::kNetworking)
+      ->PostTask(BLINK_FROM_HERE,
+                 CrossThreadBind(&Peer::SendTextAsCharVector, peer_,
+                                 WTF::Passed(std::move(data))));
 }
 
 void Bridge::Send(const DOMArrayBuffer& binary_data,
@@ -428,39 +440,42 @@
            static_cast<const char*>(binary_data.Data()) + byte_offset,
            byte_length);
 
-  loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE, CrossThreadBind(&Peer::SendBinaryAsCharVector, peer_,
-                                       WTF::Passed(std::move(data))));
+  parent_frame_task_runners_->Get(TaskType::kNetworking)
+      ->PostTask(BLINK_FROM_HERE,
+                 CrossThreadBind(&Peer::SendBinaryAsCharVector, peer_,
+                                 WTF::Passed(std::move(data))));
 }
 
 void Bridge::Send(PassRefPtr<BlobDataHandle> data) {
   DCHECK(peer_);
-  loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE,
-      CrossThreadBind(&Peer::SendBlob, peer_, std::move(data)));
+  parent_frame_task_runners_->Get(TaskType::kNetworking)
+      ->PostTask(BLINK_FROM_HERE,
+                 CrossThreadBind(&Peer::SendBlob, peer_, std::move(data)));
 }
 
 void Bridge::Close(int code, const String& reason) {
   DCHECK(peer_);
-  loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE, CrossThreadBind(&Peer::Close, peer_, code, reason));
+  parent_frame_task_runners_->Get(TaskType::kNetworking)
+      ->PostTask(BLINK_FROM_HERE,
+                 CrossThreadBind(&Peer::Close, peer_, code, reason));
 }
 
 void Bridge::Fail(const String& reason,
                   MessageLevel level,
                   std::unique_ptr<SourceLocation> location) {
   DCHECK(peer_);
-  loader_proxy_->PostTaskToLoader(
-      BLINK_FROM_HERE, CrossThreadBind(&Peer::Fail, peer_, reason, level,
-                                       WTF::Passed(location->Clone())));
+  parent_frame_task_runners_->Get(TaskType::kNetworking)
+      ->PostTask(BLINK_FROM_HERE,
+                 CrossThreadBind(&Peer::Fail, peer_, reason, level,
+                                 WTF::Passed(location->Clone())));
 }
 
 void Bridge::Disconnect() {
   if (!peer_)
     return;
 
-  loader_proxy_->PostTaskToLoader(BLINK_FROM_HERE,
-                                  CrossThreadBind(&Peer::Disconnect, peer_));
+  parent_frame_task_runners_->Get(TaskType::kNetworking)
+      ->PostTask(BLINK_FROM_HERE, CrossThreadBind(&Peer::Disconnect, peer_));
 
   client_ = nullptr;
   peer_ = nullptr;
diff --git a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
index d35f36b..80f42f0 100644
--- a/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
+++ b/third_party/WebKit/Source/modules/websockets/WorkerWebSocketChannel.h
@@ -34,6 +34,7 @@
 #include <stdint.h>
 #include <memory>
 #include "bindings/core/v8/SourceLocation.h"
+#include "core/workers/ParentFrameTaskRunners.h"
 #include "core/workers/WorkerThreadLifecycleObserver.h"
 #include "modules/websockets/WebSocketChannel.h"
 #include "modules/websockets/WebSocketChannelClient.h"
@@ -96,7 +97,10 @@
     WTF_MAKE_NONCOPYABLE(Peer);
 
    public:
-    Peer(Bridge*, PassRefPtr<WorkerLoaderProxy>, WorkerThreadLifecycleContext*);
+    Peer(Bridge*,
+         PassRefPtr<WorkerLoaderProxy>,
+         RefPtr<WebTaskRunner>,
+         WorkerThreadLifecycleContext*);
     ~Peer() override;
 
     // SourceLocation parameter may be shown when the connection fails.
@@ -134,6 +138,7 @@
    private:
     CrossThreadWeakPersistent<Bridge> bridge_;
     RefPtr<WorkerLoaderProxy> loader_proxy_;
+    RefPtr<WebTaskRunner> worker_networking_task_runner_;
     Member<WebSocketChannel> main_web_socket_channel_;
   };
 
@@ -163,6 +168,7 @@
 
     void ConnectOnMainThread(std::unique_ptr<SourceLocation>,
                              RefPtr<WorkerLoaderProxy>,
+                             RefPtr<WebTaskRunner>,
                              WorkerThreadLifecycleContext*,
                              const KURL&,
                              const String& protocol,
@@ -179,6 +185,7 @@
     Member<WebSocketChannelClient> client_;
     Member<WorkerGlobalScope> worker_global_scope_;
     RefPtr<WorkerLoaderProxy> loader_proxy_;
+    CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
     CrossThreadPersistent<Peer> peer_;
   };
 
diff --git a/third_party/WebKit/Source/platform/wtf/README.md b/third_party/WebKit/Source/platform/wtf/README.md
index e61a501..20f537e 100644
--- a/third_party/WebKit/Source/platform/wtf/README.md
+++ b/third_party/WebKit/Source/platform/wtf/README.md
@@ -1,14 +1,127 @@
-# platform/wtf
+# WTF (Web Template Framework)
 
-This is the location where all the files under Source/wtf will be moved
-eventually. See
-[the proposal](https://docs.google.com/document/d/1shS1IZe__auYxjm9FhPbTY2P01FbNTMYRh-nen5gkDo/edit?usp=sharing)
-and
-[the design doc](https://docs.google.com/document/d/1JK26H-1-cD9-s9QLvEfY55H2kgSxRFNPLfjs049Us5w/edit?usp=sharing)
-regarding the relocation project. For the project's progress, see
-[bug 691465](https://bugs.chromium.org/p/chromium/issues/detail?id=691465).
+WTF is a base library for Blink providing a variety of basic functionalities,
+like containers, string libraries, reference counting mechanisms, functors,
+threading primitives etc.
 
-During the project, files in wtf/ are moved to platform/wtf incrementally, and
-redirection headers will be placed in wtf/. So nothing should break in the
-meantime. You can continue including WTF headers like `#include "wtf/Xxx.h"`
-till the next announce in blink-dev.
+WTF's mission is to power and support all other Blink code base by providing
+fast, reliable, user-friendly and secure generic primitives.
+
+Dependency-wise, WTF cannot depend on any other Blink headers, including
+files under other platform/ subdirectories, since WTF is a library that can be
+referred from anywhere in Blink. WTF basically can only depend on [base].
+
+Main code base of Blink (core and modules) cannot directly depend on [base].
+The main objective of this is to limit what Blink core can use, so that Blink
+core code wouldn't use libraries prohibited in Blink accidentally (such as
+`std::string` or `std::vector`).
+
+Our approach here is to make WTF and other platform/ components a gatekeeper of
+the use of [base] libraries. platform/ (including WTF) can directly depend on
+[base], and if some of the [base] functionalities are worth having in Blink,
+WTF can expose them in a way Blink core code can easily use them. Usually,
+such a library would be a thin wrapper of the corresponding [base]
+functionality.
+
+Also, we are trying to eliminate duplicated functionalities between WTF and
+[base]. Historically, WTF was developed as a stand-alone library, so there
+are still many overlaps. We want to eventually delegate sharable implementation
+to [base] as much as possible.
+
+If you find a missing functionality in WTF, regardless of whether it is
+available in [base] or not, feel free to file a bug under the component
+Blink>Internals>WTF.
+
+## Library catalog
+
+The below is a list of major libraries. For a complete list, look at
+[the directory listing].
+
+* **Containers**
+
+  [Vector], [HashSet], [HashMap], [Deque]
+
+* **Strings**
+
+  [String], [AtomicString], [StringBuilder], [CString]
+
+* **Reference counting**
+
+  [RefCounted], [RefPtr]
+
+* **Memory**
+
+  [PtrUtil.h] (`std::unique_ptr<>` utilities),
+  [Allocator.h] (memory placement macros)
+
+* **Functors, binding**
+
+  [Functional.h]
+
+* **Threading**
+
+  [Threading.h], [ThreadingPrimitives.h]
+
+* **Compile-time switch macros**
+
+  [Compiler.h] (e.g. `COMPILER(GCC)`),
+  [CPU.h] (e.g. `CPU(X86_64)` or `CPU(64BIT)`),
+  [build_config.h] (e.g. `OS(WIN)`)
+
+* **Miscellaneous**
+
+  [Noncopyable.h] (`WTF_MAKE_NONCOPYABLE`),
+  [StdLibExtras.h] (`DEFINE_STATIC_LOCAL` etc.),
+  [CurrentTime.h],
+  [CryptographicallyRandomNumber.h],
+  [AutoReset.h],
+  [Optional.h]
+
+## History
+
+The name WTF first [appeared in 2006][1], as a replacement of its older name
+KXMLCore. At that point, there were already plenty of libraries we see today.
+For example, you can see [the initial implementation of `Vector`][2] was landed
+in 2006, replacing several manual array allocations and deallocations(!).
+
+If you dig the repository a bit more, you can find the original version of
+Assertions.h was [committed back in 2002][3]. This is probably the oldest
+library that we can find from the repository history.
+
+As you see, pretty much everything that we have today in WTF was created in
+the WebKit era. WTF was initially under the directory Source/JavaScriptCore,
+but it moved to Source/WTF/wtf in 2011-2012, then to Source/wtf in 2013.
+
+Blink forked WebKit in 2013. In 2017, the directory finally [moved to the
+current location][4] Source/platform/wtf.
+
+[the directory listing]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/
+[base]: https://cs.chromium.org/chromium/src/base/
+[Vector]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Vector.h
+[HashSet]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/HashSet.h
+[HashMap]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/HashMap.h
+[Deque]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Deque.h
+[String]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/text/WTFString.h
+[AtomicString]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/text/AtomicString.h
+[StringBuilder]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/text/StringBuilder.h
+[CString]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/text/CString.h
+[RefCounted]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/RefCounted.h
+[RefPtr]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/RefPtr.h
+[PtrUtil.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/PtrUtil.h
+[Allocator.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Allocator.h
+[Functional.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Functional.h
+[Threading.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Threading.h
+[ThreadingPrimitives.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/ThreadingPrimitives.h
+[Compiler.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Compiler.h
+[CPU.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/CPU.h
+[build_config.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/build_config.h
+[Noncopyable.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Noncopyable.h
+[StdLibExtras.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/StdLibExtras.h
+[CurrentTime.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/CurrentTime.h
+[CryptographicallyRandomNumber.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/CryptographicallyRandomNumber.h
+[AutoReset.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/AutoReset.h
+[Optional.h]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/wtf/Optional.h
+[1]: https://chromium.googlesource.com/chromium/src/+/e372c152fc6e57743ebc508fe17f6eb131b4ff8d
+[2]: https://chromium.googlesource.com/chromium/src/+/547a6ca360a56fbee3d5ea4a71ba18f91622455c
+[3]: https://chromium.googlesource.com/chromium/src/+/478890427ee03fd88e6f0f58ee8220512044bed9/third_party/WebKit/WebCore/kwq/KWQAssertions.h
+[4]:https://docs.google.com/document/d/1JK26H-1-cD9-s9QLvEfY55H2kgSxRFNPLfjs049Us5w/edit?usp=sharing
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
index 38eab81..1b4d6eb 100644
--- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.cpp
@@ -263,22 +263,6 @@
   worker_inspector_proxy_->DispatchMessageFromWorker(message);
 }
 
-void WebEmbeddedWorkerImpl::PostTaskToLoader(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  main_thread_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(BLINK_FROM_HERE, std::move(task));
-}
-
-void WebEmbeddedWorkerImpl::PostTaskToWorkerGlobalScope(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  if (asked_to_terminate_ || !worker_thread_)
-    return;
-  TaskRunnerHelper::Get(TaskType::kNetworking, worker_thread_.get())
-      ->PostTask(location, std::move(task));
-}
-
 ThreadableLoadingContext* WebEmbeddedWorkerImpl::GetThreadableLoadingContext() {
   if (!loading_context_) {
     loading_context_ = ThreadableLoadingContext::Create(
@@ -467,19 +451,19 @@
 
   main_script_loader_.Clear();
 
-  // We have a dummy document here for loading but it doesn't really represent
-  // the document/frame of associated document(s) for this worker. Here we
-  // populate the task runners with null document not to confuse the frame
-  // scheduler (which will end up using the thread's default task runner).
-  main_thread_task_runners_ = ParentFrameTaskRunners::Create(nullptr);
-
   worker_global_scope_proxy_ = ServiceWorkerGlobalScopeProxy::Create(
       *this, *document, *worker_context_client_);
   loader_proxy_ = WorkerLoaderProxy::Create(this);
   worker_thread_ =
       ServiceWorkerThread::Create(loader_proxy_, *worker_global_scope_proxy_);
+
+  // We have a dummy document here for loading but it doesn't really represent
+  // the document/frame of associated document(s) for this worker. Here we
+  // populate the task runners with null document not to confuse the frame
+  // scheduler (which will end up using the thread's default task runner).
   worker_thread_->Start(std::move(startup_data),
-                        main_thread_task_runners_.Get());
+                        ParentFrameTaskRunners::Create(nullptr));
+
   worker_inspector_proxy_->WorkerThreadCreated(document, worker_thread_.get(),
                                                script_url);
 }
diff --git a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h
index 0c7c01c..7d8c2c9 100644
--- a/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h
+++ b/third_party/WebKit/Source/web/WebEmbeddedWorkerImpl.h
@@ -44,7 +44,6 @@
 namespace blink {
 
 class ThreadableLoadingContext;
-class ParentFrameTaskRunners;
 class ServiceWorkerGlobalScopeProxy;
 class WebLocalFrameImpl;
 class WebView;
@@ -100,11 +99,6 @@
   void StartWorkerThread();
 
   // WorkerLoaderProxyProvider
-  void PostTaskToLoader(const WebTraceLocation&,
-                        std::unique_ptr<WTF::CrossThreadClosure>) override;
-  void PostTaskToWorkerGlobalScope(
-      const WebTraceLocation&,
-      std::unique_ptr<WTF::CrossThreadClosure>) override;
   ThreadableLoadingContext* GetThreadableLoadingContext() override;
 
   WebEmbeddedWorkerStartData worker_start_data_;
@@ -118,10 +112,6 @@
   // Kept around only while main script loading is ongoing.
   RefPtr<WorkerScriptLoader> main_script_loader_;
 
-  // Owned by the main thread, but will be accessed by the worker when
-  // posting tasks.
-  CrossThreadPersistent<ParentFrameTaskRunners> main_thread_task_runners_;
-
   std::unique_ptr<WorkerThread> worker_thread_;
   RefPtr<WorkerLoaderProxy> loader_proxy_;
   Persistent<ServiceWorkerGlobalScopeProxy> worker_global_scope_proxy_;
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
index d0625a0..df1c855 100644
--- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
+++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.cpp
@@ -241,24 +241,6 @@
   delete this;
 }
 
-// WorkerLoaderProxyProvider -------------------------------------------------
-
-void WebSharedWorkerImpl::PostTaskToLoader(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  DCHECK(worker_thread_->IsCurrentThread());
-  parent_frame_task_runners_->Get(TaskType::kNetworking)
-      ->PostTask(FROM_HERE, std::move(task));
-}
-
-void WebSharedWorkerImpl::PostTaskToWorkerGlobalScope(
-    const WebTraceLocation& location,
-    std::unique_ptr<WTF::CrossThreadClosure> task) {
-  DCHECK(IsMainThread());
-  TaskRunnerHelper::Get(TaskType::kNetworking, GetWorkerThread())
-      ->PostTask(location, std::move(task));
-}
-
 ThreadableLoadingContext* WebSharedWorkerImpl::GetThreadableLoadingContext() {
   if (!loading_context_) {
     loading_context_ =
@@ -270,6 +252,9 @@
 void WebSharedWorkerImpl::Connect(
     std::unique_ptr<WebMessagePortChannel> web_channel) {
   DCHECK(IsMainThread());
+  // The HTML spec requires to queue a connect event using the DOM manipulation
+  // task source.
+  // https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworker-interface
   TaskRunnerHelper::Get(TaskType::kDOMManipulation, GetWorkerThread())
       ->PostTask(
           BLINK_FROM_HERE,
@@ -365,19 +350,18 @@
   // use the thread's default task runner. Note that |m_document| should not be
   // used as it's a dummy document for loading that doesn't represent the frame
   // of any associated document.
-  parent_frame_task_runners_ = ParentFrameTaskRunners::Create(nullptr);
+  ParentFrameTaskRunners* task_runners =
+      ParentFrameTaskRunners::Create(nullptr);
 
   loader_proxy_ = WorkerLoaderProxy::Create(this);
-  reporting_proxy_ = new WebSharedWorkerReportingProxyImpl(
-      this, parent_frame_task_runners_.Get());
+  reporting_proxy_ = new WebSharedWorkerReportingProxyImpl(this, task_runners);
   worker_thread_ =
       SharedWorkerThread::Create(name_, loader_proxy_, *reporting_proxy_);
   probe::scriptImported(loading_document_, main_script_loader_->Identifier(),
                         main_script_loader_->SourceText());
   main_script_loader_.Clear();
 
-  GetWorkerThread()->Start(std::move(startup_data),
-                           parent_frame_task_runners_.Get());
+  GetWorkerThread()->Start(std::move(startup_data), task_runners);
   worker_inspector_proxy_->WorkerThreadCreated(ToDocument(loading_document_),
                                                GetWorkerThread(), url_);
   client_->WorkerScriptLoaded();
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
index dbe067d..85ea4b4 100644
--- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
+++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
@@ -47,7 +47,6 @@
 
 namespace blink {
 
-class ParentFrameTaskRunners;
 class WebApplicationCacheHost;
 class WebApplicationCacheHostClient;
 class WebLocalFrameImpl;
@@ -128,12 +127,6 @@
   void ConnectTaskOnWorkerThread(std::unique_ptr<WebMessagePortChannel>);
 
   // WorkerLoaderProxyProvider
-  // postTaskToLoader() must be called from a worker thread.
-  void PostTaskToLoader(const WebTraceLocation&,
-                        std::unique_ptr<WTF::CrossThreadClosure>) override;
-  void PostTaskToWorkerGlobalScope(
-      const WebTraceLocation&,
-      std::unique_ptr<WTF::CrossThreadClosure>) override;
   ThreadableLoadingContext* GetThreadableLoadingContext() override;
 
   // 'shadow page' - created to proxy loading requests from the worker.
@@ -148,9 +141,6 @@
 
   Persistent<WorkerInspectorProxy> worker_inspector_proxy_;
 
-  // Owned by the main thread, but will be accessed by the worker.
-  CrossThreadPersistent<ParentFrameTaskRunners> parent_frame_task_runners_;
-
   Persistent<WebSharedWorkerReportingProxyImpl> reporting_proxy_;
   std::unique_ptr<WorkerThread> worker_thread_;
 
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index 067416e..30c8408 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -222,6 +222,10 @@
 
     # requires descriptors & reflection; testonly.
     "//third_party/libprotobuf-mutator:*",
+
+    # The traffic_annotation tool is not part of Chrome itself, and needs to
+    # parse human-readable protobufs.
+    "//tools/traffic_annotation/*",
   ]
 
   sources = protobuf_lite_sources + protobuf_globals_sources + [
diff --git a/tools/clang/traffic_annotation_extractor/CMakeLists.txt b/tools/clang/traffic_annotation_extractor/CMakeLists.txt
new file mode 100644
index 0000000..f33d3ae
--- /dev/null
+++ b/tools/clang/traffic_annotation_extractor/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_LINK_COMPONENTS
+  BitReader
+  MCParser
+  Option
+  )
+
+add_llvm_executable(traffic_annotation_extractor
+  traffic_annotation_extractor.cpp
+  )
+
+target_link_libraries(traffic_annotation_extractor
+  clangAST
+  clangASTMatchers
+  clangAnalysis
+  clangBasic
+  clangDriver
+  clangEdit
+  clangFrontend
+  clangLex
+  clangParse
+  clangSema
+  clangSerialization
+  clangTooling
+  )
+
+cr_install(TARGETS traffic_annotation_extractor RUNTIME DESTINATION bin)
diff --git a/tools/clang/traffic_annotation_extractor/README.md b/tools/clang/traffic_annotation_extractor/README.md
new file mode 100644
index 0000000..e17ac2d
--- /dev/null
+++ b/tools/clang/traffic_annotation_extractor/README.md
@@ -0,0 +1,26 @@
+# Traffic Annotation Extrator
+This is a clang tool to extract network traffic annotations. The tool is run by
+`tools/traffic_annotation/auditor/traffic_annotaion_auditor.py`. Refer to it for
+help on how to use.
+
+## Build on Linux
+`tools/clang/scripts/update.py --bootstrap --force-local-build
+   --without-android --extra-tools traffic_annotation_extractor`
+
+## Build on Window
+1. Either open a `VS2015 x64 Native Tools Command Prompt`, or open a normal
+   command prompt and run `depot_tools\win_toolchain\vs_files\
+   $long_autocompleted_hash\win_sdk\bin\setenv.cmd /x64`
+2. Run `python tools/clang/scripts/update.py --bootstrap --force-local-build
+   --without-android --extra-tools traffic_annotation_extractor`
+
+## Usage
+Run `traffic_annotation_extractor --help` for parameters help.
+The executable extracts network traffic annotations from given file paths based
+  on build parameters in build path, and writes them to llvm::outs.
+  Each output will have the following format:
+  - Line 1: File path.
+  - Line 2: Name of the function in which annotation is defined.
+  - Line 3: Line number of annotation.
+  - Line 4: Unique id of annotation.
+  - Line 5-: Serialized protobuf of the annotation.
\ No newline at end of file
diff --git a/tools/clang/traffic_annotation_extractor/traffic_annotation_extractor.cpp b/tools/clang/traffic_annotation_extractor/traffic_annotation_extractor.cpp
new file mode 100644
index 0000000..4a4baa0
--- /dev/null
+++ b/tools/clang/traffic_annotation_extractor/traffic_annotation_extractor.cpp
@@ -0,0 +1,175 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This clang tool finds all instances of net::DefineNetworkTrafficAnnotation in
+// given source code, extracts the location info and content of annotation tags
+// (unique id and annotation text), and stores them in separate text files
+// (per instance) in the given output directory. Please refer to README.md for
+// build and usage instructions.
+
+#include <memory>
+#include <vector>
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace clang::ast_matchers;
+
+namespace {
+
+// An instance of a call to the net::DefineNetworkTrafficAnnotation function.
+struct NetworkAnnotationInstance {
+  // Information about where the call has happened.
+  struct Location {
+    std::string file_path;
+    int line_number = -1;
+
+    // Name of the function calling net::DefineNetworkTrafficAnnotation. E.g.,
+    // in the following code, |function_name| will be 'foo':
+    // void foo() { NetworkTrafficAnnotationTag bar =
+    //                  net::DefineNetworkTrafficAnnotation(...); }
+    // If no function is found, 'Global Namespace' will be returned.
+    std::string function_name;
+  };
+
+  // Annotation content. These are the parameters of the call to
+  // net::DefineNetworkTrafficAnnotation. The unique_id is an identifier for the
+  // annotation that has to be unique across the entire code base. The |text|
+  // stores a raw string with the annotation that should be extracted.
+  struct Annotation {
+    std::string unique_id;
+    std::string text;
+  };
+
+  Location location;
+  Annotation annotation;
+};
+
+using Collector = std::vector<NetworkAnnotationInstance>;
+
+// This class implements the call back functions for AST Matchers. The matchers
+// are defined in RunMatchers function. When a pattern is found there,
+// the run function in this class is called back with information on the matched
+// location and description of the matched pattern.
+class NetworkAnnotationTagCallback : public MatchFinder::MatchCallback {
+ public:
+  explicit NetworkAnnotationTagCallback(Collector* collector)
+      : collector_(collector) {}
+  ~NetworkAnnotationTagCallback() override = default;
+
+  // Is called on any pattern found by ASTMathers that are defined in RunMathers
+  // function.
+  virtual void run(const MatchFinder::MatchResult& result) override {
+    const clang::CallExpr* call_expr =
+        result.Nodes.getNodeAs<clang::CallExpr>("definition_function");
+    const clang::StringLiteral* unique_id =
+        result.Nodes.getNodeAs<clang::StringLiteral>("unique_id");
+    const clang::StringLiteral* annotation_text =
+        result.Nodes.getNodeAs<clang::StringLiteral>("annotation_text");
+    const clang::FunctionDecl* ancestor =
+        result.Nodes.getNodeAs<clang::FunctionDecl>("function_context");
+
+    assert(call_expr && unique_id && annotation_text);
+
+    NetworkAnnotationInstance instance;
+    instance.annotation.unique_id = unique_id->getString();
+    instance.annotation.text = annotation_text->getString();
+
+    // Get annotation location.
+    clang::SourceLocation source_location = call_expr->getLocStart();
+    if (source_location.isMacroID()) {
+      source_location =
+          result.SourceManager->getImmediateMacroCallerLoc(source_location);
+    }
+    instance.location.file_path =
+        result.SourceManager->getFilename(source_location);
+    instance.location.line_number =
+        result.SourceManager->getSpellingLineNumber(source_location);
+    if (ancestor)
+      instance.location.function_name = ancestor->getQualifiedNameAsString();
+    else
+      instance.location.function_name = "Global Namespace";
+
+    // Trim leading "../"s from file path.
+    std::replace(instance.location.file_path.begin(),
+                 instance.location.file_path.end(), '\\', '/');
+    while (instance.location.file_path.length() > 3 &&
+           instance.location.file_path.substr(0, 3) == "../") {
+      instance.location.file_path = instance.location.file_path.substr(
+          3, instance.location.file_path.length() - 3);
+    }
+
+    collector_->push_back(instance);
+  }
+
+ private:
+  Collector* collector_;
+};
+
+// Sets up an ASTMatcher and runs clang tool to populate collector. Returns the
+// result of running the clang tool.
+int RunMatchers(clang::tooling::ClangTool* clang_tool, Collector* collector) {
+  NetworkAnnotationTagCallback callback(collector);
+  MatchFinder match_finder;
+
+  // Set up a pattern to find functions that are named
+  // [net::]DefineNetworkTrafficAnnotation and have 2 arguments of string
+  // literal type. If pattern has a function declaration as ancestor, it is
+  // marked.
+  match_finder.addMatcher(
+      callExpr(hasDeclaration(functionDecl(
+                   anyOf(hasName("DefineNetworkTrafficAnnotation"),
+                         hasName("net::DefineNetworkTrafficAnnotation")))),
+               hasArgument(0, stringLiteral().bind("unique_id")),
+               hasArgument(1, stringLiteral().bind("annotation_text")),
+               anyOf(hasAncestor(functionDecl().bind("function_context")),
+                     unless(hasAncestor(functionDecl()))))
+          .bind("definition_function"),
+      &callback);
+  std::unique_ptr<clang::tooling::FrontendActionFactory> frontend_factory =
+      clang::tooling::newFrontendActionFactory(&match_finder);
+  return clang_tool->run(frontend_factory.get());
+}
+
+}  // namespace
+
+static llvm::cl::OptionCategory ToolCategory(
+    "traffic_annotation_extractor: Extract traffic annotation texts");
+static llvm::cl::extrahelp CommonHelp(
+    clang::tooling::CommonOptionsParser::HelpMessage);
+
+int main(int argc, const char* argv[]) {
+  clang::tooling::CommonOptionsParser options(argc, argv, ToolCategory);
+  clang::tooling::ClangTool tool(options.getCompilations(),
+                                 options.getSourcePathList());
+  Collector collector;
+
+  int result = RunMatchers(&tool, &collector);
+
+  if (result != 0)
+    return result;
+
+  // For each call to "DefineNetworkTrafficAnnotation", write annotation text
+  // and relevant meta data into a separate file. The filename is uniquely
+  // generated using the file path and filename of the code including the call
+  // and its line number.
+  for (const NetworkAnnotationInstance& call : collector) {
+    llvm::outs() << "==== NEW ANNOTATION ====\n";
+    llvm::outs() << call.location.file_path << "\n";
+    llvm::outs() << call.location.function_name << "\n";
+    llvm::outs() << call.location.line_number << "\n";
+    llvm::outs() << call.annotation.unique_id << "\n";
+    llvm::outs() << call.annotation.text << "\n";
+    llvm::outs() << "==== ANNOTATION ENDS ====\n";
+  }
+
+  return 0;
+}
\ No newline at end of file
diff --git a/tools/gn/escape.cc b/tools/gn/escape.cc
index 84928ef..685a100 100644
--- a/tools/gn/escape.cc
+++ b/tools/gn/escape.cc
@@ -27,7 +27,7 @@
 //  `  a  b  c  d  e  f  g  h  i  j  k  l  m  n  o
     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 //  p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0 };
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
 
 // Append one character to the given string, escaping it for Ninja.
 //
diff --git a/tools/gn/escape_unittest.cc b/tools/gn/escape_unittest.cc
index f2b2eae..fc7692d 100644
--- a/tools/gn/escape_unittest.cc
+++ b/tools/gn/escape_unittest.cc
@@ -49,6 +49,10 @@
 
   // Some more generic shell chars.
   EXPECT_EQ("a_\\;\\<\\*b", EscapeString("a_;<*b", opts, nullptr));
+
+  // Curly braces must be escaped to avoid brace expansion on systems using
+  // bash as default shell..
+  EXPECT_EQ("\\{a,b\\}\\{c,d\\}", EscapeString("{a,b}{c,d}", opts, nullptr));
 }
 
 TEST(Escape, NinjaPreformatted) {
diff --git a/tools/traffic_annotation/auditor/BUILD.gn b/tools/traffic_annotation/auditor/BUILD.gn
new file mode 100644
index 0000000..bd3606f
--- /dev/null
+++ b/tools/traffic_annotation/auditor/BUILD.gn
@@ -0,0 +1,49 @@
+# 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/protobuf/proto_library.gni")
+
+# Works only on desktop platforms.
+assert(is_win || is_linux || is_mac)
+
+proto_library("chrome_settings_full_runtime") {
+  proto_out_dir = "/tools/traffic_annotation"
+
+  cc_include = "components/policy/proto/policy_proto_export.h"
+
+  sources = [
+    "$root_gen_dir" +
+        "/components/policy/proto/cloud_policy_full_runtime.proto",
+    "$root_gen_dir" +
+        "/components/policy/proto/chrome_settings_full_runtime.proto",
+  ]
+
+  use_protobuf_full = true
+
+  deps = [
+    "//components/policy:full_runtime_code_generate",
+    "//third_party/protobuf:protobuf_full",
+  ]
+}
+
+proto_library("traffic_annotation") {
+  sources = [
+    "../traffic_annotation.proto",
+  ]
+
+  import_dirs = [ "$root_gen_dir" + "/components/policy/proto" ]
+
+  deps = [
+    ":chrome_settings_full_runtime",
+  ]
+
+  use_protobuf_full = true
+}
+
+group("traffic_annotation_auditor") {
+  deps = [
+    ":traffic_annotation",
+    "//third_party/protobuf:protobuf_full",
+  ]
+}
diff --git a/tools/traffic_annotation/auditor/DEPS b/tools/traffic_annotation/auditor/DEPS
new file mode 100644
index 0000000..44a38e9
--- /dev/null
+++ b/tools/traffic_annotation/auditor/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+components/policy/proto",
+  "+third_party/protobuf/src/google",
+]
diff --git a/tools/traffic_annotation/auditor/README.md b/tools/traffic_annotation/auditor/README.md
new file mode 100644
index 0000000..41aafc0
--- /dev/null
+++ b/tools/traffic_annotation/auditor/README.md
@@ -0,0 +1,27 @@
+# Network Traffic Annotation Auditor
+This script runs the clang tool for extraction of Network Traffic Annotations
+from chromium source code and collects and summarizes its outputs.
+
+## Running
+1. `ninja -C [build directory] traffic_annotation_auditor`
+2. Copy * from `[build_directory]/pyproto/tools/traffic_annotation` to
+      `tools/traffic_annotation/auditor`
+
+## Usage
+`traffic_annotation_auditor.py [OPTION]... [path_filter]...`
+
+Extracts network traffic annotations from source files. If path filter(s) are
+specified, only those directories of the source will be analyzed.
+Run `traffic_annotation_auditor.py --help` for options.
+
+Example:
+  `traffic_annotation_auditor.py --build-dir=out/Debug --summary-file=
+  report.txt`
+
+
+## Running on Windows
+Before running the script as above, you should build COMPLETE chromium with
+clang with keeprsp switch as follows:
+1. `gn args [build_dir, e.g. out\Debug]`
+2. add `is_clang=true` to the opened text file and save and close it.
+3. `ninja -C [build_dir] -d keeprsp -k 1000`
diff --git a/tools/traffic_annotation/auditor/prepare_protobuf.py b/tools/traffic_annotation/auditor/prepare_protobuf.py
new file mode 100644
index 0000000..6d986aa6
--- /dev/null
+++ b/tools/traffic_annotation/auditor/prepare_protobuf.py
@@ -0,0 +1,36 @@
+# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" This code is imported with modifications from
+'//infra/recipes-py/recipe_engine/env.py' to import protobuf from third_party
+directory instead of the one installed with current python libraries."""
+
+import contextlib
+import pkg_resources
+import os
+import sys
+
+
+def PrepareProtobuf():
+  CHROME_SRC = os.path.abspath(
+      os.path.join(os.path.dirname(os.path.realpath(__file__)),
+      "..", "..", ".."))
+  THIRD_PARTY = os.path.join(CHROME_SRC, 'third_party')
+  sys.path.insert(0, os.path.join(THIRD_PARTY, 'protobuf', 'python'))
+  sys.path.insert(
+      1, os.path.join(THIRD_PARTY, 'protobuf', 'third_party', 'six'))
+
+  @contextlib.contextmanager
+  def temp_sys_path():
+    orig_path = sys.path[:]
+    try:
+      yield
+    finally:
+      sys.path = orig_path
+
+  with temp_sys_path():
+    sys.path = [THIRD_PARTY]
+    sys.modules.pop('google', None)
+    pkg_resources.declare_namespace('google')
+    pkg_resources.fixup_namespace_packages(THIRD_PARTY)
diff --git a/tools/traffic_annotation/auditor/traffic_annotation_auditor.py b/tools/traffic_annotation/auditor/traffic_annotation_auditor.py
new file mode 100755
index 0000000..811d16e
--- /dev/null
+++ b/tools/traffic_annotation/auditor/traffic_annotation_auditor.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+# Copyright (c) 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This script is used to extract network traffic annotations from Chrome.
+Please refer to README.md for running steps."""
+
+import argparse
+import os
+import subprocess
+import sys
+
+# These two lines are required to import protobuf from third_party directory
+# instead of the one installed with python.
+from prepare_protobuf import PrepareProtobuf
+PrepareProtobuf()
+
+from google.protobuf import text_format
+import traffic_annotation_pb2
+
+
+def _RunClangTool(src_dir, build_dir, path_filters):
+  """Executes the clang tool to extract annotations.
+  Args:
+    src_dir: str Path to the src directory of Chrome.
+    build_dir: str Path to the build directory.
+    path_filters: list of str List of paths to source directories for
+        extraction.
+
+  Returns:
+    raw_annotations: str Output of clang tool (extracted content and metadata of
+        annotations).
+  """
+  raw_annotations = ""
+  for path in path_filters:
+    args = [
+        src_dir + "/tools/clang/scripts/run_tool.py",
+        "--generate-compdb",
+        "traffic_annotation_extractor",
+        build_dir, path]
+    if sys.platform == "win32":
+      args.insert(0, "python")
+    command = subprocess.Popen(args, stdout=subprocess.PIPE,
+                               stderr=subprocess.PIPE)
+    stdout_text, stderr_text = command.communicate()
+    raw_annotations += stdout_text
+    if stderr_text:
+      print stderr_text
+  return raw_annotations
+
+
+def _ParsRawAnnotations(raw_annotations):
+  """Parses raw annotations texts which are received from the clang tool.
+  Args:
+    raw_annotations: str Serialization of annotations and metadata. Each
+        annotation should have the following lines:
+        1- "==== NEW ANNOTATION ===="
+        2- File path.
+        3- Name of the function including this position.
+        4- Line number.
+        5- Unique id of annotation.
+        6- Serialization of annotation text (several lines)
+        n- "==== ANNOTATION ENDS ===="
+
+  Returns:
+    annotations: ExtractedNetworkTrafficAnnotation A protobuf including all
+      extracted annotations.
+    errors: list of str List of errors.
+  """
+  annotations = traffic_annotation_pb2.ExtractedNetworkTrafficAnnotation()
+  errors = []
+
+  lines = [line.strip("\r\n") for line in raw_annotations.split("\n")]
+  current = 0
+
+  try:
+    while current < len(lines) - 1:
+      if lines[current] != "==== NEW ANNOTATION ====":
+        raise Exception(
+            "Error at line %i, expected starting new annotaion." % current)
+      if current + 5 >= len(lines):
+        raise Exception(
+            "Not enough header lines at line %i." % current)
+
+      # Extract header lines.
+      source = traffic_annotation_pb2.NetworkTrafficAnnotation.TrafficSource()
+      source.file = lines[current + 1]
+      source.function = lines[current + 2]
+      source.line = int(lines[current + 3])
+      unique_id = lines[current + 4]
+
+      # Extract serialized proto.
+      current += 5
+      annotation_text = ""
+
+      while current < len(lines):
+        current += 1
+        if lines[current - 1] == "==== ANNOTATION ENDS ====":
+          break
+        else:
+          annotation_text += lines[current - 1]
+      else:
+        raise Exception(
+          "Error at line %i, expected annotation end tag." % current)
+
+      # Process unittests and undefined tags.
+      if unique_id == "UnitTest":
+        continue
+      if unique_id == "Undefined":
+        errors.append("Annotation is not defined for file '%s', line %i." %
+            (source.file, source.line))
+        continue
+
+      # Decode serialized proto.
+      annotation_proto = traffic_annotation_pb2.NetworkTrafficAnnotation()
+      try:
+        text_format.Parse(annotation_text, annotation_proto)
+      except Exception as error:
+        errors.append("Annotation in file '%s', line %i, has error: %s" %
+            (source.file, source.line, error))
+
+      # Add new proto.
+      annotation_proto.unique_id = unique_id
+      annotation_proto.source.CopyFrom(source)
+      annotations.network_traffic_annotation.add().CopyFrom(annotation_proto)
+
+  except Exception as error:
+    errors.append(str(error))
+
+  print "Extracted %i annotations with %i errors." % \
+    (len(annotations.network_traffic_annotation), len(errors))
+  return annotations, errors
+
+
+def _WriteSummaryFile(annotations, errors, file_path):
+  """Writes extracted annotations and errors into a simple text file.
+  args:
+    annotations ExtractedNetworkTrafficAnnotation A protobuf including all
+      extracted annotations.
+    errors list of str List of all extraction errors.
+    file_path str File path to the brief summary file.
+  """
+  with open(file_path, 'w') as summary_file:
+    if errors:
+      summary_file.write("Errors:\n%s\n\n" % "\n".join(errors))
+    if len(annotations.network_traffic_annotation):
+      summary_file.write("Annotations:\n%s" % "\n---\n".join(
+          [str(a) for a in annotations.network_traffic_annotation]))
+
+
+def main():
+  parser = argparse.ArgumentParser(description='Traffic Annotation Auditor.')
+  parser.add_argument('--build-dir',
+                      help='Path to the build directory.')
+  parser.add_argument('--extractor-output',
+                      help='Optional path to the temporary file that extracted '
+                           'annotations will be stored into.')
+  parser.add_argument('--extractor-input',
+                      help='Optional path to the file that temporary extracted '
+                           'annotations are already stored in. If this is '
+                           'provided, clang tool is not run and this is used '
+                           'as input.')
+  parser.add_argument('--summary-file',
+                      help='Path to the output file.')
+  parser.add_argument('path_filters',
+                      nargs='*',
+                      help='Optional paths to filter what files the tool is '
+                           'run on.')
+  args = parser.parse_args()
+
+  if not args.summary_file:
+    print "Warning: Output file not specified."
+
+  # If a pre-extracted input file is provided, load it.
+  if args.extractor_input:
+    with open(args.extractor_input, 'r') as raw_file:
+      raw_annotations = raw_file.read()
+  else:
+    # Either extacted input file or build directory should be provided.
+    if not args.build_dir:
+      print "You must either specify the build directory to run the clang " \
+            "tool and extract annotations, or specify the input directory " \
+            "where extracted annotation files already exist.\n"
+      return 1
+
+    # Get Chrome source directory with relative path from this file.
+    chrome_source = os.path.abspath(os.path.join(os.path.dirname(
+        os.path.realpath(__file__)), "..", "..", ".."))
+    raw_annotations = _RunClangTool(chrome_source, args.build_dir,
+        args.path_filters if args.path_filters else ["./"])
+
+  if args.extractor_output:
+    with open(args.extractor_output, 'w') as raw_file:
+      raw_file.write(raw_annotations)
+
+  annotations, errors = _ParsRawAnnotations(raw_annotations)
+
+  if not annotations:
+    print "Could not extract any annotation."
+    if errors:
+      print "Errors:\n%s" % "\n".join(errors)
+    return 1
+
+  if args.summary_file:
+    _WriteSummaryFile(annotations, errors, args.summary_file)
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main())