diff --git a/DEPS b/DEPS
index afc8be0..8e502fd 100644
--- a/DEPS
+++ b/DEPS
@@ -40,15 +40,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '3befb84efc3deba472849d76af96c6f56060b918',
+  'skia_revision': 'e14349a7545e7bd1e93f4c3095db8f481939b053',
   # 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': '150b8be0e459ff9d420868443cfdc32317e93b5e',
+  'v8_revision': 'b90dca90177970979a5c9083b7ee861ddd9cdbd4',
   # 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.
-  'swarming_revision': 'ebc8dab6f8b8d79ec221c94de39a921145abd404',
+  'swarming_revision': '11e31afa5d330756ff87aa12064bb5d032896cb5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
diff --git a/base/debug/activity_tracker.h b/base/debug/activity_tracker.h
index fcd3175..719a318 100644
--- a/base/debug/activity_tracker.h
+++ b/base/debug/activity_tracker.h
@@ -162,7 +162,7 @@
   // Helper function to access an object allocated using this instance.
   template <typename T>
   T* GetAsObject(Reference ref) {
-    return allocator_->GetAsObject<T>(ref, object_type_);
+    return allocator_->GetAsObject<T>(ref);
   }
 
   // Similar to GetAsObject() but converts references to arrays of objects.
@@ -198,6 +198,12 @@
 // the |data| field. All fields must be explicitly sized types to ensure no
 // interoperability problems between 32-bit and 64-bit systems.
 struct Activity {
+  // SHA1(base::debug::Activity): Increment this if structure changes!
+  static constexpr uint32_t kPersistentTypeId = 0x99425159 + 1;
+  // Expected size for 32/64-bit check. Update this if structure changes!
+  static constexpr size_t kExpectedInstanceSize =
+      48 + 8 * kActivityCallStackSize;
+
   // The type of an activity on the stack. Activities are broken into
   // categories with the category ID taking the top 4 bits and the lower
   // bits representing an action within that category. This combination
diff --git a/base/task_scheduler/post_task.h b/base/task_scheduler/post_task.h
index 163d06d..8b3e7df 100644
--- a/base/task_scheduler/post_task.h
+++ b/base/task_scheduler/post_task.h
@@ -26,7 +26,7 @@
 // TaskScheduler must have been registered for the current process via
 // TaskScheduler::SetInstance() before the functions below are valid.
 //
-// To post a simple one-off task:
+// To post a simple one-off task with default traits:
 //     PostTask(FROM_HERE, Bind(...));
 //
 // To post a high priority one-off task to respond to a user interaction:
@@ -35,7 +35,7 @@
 //         TaskTraits().WithPriority(TaskPriority::USER_BLOCKING),
 //         Bind(...));
 //
-// To post tasks that must run in sequence:
+// To post tasks that must run in sequence with default traits:
 //     scoped_refptr<SequencedTaskRunner> task_runner =
 //         CreateSequencedTaskRunnerWithTraits(TaskTraits());
 //     task_runner.PostTask(FROM_HERE, Bind(...));
@@ -50,17 +50,18 @@
 //     task_runner.PostTask(FROM_HERE, Bind(...));
 //     task_runner.PostTask(FROM_HERE, Bind(...));
 //
-// The default TaskTraits apply to tasks that:
+// The default traits apply to tasks that:
 //     (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()),
 //     (2) prefer inheriting the current priority to specifying their own, and
 //     (3) can either block shutdown or be skipped on shutdown
-//         (barring current TaskScheduler default).
-// If those loose requirements are sufficient for your task, use
-// PostTask[AndReply], otherwise override these with explicit traits via
-// PostTaskWithTraits[AndReply].
+//         (TaskScheduler implementation is free to choose a fitting default).
+// Explicit traits must be specified for tasks for which these loose
+// requirements are not sufficient.
 //
-// Tasks posted to TaskScheduler with a delay may be coalesced (i.e. delays may
-// be adjusted to reduce the number of wakeups and hence power consumption).
+// Tasks posted through functions below will run on threads owned by the
+// registered TaskScheduler (i.e. not on the main thread). Tasks posted through
+// functions below with a delay may be coalesced (i.e. delays may be adjusted to
+// reduce the number of wakeups and hence power consumption).
 
 // Posts |task| to the TaskScheduler. Calling this is equivalent to calling
 // PostTaskWithTraits with plain TaskTraits.
diff --git a/base/task_scheduler/task_traits.h b/base/task_scheduler/task_traits.h
index 8354650..c2e3728 100644
--- a/base/task_scheduler/task_traits.h
+++ b/base/task_scheduler/task_traits.h
@@ -79,9 +79,10 @@
 class BASE_EXPORT TaskTraits {
  public:
   // Constructs a default TaskTraits for tasks that
-  //     (1) do not make blocking calls
-  //     (2) can inherit their priority from the calling context, and
-  //     (3) may block shutdown or be skipped on shutdown.
+  //     (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()),
+  //     (2) prefer inheriting the current priority to specifying their own, and
+  //     (3) can either block shutdown or be skipped on shutdown
+  //         (TaskScheduler implementation is free to choose a fitting default).
   // Tasks that require stricter guarantees and/or know the specific
   // TaskPriority appropriate for them should highlight those by requesting
   // explicit traits below.
diff --git a/base/test/scoped_task_scheduler.h b/base/test/scoped_task_scheduler.h
index a371647e..4ac2bb541b 100644
--- a/base/test/scoped_task_scheduler.h
+++ b/base/test/scoped_task_scheduler.h
@@ -21,6 +21,12 @@
 // thread where the ScopedTaskScheduler lives. The destructor runs remaining
 // BLOCK_SHUTDOWN tasks synchronously.
 //
+// Note: ScopedTaskScheduler intentionally breaks the TaskScheduler contract of
+// always running its tasks on threads it owns, instead opting to run its tasks
+// on the main thread for determinism in tests. Components that depend on
+// TaskScheduler using independent threads should use ScopedAsyncTaskScheduler
+// for testing.
+//
 // Example usage:
 //
 // In this snippet, RunUntilIdle() returns after "A" is run.
diff --git a/base/time/OWNERS b/base/time/OWNERS
index 02bdb39..ff0520a6 100644
--- a/base/time/OWNERS
+++ b/base/time/OWNERS
@@ -1 +1,3 @@
 miu@chromium.org
+
+# COMPONENT: Internals>Core
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 546bb0dbb..19942200 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -71,6 +71,11 @@
     private static final String PARAM_NTP_MAX_TILE_ROWS = "ntp_max_tile_rows";
 
     /**
+     * Experiment parameter for the number of tile title lines to show.
+     */
+    private static final String PARAM_NTP_TILE_TITLE_LINES = "ntp_tile_title_lines";
+
+    /**
      * The maximum number of tiles to try and fit in a row. On smaller screens, there may not be
      * enough space to fit all of them.
      */
@@ -800,6 +805,15 @@
                 ChromeFeatureList.NTP_CONDENSED_LAYOUT, PARAM_NTP_MAX_TILE_ROWS, defaultValue);
     }
 
+    private static int getTileTitleLines() {
+        int defaultValue = 2;
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_CONDENSED_LAYOUT)) {
+            defaultValue = 1;
+        }
+        return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                ChromeFeatureList.NTP_CONDENSED_LAYOUT, PARAM_NTP_TILE_TITLE_LINES, defaultValue);
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         if (mNewTabPageLayout != null) {
@@ -841,7 +855,7 @@
 
     @Override
     public void onTileDataChanged() {
-        mTileGroup.renderTileViews(mTileGridLayout, !mLoadHasCompleted);
+        mTileGroup.renderTileViews(mTileGridLayout, !mLoadHasCompleted, getTileTitleLines());
         mSnapshotTileGridChanged = true;
 
         // The page contents are initially hidden; otherwise they'll be drawn centered on the page
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java
index 123e01b..90d366d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGrid.java
@@ -29,6 +29,11 @@
      */
     private static final String PARAM_CHROME_HOME_MAX_TILE_ROWS = "chrome_home_max_tile_rows";
 
+    /**
+     * Experiment parameter for the number of tile title lines to show.
+     */
+    private static final String PARAM_CHROME_HOME_TILE_TITLE_LINES = "chrome_home_tile_title_lines";
+
     private final TileGroup mTileGroup;
 
     public TileGrid(SuggestionsUiDelegate uiDelegate, ContextMenuManager contextMenuManager,
@@ -78,6 +83,12 @@
                 ChromeFeatureList.CHROME_HOME, PARAM_CHROME_HOME_MAX_TILE_ROWS, defaultValue);
     }
 
+    private static int getTileTitleLines() {
+        int defaultValue = 1;
+        return ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
+                ChromeFeatureList.CHROME_HOME, PARAM_CHROME_HOME_TILE_TITLE_LINES, defaultValue);
+    }
+
     /**
      * The {@code ViewHolder} for the {@link TileGrid}.
      */
@@ -92,7 +103,7 @@
 
         public void onBindViewHolder(TileGroup tileGroup) {
             mLayout.setMaxRows(getMaxTileRows());
-            tileGroup.renderTileViews(mLayout, /* trackLoadTasks = */ false);
+            tileGroup.renderTileViews(mLayout, /* trackLoadTasks = */ false, getTileTitleLines());
         }
 
         public void updateIconView(Tile tile) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java
index 22f3541..af1c4a2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileGroup.java
@@ -192,8 +192,10 @@
      * possible because view inflation and icon loading are slow.
      * @param tileGridLayout The layout to render the tile views into.
      * @param trackLoadTasks Whether to track load tasks.
+     * @param titleLines The number of text lines to use for each tile title.
      */
-    public void renderTileViews(TileGridLayout tileGridLayout, boolean trackLoadTasks) {
+    public void renderTileViews(
+            TileGridLayout tileGridLayout, boolean trackLoadTasks, int titleLines) {
         // Map the old tile views by url so they can be reused later.
         Map<String, TileView> oldTileViews = new HashMap<>();
         int childCount = tileGridLayout.getChildCount();
@@ -227,7 +229,7 @@
             }
 
             // No view was reused, create a new one.
-            TileView tileView = buildTileView(tile, tileGridLayout, trackLoadTasks);
+            TileView tileView = buildTileView(tile, tileGridLayout, trackLoadTasks, titleLines);
 
             tileView.setOnClickListener(new OnClickListener() {
                 @Override
@@ -303,12 +305,14 @@
      * @param tile The tile that holds the data to populate the new tile view.
      * @param parentView The parent of the new tile view.
      * @param trackLoadTask Whether to track a load task.
+     * @param titleLines The number of text lines to use for each tile title.
      * @return The new tile view.
      */
-    private TileView buildTileView(Tile tile, ViewGroup parentView, boolean trackLoadTask) {
+    private TileView buildTileView(
+            Tile tile, ViewGroup parentView, boolean trackLoadTask, int titleLines) {
         TileView tileView = (TileView) LayoutInflater.from(parentView.getContext())
                                     .inflate(R.layout.tile_view, parentView, false);
-        tileView.initialize(tile);
+        tileView.initialize(tile, titleLines);
 
         LargeIconCallback iconCallback = new LargeIconCallbackImpl(tile, trackLoadTask);
         if (trackLoadTask) mObserver.onLoadTaskAdded();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java
index b9bde01af..535489c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/TileView.java
@@ -35,11 +35,13 @@
      * Initializes the view using the data held by {@code tile}. This should be called immediately
      * after inflation.
      * @param tile The tile that holds the data to populate this view.
+     * @param titleLines The number of text lines to use for the tile title.
      */
-    public void initialize(Tile tile) {
+    public void initialize(Tile tile, int titleLines) {
         mTile = tile;
-        ((TextView) findViewById(R.id.tile_view_title))
-                .setText(TitleUtil.getTitleForDisplay(mTile.getTitle(), mTile.getUrl()));
+        TextView titleView = (TextView) findViewById(R.id.tile_view_title);
+        titleView.setLines(titleLines);
+        titleView.setText(TitleUtil.getTitleForDisplay(mTile.getTitle(), mTile.getUrl()));
         renderIcon();
         findViewById(R.id.offline_badge)
                 .setVisibility(mTile.isOfflineAvailable() ? View.VISIBLE : View.GONE);
diff --git a/chrome/browser/android/history/browsing_history_bridge.cc b/chrome/browser/android/history/browsing_history_bridge.cc
index 5e45e13..9fcd8a0 100644
--- a/chrome/browser/android/history/browsing_history_bridge.cc
+++ b/chrome/browser/android/history/browsing_history_bridge.cc
@@ -94,8 +94,6 @@
       j_history_service_obj_.obj(),
       j_query_result_obj_.obj(),
       !(query_results_info->reached_beginning));
-
-  j_query_result_obj_.Release();
 }
 
 void BrowsingHistoryBridge::MarkItemForRemoval(
diff --git a/chrome/browser/browser_about_handler_unittest.cc b/chrome/browser/browser_about_handler_unittest.cc
index f9df2da..321fd720 100644
--- a/chrome/browser/browser_about_handler_unittest.cc
+++ b/chrome/browser/browser_about_handler_unittest.cc
@@ -82,6 +82,9 @@
 // Chrome OS defaults to showing Options in a window and including About in
 // Options.
 TEST_F(BrowserAboutHandlerTest, WillHandleBrowserAboutURLForOptionsChromeOS) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(features::kMaterialDesignSettings);
+
   std::string chrome_prefix(content::kChromeUIScheme);
   chrome_prefix.append(url::kStandardSchemeSeparator);
   std::vector<AboutURLTestCase> test_cases(
@@ -95,6 +98,9 @@
 
 #else
 TEST_F(BrowserAboutHandlerTest, WillHandleBrowserAboutURLForOptions) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(features::kMaterialDesignSettings);
+
   std::string chrome_prefix(content::kChromeUIScheme);
   chrome_prefix.append(url::kStandardSchemeSeparator);
   std::vector<AboutURLTestCase> test_cases(
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc
index fa57c299..e0e82fe9 100644
--- a/chrome/browser/chrome_content_browser_client_browsertest.cc
+++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -4,10 +4,12 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -32,11 +34,19 @@
         GetController().GetLastCommittedEntry();
   }
 
+  void SetUpInProcessBrowserTestFixture() override {
+    disable_md_settings_.InitAndDisableFeature(
+        features::kMaterialDesignSettings);
+  }
+
 #if defined(OS_CHROMEOS)
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kDisableSettingsWindow);
   }
 #endif
+
+ private:
+  base::test::ScopedFeatureList disable_md_settings_;
 };
 
 IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientBrowserTest,
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index 6ae5cb9..7eab36a 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -118,8 +118,12 @@
   registry->RegisterBooleanPref(prefs::kArcEnabled, false);
   registry->RegisterBooleanPref(prefs::kArcSignedIn, false);
   registry->RegisterBooleanPref(prefs::kArcTermsAccepted, false);
-  registry->RegisterBooleanPref(prefs::kArcBackupRestoreEnabled, true);
-  registry->RegisterBooleanPref(prefs::kArcLocationServiceEnabled, true);
+  // Note that ArcBackupRestoreEnabled and ArcLocationServiceEnabled prefs have
+  // to be off by default, until an explicit gesture from the user to enable
+  // them is received. This is crucial in the cases when these prefs transition
+  // from a previous managed state to the unmanaged.
+  registry->RegisterBooleanPref(prefs::kArcBackupRestoreEnabled, false);
+  registry->RegisterBooleanPref(prefs::kArcLocationServiceEnabled, false);
 }
 
 // static
@@ -706,18 +710,30 @@
     return;
   }
 
+  PrefService* const prefs = profile_->GetPrefs();
+
   // For ARC Kiosk we skip ToS because it is very likely that near the device
   // there will be no one who is eligible to accept them.
   // TODO(poromov): Move to more Kiosk dedicated set-up phase.
   if (IsArcKioskMode())
-    profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
+    prefs->SetBoolean(prefs::kArcTermsAccepted, true);
+
+  // Skip to show UI asking users to enable/disable their preference for
+  // backup-restore and location-service, if both are managed by the admin
+  // policy. Note that the ToS agreement is anyway not shown in the case of the
+  // managed ARC.
+  if (IsArcManaged() &&
+      prefs->IsManagedPreference(prefs::kArcBackupRestoreEnabled) &&
+      prefs->IsManagedPreference(prefs::kArcLocationServiceEnabled)) {
+    prefs->SetBoolean(prefs::kArcTermsAccepted, true);
+  }
 
   // If it is marked that sign in has been successfully done, then directly
   // start ARC.
-  // For testing, and for Kisok mode, we also skip ToS negotiation procedure.
+  // For testing, and for Kiosk mode, we also skip ToS negotiation procedure.
   // For backward compatibility, this check needs to be prior to the
   // kArcTermsAccepted check below.
-  if (profile_->GetPrefs()->GetBoolean(prefs::kArcSignedIn) ||
+  if (prefs->GetBoolean(prefs::kArcSignedIn) ||
       IsArcOptInVerificationDisabled() || IsArcKioskMode()) {
     StartArc();
 
@@ -751,10 +767,12 @@
   // 1) User accepted the Terms of service on OOBE flow.
   // 2) User accepted the Terms of service on Opt-in flow, but logged out
   //   before ARC sign in procedure was done. Then, logs in again.
-  if (profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
+  if (prefs->GetBoolean(prefs::kArcTermsAccepted)) {
     // Don't show UI for this progress if it was not shown.
-    if (support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE)
+    if (support_host_ &&
+        support_host_->ui_page() != ArcSupportHost::UIPage::NO_PAGE) {
       support_host_->ShowArcLoading();
+    }
     StartArcAndroidManagementCheck();
     return;
   }
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
index a2ae503..98d8e147 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <memory>
 #include <string>
+#include <tuple>
 #include <vector>
 
 #include "base/bind.h"
@@ -11,10 +12,12 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/observer_list.h"
 #include "base/run_loop.h"
+#include "base/values.h"
 #include "chrome/browser/chromeos/arc/arc_optin_uma.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/arc/optin/arc_terms_of_service_oobe_negotiator.h"
@@ -42,6 +45,7 @@
 #include "components/arc/arc_util.h"
 #include "components/arc/test/fake_arc_session.h"
 #include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
 #include "components/signin/core/account_id/account_id.h"
 #include "components/sync/model/fake_sync_change_processor.h"
 #include "components/sync/model/sync_error_factory_mock.h"
@@ -567,6 +571,75 @@
   arc_session_manager()->Shutdown();
 }
 
+class ArcSessionManagerPolicyTest
+    : public ArcSessionManagerTest,
+      public testing::WithParamInterface<std::tuple<base::Value, base::Value>> {
+ public:
+  const base::Value& backup_restore_pref_value() const {
+    return std::get<0>(GetParam());
+  }
+
+  const base::Value& location_service_pref_value() const {
+    return std::get<1>(GetParam());
+  }
+};
+
+TEST_P(ArcSessionManagerPolicyTest, SkippingTerms) {
+  sync_preferences::TestingPrefServiceSyncable* const prefs =
+      profile()->GetTestingPrefService();
+
+  // Backup-restore and location-service prefs are off by default.
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn));
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcTermsAccepted));
+
+  // Set ARC to be managed.
+  prefs->SetManagedPref(prefs::kArcEnabled, new base::Value(true));
+
+  // Assign test values to the prefs.
+  if (backup_restore_pref_value().is_bool()) {
+    prefs->SetManagedPref(prefs::kArcBackupRestoreEnabled,
+                          backup_restore_pref_value().DeepCopy());
+  }
+  if (location_service_pref_value().is_bool()) {
+    prefs->SetManagedPref(prefs::kArcLocationServiceEnabled,
+                          location_service_pref_value().DeepCopy());
+  }
+
+  arc_session_manager()->OnPrimaryUserProfilePrepared(profile());
+  EXPECT_TRUE(arc_session_manager()->IsArcPlayStoreEnabled());
+  EXPECT_TRUE(arc_session_manager()->IsArcManaged());
+
+  // Terms of Service should be skipped if both ArcBackupRestoreEnabled and
+  // ArcLocationServiceEnabled are managed.
+  const ArcSessionManager::State expected_state =
+      backup_restore_pref_value().is_bool() &&
+              location_service_pref_value().is_bool()
+          ? ArcSessionManager::State::ACTIVE
+          : ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE;
+  EXPECT_EQ(expected_state, arc_session_manager()->state());
+
+  // Managed values for the prefs are unset.
+  prefs->RemoveManagedPref(prefs::kArcBackupRestoreEnabled);
+  prefs->RemoveManagedPref(prefs::kArcLocationServiceEnabled);
+
+  // The ARC state is preserved. The prefs return to the default false values.
+  EXPECT_EQ(expected_state, arc_session_manager()->state());
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcLocationServiceEnabled));
+
+  // Stop ARC and shutdown the service.
+  prefs->RemoveManagedPref(prefs::kArcEnabled);
+  WaitForDataRemoved(ArcSessionManager::State::STOPPED);
+  arc_session_manager()->Shutdown();
+}
+
+INSTANTIATE_TEST_CASE_P(
+    ArcSessionManagerPolicyTest,
+    ArcSessionManagerPolicyTest,
+    testing::Combine(
+        testing::Values(base::Value(), base::Value(false), base::Value(true)),
+        testing::Values(base::Value(), base::Value(false), base::Value(true))));
+
 class ArcSessionManagerKioskTest : public ArcSessionManagerTestBase {
  public:
   ArcSessionManagerKioskTest() = default;
diff --git a/chrome/browser/chromeos/arc/extensions/fake_arc_support.h b/chrome/browser/chromeos/arc/extensions/fake_arc_support.h
index a0af1b5..f34b0ee0 100644
--- a/chrome/browser/chromeos/arc/extensions/fake_arc_support.h
+++ b/chrome/browser/chromeos/arc/extensions/fake_arc_support.h
@@ -32,6 +32,10 @@
   // Emulates clicking Agree button.
   void ClickAgreeButton();
 
+  bool metrics_mode() const { return metrics_mode_; }
+  bool backup_and_restore_mode() const { return backup_and_restore_mode_; }
+  bool location_service_mode() const { return location_service_mode_; }
+
   // Emulates checking preference box.
   void set_metrics_mode(bool mode) { metrics_mode_ = mode; }
   void set_backup_and_restore_mode(bool mode) {
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
index b52c9cac..008a1c4 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service.cc
@@ -65,12 +65,15 @@
   return !host->empty() && *port;
 }
 
+PrefService* GetPrefs() {
+  return ProfileManager::GetActiveUserProfile()->GetPrefs();
+}
+
 // Returns whether kProxy pref proxy config is applied.
 bool IsPrefProxyConfigApplied() {
   net::ProxyConfig config;
-  Profile* profile = ProfileManager::GetActiveUserProfile();
   return PrefProxyConfigTrackerImpl::PrefPrecedes(
-      PrefProxyConfigTrackerImpl::ReadPrefConfig(profile->GetPrefs(), &config));
+      PrefProxyConfigTrackerImpl::ReadPrefConfig(GetPrefs(), &config));
 }
 
 }  // namespace
@@ -112,18 +115,23 @@
   // Stops listening for Chrome settings changes.
   void StopObservingSettingsChanges();
 
+  // Retrieves Chrome's state for the settings that need to be synced on the
+  // initial Android boot and send it to Android.
+  void SyncInitialSettings() const;
   // Retrieves Chrome's state for the settings that need to be synced on each
   // Android boot and send it to Android.
   void SyncRuntimeSettings() const;
-  // Send settings that need to be synced only on Android first start to
-  // Android.
+  // Determine whether a particular setting needs to be synced to Android.
+  // Keep these lines ordered lexicographically.
+  bool ShouldSyncBackupEnabled() const;
+  bool ShouldSyncLocationServiceEnabled() const;
+  // Send particular settings to Android.
   // Keep these lines ordered lexicographically.
   void SyncAccessibilityLargeMouseCursorEnabled() const;
   void SyncAccessibilityVirtualKeyboardEnabled() const;
   void SyncBackupEnabled() const;
   void SyncFocusHighlightEnabled() const;
   void SyncFontSize() const;
-  void SyncInitialSettings() const;
   void SyncLocale() const;
   void SyncLocationServiceEnabled() const;
   void SyncProxySettings() const;
@@ -204,10 +212,11 @@
     SyncSpokenFeedbackEnabled();
   } else if (pref_name == prefs::kAccessibilityVirtualKeyboardEnabled) {
     SyncAccessibilityVirtualKeyboardEnabled();
+  } else if (pref_name == prefs::kArcBackupRestoreEnabled) {
+    if (ShouldSyncBackupEnabled())
+      SyncBackupEnabled();
   } else if (pref_name == prefs::kArcLocationServiceEnabled) {
-    const PrefService* const prefs =
-        ProfileManager::GetActiveUserProfile()->GetPrefs();
-    if (prefs->IsManagedPreference(prefs::kArcLocationServiceEnabled))
+    if (ShouldSyncLocationServiceEnabled())
       SyncLocationServiceEnabled();
   } else if (pref_name == prefs::kUse24HourClock) {
     SyncUse24HourClock();
@@ -249,8 +258,7 @@
 }
 
 void ArcSettingsServiceImpl::StartObservingSettingsChanges() {
-  Profile* profile = ProfileManager::GetActiveUserProfile();
-  registrar_.Init(profile->GetPrefs());
+  registrar_.Init(GetPrefs());
 
   // Keep these lines ordered lexicographically.
   AddPrefToObserve(prefs::kAccessibilityFocusHighlightEnabled);
@@ -293,6 +301,12 @@
       this, FROM_HERE);
 }
 
+void ArcSettingsServiceImpl::SyncInitialSettings() const {
+  // Keep these lines ordered lexicographically.
+  SyncBackupEnabled();
+  SyncLocationServiceEnabled();
+}
+
 void ArcSettingsServiceImpl::SyncRuntimeSettings() const {
   // Keep these lines ordered lexicographically.
   SyncAccessibilityLargeMouseCursorEnabled();
@@ -306,14 +320,28 @@
   SyncTimeZone();
   SyncUse24HourClock();
 
-  const PrefService* const prefs =
-      ProfileManager::GetActiveUserProfile()->GetPrefs();
-  if (prefs->IsManagedPreference(prefs::kArcBackupRestoreEnabled))
+  if (ShouldSyncBackupEnabled())
     SyncBackupEnabled();
-  if (prefs->IsManagedPreference(prefs::kArcLocationServiceEnabled))
+  if (ShouldSyncLocationServiceEnabled())
     SyncLocationServiceEnabled();
 }
 
+bool ArcSettingsServiceImpl::ShouldSyncBackupEnabled() const {
+  // Always sync the managed setting. Also sync when the pref is unset, which
+  // normally happens once after the pref changes from the managed state to
+  // unmanaged.
+  return GetPrefs()->IsManagedPreference(prefs::kArcBackupRestoreEnabled) ||
+         !GetPrefs()->HasPrefPath(prefs::kArcBackupRestoreEnabled);
+}
+
+bool ArcSettingsServiceImpl::ShouldSyncLocationServiceEnabled() const {
+  // Always sync the managed setting. Also sync when the pref is unset, which
+  // normally happens once after the pref changes from the managed state to
+  // unmanaged.
+  return GetPrefs()->IsManagedPreference(prefs::kArcLocationServiceEnabled) ||
+         !GetPrefs()->HasPrefPath(prefs::kArcLocationServiceEnabled);
+}
+
 void ArcSettingsServiceImpl::SyncAccessibilityLargeMouseCursorEnabled() const {
   SendBoolPrefSettingsBroadcast(
       prefs::kAccessibilityLargeCursorEnabled,
@@ -330,6 +358,15 @@
   SendBoolPrefSettingsBroadcast(
       prefs::kArcBackupRestoreEnabled,
       "org.chromium.arc.intent_helper.SET_BACKUP_ENABLED");
+  if (GetPrefs()->IsManagedPreference(prefs::kArcBackupRestoreEnabled)) {
+    // Unset the user pref so that if the pref becomes unmanaged at some point,
+    // this change will be synced.
+    GetPrefs()->ClearPref(prefs::kArcBackupRestoreEnabled);
+  } else if (!GetPrefs()->HasPrefPath(prefs::kArcBackupRestoreEnabled)) {
+    // Set the pref value in order to prevent the subsequent syncing. The
+    // "false" value is a safe default from the legal/privacy perspective.
+    GetPrefs()->SetBoolean(prefs::kArcBackupRestoreEnabled, false);
+  }
 }
 
 void ArcSettingsServiceImpl::SyncFocusHighlightEnabled() const {
@@ -352,11 +389,6 @@
                         extras);
 }
 
-void ArcSettingsServiceImpl::SyncInitialSettings() const {
-  SyncBackupEnabled();
-  SyncLocationServiceEnabled();
-}
-
 void ArcSettingsServiceImpl::SyncLocale() const {
   const PrefService::Preference* pref =
       registrar_.prefs()->FindPreference(prefs::kApplicationLocale);
@@ -373,13 +405,21 @@
   SendBoolPrefSettingsBroadcast(
       prefs::kArcLocationServiceEnabled,
       "org.chromium.arc.intent_helper.SET_LOCATION_SERVICE_ENABLED");
+  if (GetPrefs()->IsManagedPreference(prefs::kArcLocationServiceEnabled)) {
+    // Unset the user pref so that if the pref becomes unmanaged at some point,
+    // this change will be synced.
+    GetPrefs()->ClearPref(prefs::kArcLocationServiceEnabled);
+  } else if (!GetPrefs()->HasPrefPath(prefs::kArcLocationServiceEnabled)) {
+    // Set the pref value in order to prevent the subsequent syncing. The
+    // "false" value is a safe default from the legal/privacy perspective.
+    GetPrefs()->SetBoolean(prefs::kArcLocationServiceEnabled, false);
+  }
 }
 
 void ArcSettingsServiceImpl::SyncProxySettings() const {
   std::unique_ptr<ProxyConfigDictionary> proxy_config_dict =
       chromeos::ProxyConfigServiceImpl::GetActiveProxyConfigDictionary(
-          ProfileManager::GetActiveUserProfile()->GetPrefs(),
-          g_browser_process->local_state());
+          GetPrefs(), g_browser_process->local_state());
   if (!proxy_config_dict)
     return;
 
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
index bdc2589..b6af8900 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_settings_service_browsertest.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/chromeos/arc/intent_helper/arc_settings_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill_profile_client.h"
@@ -174,6 +175,8 @@
 
 constexpr char kONCPacUrl[] = "http://domain.com/x";
 
+constexpr char kBackupBroadcastAction[] =
+    "org.chromium.arc.intent_helper.SET_BACKUP_ENABLED";
 constexpr char kLocationServiceBroadcastAction[] =
     "org.chromium.arc.intent_helper.SET_LOCATION_SERVICE_ENABLED";
 constexpr char kSetProxyBroadcastAction[] =
@@ -317,7 +320,76 @@
   DISALLOW_COPY_AND_ASSIGN(ArcSettingsServiceTest);
 };
 
+IN_PROC_BROWSER_TEST_F(ArcSettingsServiceTest, BackupRestorePolicyTest) {
+  PrefService* const prefs = browser()->profile()->GetPrefs();
+
+  // Set the user pref as initially enabled.
+  prefs->SetBoolean(prefs::kArcBackupRestoreEnabled, true);
+  EXPECT_TRUE(prefs->GetBoolean(prefs::kArcBackupRestoreEnabled));
+
+  fake_intent_helper_instance_->clear_broadcasts();
+
+  // The policy is set to false.
+  policy::PolicyMap policy;
+  policy.Set(policy::key::kArcBackupRestoreEnabled,
+             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+             policy::POLICY_SOURCE_CLOUD, base::MakeUnique<base::Value>(false),
+             nullptr);
+  UpdatePolicy(policy);
+
+  // The pref is disabled and managed, and the corresponding broadcast is sent
+  // at least once.
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  EXPECT_TRUE(prefs->IsManagedPreference(prefs::kArcBackupRestoreEnabled));
+  base::DictionaryValue expected_broadcast_extras;
+  expected_broadcast_extras.SetBoolean("enabled", false);
+  expected_broadcast_extras.SetBoolean("managed", true);
+  EXPECT_GE(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
+                            kBackupBroadcastAction, &expected_broadcast_extras),
+            1);
+
+  fake_intent_helper_instance_->clear_broadcasts();
+
+  // The policy is set to true.
+  policy.Set(policy::key::kArcBackupRestoreEnabled,
+             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+             policy::POLICY_SOURCE_CLOUD, base::MakeUnique<base::Value>(true),
+             nullptr);
+  UpdatePolicy(policy);
+
+  // The pref is enabled and managed, and the corresponding broadcast is sent at
+  // least once.
+  EXPECT_TRUE(prefs->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  EXPECT_TRUE(prefs->IsManagedPreference(prefs::kArcBackupRestoreEnabled));
+  expected_broadcast_extras.SetBoolean("enabled", true);
+  EXPECT_GE(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
+                            kBackupBroadcastAction, &expected_broadcast_extras),
+            1);
+
+  fake_intent_helper_instance_->clear_broadcasts();
+
+  // The policy is unset.
+  policy.Erase(policy::key::kArcBackupRestoreEnabled);
+  UpdatePolicy(policy);
+
+  // The pref is disabled and unmanaged, and the corresponding broadcast is
+  // sent.
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  EXPECT_FALSE(prefs->IsManagedPreference(prefs::kArcBackupRestoreEnabled));
+  expected_broadcast_extras.SetBoolean("enabled", false);
+  expected_broadcast_extras.SetBoolean("managed", false);
+  EXPECT_EQ(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
+                            kBackupBroadcastAction, &expected_broadcast_extras),
+            1);
+}
+
 IN_PROC_BROWSER_TEST_F(ArcSettingsServiceTest, LocationServicePolicyTest) {
+  PrefService* const prefs = browser()->profile()->GetPrefs();
+
+  // Set the user pref as initially enabled.
+  prefs->SetBoolean(prefs::kArcLocationServiceEnabled, true);
+  EXPECT_TRUE(prefs->GetBoolean(prefs::kArcLocationServiceEnabled));
+
   fake_intent_helper_instance_->clear_broadcasts();
 
   // The policy is set to false.
@@ -328,11 +400,14 @@
              nullptr);
   UpdatePolicy(policy);
 
-  // The broadcast is sent which says that the pref is disabled and managed.
+  // The pref is disabled and managed, and the corresponding broadcast is sent
+  // at least once.
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcLocationServiceEnabled));
+  EXPECT_TRUE(prefs->IsManagedPreference(prefs::kArcLocationServiceEnabled));
   base::DictionaryValue expected_broadcast_extras;
   expected_broadcast_extras.SetBoolean("enabled", false);
   expected_broadcast_extras.SetBoolean("managed", true);
-  EXPECT_EQ(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
+  EXPECT_GE(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
                             kLocationServiceBroadcastAction,
                             &expected_broadcast_extras),
             1);
@@ -346,8 +421,28 @@
              nullptr);
   UpdatePolicy(policy);
 
-  // The broadcast is sent which says that the pref is enabled and managed.
+  // The pref is enabled and managed, and the corresponding broadcast is sent at
+  // least once.
+  EXPECT_TRUE(prefs->GetBoolean(prefs::kArcLocationServiceEnabled));
+  EXPECT_TRUE(prefs->IsManagedPreference(prefs::kArcLocationServiceEnabled));
   expected_broadcast_extras.SetBoolean("enabled", true);
+  EXPECT_GE(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
+                            kLocationServiceBroadcastAction,
+                            &expected_broadcast_extras),
+            1);
+
+  fake_intent_helper_instance_->clear_broadcasts();
+
+  // The policy is unset.
+  policy.Erase(policy::key::kArcLocationServiceEnabled);
+  UpdatePolicy(policy);
+
+  // The pref is disabled and unmanaged, and the corresponding broadcast is
+  // sent.
+  EXPECT_FALSE(prefs->GetBoolean(prefs::kArcLocationServiceEnabled));
+  EXPECT_FALSE(prefs->IsManagedPreference(prefs::kArcLocationServiceEnabled));
+  expected_broadcast_extras.SetBoolean("enabled", false);
+  expected_broadcast_extras.SetBoolean("managed", false);
   EXPECT_EQ(CountBroadcasts(fake_intent_helper_instance_->broadcasts(),
                             kLocationServiceBroadcastAction,
                             &expected_broadcast_extras),
diff --git a/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.cc b/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.cc
index 11972d6..8ae3b0f 100644
--- a/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.cc
+++ b/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.cc
@@ -72,14 +72,26 @@
 }
 
 void ArcOptInPreferenceHandler::SendBackupAndRestoreMode() {
+  // Override the pref default to the true value, in order to encourage users to
+  // consent with it during OptIn flow.
+  const bool enabled =
+      pref_service_->HasPrefPath(prefs::kArcBackupRestoreEnabled)
+          ? pref_service_->GetBoolean(prefs::kArcBackupRestoreEnabled)
+          : true;
   observer_->OnBackupAndRestoreModeChanged(
-      pref_service_->GetBoolean(prefs::kArcBackupRestoreEnabled),
+      enabled,
       pref_service_->IsManagedPreference(prefs::kArcBackupRestoreEnabled));
 }
 
 void ArcOptInPreferenceHandler::SendLocationServicesMode() {
+  // Override the pref default to the true value, in order to encourage users to
+  // consent with it during OptIn flow.
+  const bool enabled =
+      pref_service_->HasPrefPath(prefs::kArcLocationServiceEnabled)
+          ? pref_service_->GetBoolean(prefs::kArcLocationServiceEnabled)
+          : true;
   observer_->OnLocationServicesModeChanged(
-      pref_service_->GetBoolean(prefs::kArcLocationServiceEnabled),
+      enabled,
       pref_service_->IsManagedPreference(prefs::kArcLocationServiceEnabled));
 }
 
diff --git a/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.h b/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.h
index 0d4ec31..2cc6d3b9 100644
--- a/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.h
+++ b/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler.h
@@ -20,6 +20,10 @@
 // observes changes there. Changes in preferences and metrics mode are passed to
 // external consumer via ArcOptInPreferenceHandlerObserver. Once started it
 // immediately sends current state of metrics mode and preferences.
+//
+// Note that the preferences and metrics mode passed by this class should only
+// be used for the OptIn flow, as this class overrides some of the defaults in
+// order to encourage users to consent with the settings.
 class ArcOptInPreferenceHandler {
  public:
   ArcOptInPreferenceHandler(ArcOptInPreferenceHandlerObserver* observer,
diff --git a/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler_observer.h b/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler_observer.h
index 56d9699..3d121f3 100644
--- a/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler_observer.h
+++ b/chrome/browser/chromeos/arc/optin/arc_optin_preference_handler_observer.h
@@ -10,11 +10,11 @@
 // Notifies about changes in ARC related preferences and metrics mode.
 class ArcOptInPreferenceHandlerObserver {
  public:
-  // Notifies metrics mode has been changed.
+  // Notifies that the metrics mode has been changed.
   virtual void OnMetricsModeChanged(bool enabled, bool managed) = 0;
-  // Notifies use backup and restore preference has been changed.
+  // Notifies that the backup and restore mode has been changed.
   virtual void OnBackupAndRestoreModeChanged(bool enabled, bool managed) = 0;
-  // Notifies location service consent preference has been changed.
+  // Notifies that the location service mode has been changed.
   virtual void OnLocationServicesModeChanged(bool enabled, bool managed) = 0;
 
   virtual ~ArcOptInPreferenceHandlerObserver() = default;
diff --git a/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc b/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc
index ce080c8d..78eb27f 100644
--- a/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc
+++ b/chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "base/values.h"
 #include "chrome/browser/chromeos/arc/arc_support_host.h"
 #include "chrome/browser/chromeos/arc/extensions/fake_arc_support.h"
 #include "chrome/browser/chromeos/arc/optin/arc_terms_of_service_default_negotiator.h"
@@ -18,6 +19,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/prefs/pref_service.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -34,8 +36,6 @@
             new chromeos::FakeChromeUserManager());
 
     profile_ = base::MakeUnique<TestingProfile>();
-    profile_->GetPrefs()->SetBoolean(prefs::kArcBackupRestoreEnabled, false);
-    profile_->GetPrefs()->SetBoolean(prefs::kArcLocationServiceEnabled, false);
 
     support_host_ = base::MakeUnique<ArcSupportHost>(profile_.get());
     fake_arc_support_ = base::MakeUnique<FakeArcSupport>(support_host_.get());
@@ -51,7 +51,7 @@
     user_manager_enabler_.reset();
   }
 
-  Profile* profile() { return profile_.get(); }
+  TestingProfile* profile() { return profile_.get(); }
   ArcSupportHost* support_host() { return support_host_.get(); }
   FakeArcSupport* fake_arc_support() { return fake_arc_support_.get(); }
   ArcTermsOfServiceNegotiator* negotiator() { return negotiator_.get(); }
@@ -112,10 +112,32 @@
   EXPECT_EQ(status, Status::PENDING);
   EXPECT_EQ(fake_arc_support()->ui_page(), ArcSupportHost::UIPage::TERMS);
 
-  // Check the preference related checkbox.
-  fake_arc_support()->set_metrics_mode(true);
-  fake_arc_support()->set_backup_and_restore_mode(true);
-  fake_arc_support()->set_location_service_mode(true);
+  // By default, the preference related checkboxes are checked, despite that
+  // the preferences default to false.
+  EXPECT_FALSE(
+      profile()->GetPrefs()->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  EXPECT_FALSE(
+      profile()->GetPrefs()->GetBoolean(prefs::kArcLocationServiceEnabled));
+  EXPECT_TRUE(fake_arc_support()->backup_and_restore_mode());
+  EXPECT_TRUE(fake_arc_support()->location_service_mode());
+
+  // The preferences are assigned to the managed false value, and the
+  // corresponding checkboxes are unchecked.
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kArcBackupRestoreEnabled, new base::Value(false));
+  EXPECT_FALSE(fake_arc_support()->backup_and_restore_mode());
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kArcLocationServiceEnabled, new base::Value(false));
+  EXPECT_FALSE(fake_arc_support()->location_service_mode());
+
+  // The managed preference values are removed, and the corresponding checkboxes
+  // are checked again.
+  profile()->GetTestingPrefService()->RemoveManagedPref(
+      prefs::kArcBackupRestoreEnabled);
+  EXPECT_TRUE(fake_arc_support()->backup_and_restore_mode());
+  profile()->GetTestingPrefService()->RemoveManagedPref(
+      prefs::kArcLocationServiceEnabled);
+  EXPECT_TRUE(fake_arc_support()->location_service_mode());
 
   // Make sure preference values are not yet updated.
   EXPECT_FALSE(
@@ -135,6 +157,41 @@
       profile()->GetPrefs()->GetBoolean(prefs::kArcLocationServiceEnabled));
 }
 
+TEST_F(ArcTermsOfServiceDefaultNegotiatorTest, AcceptWithUnchecked) {
+  // Show Terms of service page.
+  Status status = Status::PENDING;
+  negotiator()->StartNegotiation(UpdateStatusCallback(&status));
+
+  // TERMS page should be shown.
+  EXPECT_EQ(status, Status::PENDING);
+  EXPECT_EQ(fake_arc_support()->ui_page(), ArcSupportHost::UIPage::TERMS);
+
+  // Override the preferences from the default values to true.
+  profile()->GetPrefs()->SetBoolean(prefs::kArcBackupRestoreEnabled, true);
+  profile()->GetPrefs()->SetBoolean(prefs::kArcLocationServiceEnabled, true);
+
+  // Uncheck the preference related checkboxes.
+  fake_arc_support()->set_backup_and_restore_mode(false);
+  fake_arc_support()->set_location_service_mode(false);
+
+  // Make sure preference values are not yet updated.
+  EXPECT_TRUE(
+      profile()->GetPrefs()->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  EXPECT_TRUE(
+      profile()->GetPrefs()->GetBoolean(prefs::kArcLocationServiceEnabled));
+
+  // Click the "AGREE" button so that the callback should be invoked
+  // with |agreed| = true.
+  fake_arc_support()->ClickAgreeButton();
+  EXPECT_EQ(status, Status::ACCEPTED);
+
+  // Make sure preference values are now updated.
+  EXPECT_FALSE(
+      profile()->GetPrefs()->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  EXPECT_FALSE(
+      profile()->GetPrefs()->GetBoolean(prefs::kArcLocationServiceEnabled));
+}
+
 TEST_F(ArcTermsOfServiceDefaultNegotiatorTest, Cancel) {
   // Show Terms of service page.
   Status status = Status::PENDING;
diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc
index e3172a4..cf47b9d 100644
--- a/chrome/browser/download/download_shelf.cc
+++ b/chrome/browser/download/download_shelf.cc
@@ -149,12 +149,12 @@
   }
 }
 
-void DownloadShelf::Show() {
+void DownloadShelf::Open() {
   if (is_hidden_) {
     should_show_on_unhide_ = true;
     return;
   }
-  DoShow();
+  DoOpen();
 }
 
 void DownloadShelf::Close(CloseReason reason) {
@@ -171,7 +171,7 @@
   is_hidden_ = true;
   if (IsShowing()) {
     should_show_on_unhide_ = true;
-    DoClose(AUTOMATIC);
+    DoHide();
   }
 }
 
@@ -181,7 +181,7 @@
   is_hidden_ = false;
   if (should_show_on_unhide_) {
     should_show_on_unhide_ = false;
-    DoShow();
+    DoUnhide();
   }
 }
 
@@ -203,7 +203,7 @@
 
   if (is_hidden_)
     Unhide();
-  Show();
+  Open();
   DoAddDownload(download);
 
   // browser() can be NULL for tests.
diff --git a/chrome/browser/download/download_shelf.h b/chrome/browser/download/download_shelf.h
index aefee262..aa4467f 100644
--- a/chrome/browser/download/download_shelf.h
+++ b/chrome/browser/download/download_shelf.h
@@ -95,7 +95,7 @@
   virtual bool IsClosing() const = 0;
 
   // Opens the shelf.
-  void Show();
+  void Open();
 
   // Closes the shelf.
   void Close(CloseReason reason);
@@ -114,8 +114,10 @@
 
  protected:
   virtual void DoAddDownload(content::DownloadItem* download) = 0;
-  virtual void DoShow() = 0;
+  virtual void DoOpen() = 0;
   virtual void DoClose(CloseReason reason) = 0;
+  virtual void DoHide() = 0;
+  virtual void DoUnhide() = 0;
 
   // Time delay to wait before adding a transient download to the shelf.
   // Protected virtual for testing.
diff --git a/chrome/browser/download/download_shelf_unittest.cc b/chrome/browser/download/download_shelf_unittest.cc
index c59e6a0..097cc82 100644
--- a/chrome/browser/download/download_shelf_unittest.cc
+++ b/chrome/browser/download/download_shelf_unittest.cc
@@ -94,7 +94,7 @@
 } // namespace
 
 TEST_F(DownloadShelfTest, ClosesShelfWhenHidden) {
-  shelf()->Show();
+  shelf()->Open();
   EXPECT_TRUE(shelf()->IsShowing());
   shelf()->Hide();
   EXPECT_FALSE(shelf()->IsShowing());
@@ -103,7 +103,7 @@
 }
 
 TEST_F(DownloadShelfTest, CloseWhileHiddenPreventsShowOnUnhide) {
-  shelf()->Show();
+  shelf()->Open();
   shelf()->Hide();
   shelf()->Close(DownloadShelf::AUTOMATIC);
   shelf()->Unhide();
@@ -117,7 +117,7 @@
 }
 
 TEST_F(DownloadShelfTest, AddDownloadWhileHiddenUnhides) {
-  shelf()->Show();
+  shelf()->Open();
   shelf()->Hide();
   shelf()->AddDownload(download_item());
   EXPECT_TRUE(shelf()->IsShowing());
diff --git a/chrome/browser/download/test_download_shelf.cc b/chrome/browser/download/test_download_shelf.cc
index 9538b7cd..80711138 100644
--- a/chrome/browser/download/test_download_shelf.cc
+++ b/chrome/browser/download/test_download_shelf.cc
@@ -47,7 +47,7 @@
   did_add_download_ = true;
 }
 
-void TestDownloadShelf::DoShow() {
+void TestDownloadShelf::DoOpen() {
   is_showing_ = true;
 }
 
@@ -55,6 +55,14 @@
   is_showing_ = false;
 }
 
+void TestDownloadShelf::DoHide() {
+  is_showing_ = false;
+}
+
+void TestDownloadShelf::DoUnhide() {
+  is_showing_ = true;
+}
+
 base::TimeDelta TestDownloadShelf::GetTransientDownloadShowDelay() {
   return base::TimeDelta();
 }
diff --git a/chrome/browser/download/test_download_shelf.h b/chrome/browser/download/test_download_shelf.h
index 7617c05..e00dbb6 100644
--- a/chrome/browser/download/test_download_shelf.h
+++ b/chrome/browser/download/test_download_shelf.h
@@ -34,8 +34,10 @@
 
  protected:
   void DoAddDownload(content::DownloadItem* download) override;
-  void DoShow() override;
+  void DoOpen() override;
   void DoClose(CloseReason reason) override;
+  void DoHide() override;
+  void DoUnhide() override;
   base::TimeDelta GetTransientDownloadShowDelay() override;
   content::DownloadManager* GetDownloadManager() override;
 
diff --git a/chrome/browser/extensions/api/cast_streaming/OWNERS b/chrome/browser/extensions/api/cast_streaming/OWNERS
index 586a2f54..41c70ee 100644
--- a/chrome/browser/extensions/api/cast_streaming/OWNERS
+++ b/chrome/browser/extensions/api/cast_streaming/OWNERS
@@ -1,2 +1,4 @@
 hubbe@chromium.org
 miu@chromium.org
+
+# COMPONENT: Internals>Cast>Streaming
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index b4126908..210f429 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -15,7 +15,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/threading/sequenced_worker_pool.h"
+#include "base/task_scheduler/post_task.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/api/developer_private/developer_private_mangle.h"
 #include "chrome/browser/extensions/api/developer_private/entry_picker.h"
@@ -1204,9 +1204,9 @@
   if (properties.path_suffix == kManifestFile && !properties.manifest_key)
     return RespondNow(Error(kManifestKeyIsRequiredError));
 
-  base::PostTaskAndReplyWithResult(
-      content::BrowserThread::GetBlockingPool(),
-      FROM_HERE,
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, base::TaskTraits().MayBlock().WithPriority(
+                     base::TaskPriority::USER_VISIBLE),
       base::Bind(&ReadFileToString, extension->path().Append(path_suffix)),
       base::Bind(&DeveloperPrivateRequestFileSourceFunction::Finish, this));
 
diff --git a/chrome/browser/extensions/api/tab_capture/OWNERS b/chrome/browser/extensions/api/tab_capture/OWNERS
index a24599a..100b4d087 100644
--- a/chrome/browser/extensions/api/tab_capture/OWNERS
+++ b/chrome/browser/extensions/api/tab_capture/OWNERS
@@ -1,3 +1,5 @@
 hubbe@chromium.org
 justinlin@chromium.org
 miu@chromium.org
+
+# COMPONENT: UI>Browser>TabCapture
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
index e00df839..88f3984 100644
--- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
+++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/path_service.h"
 #include "base/strings/string_piece.h"
@@ -364,8 +365,12 @@
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   ASSERT_TRUE(content::WaitForLoadStop(web_contents));
-  ASSERT_EQ("chrome://settings/contentExceptions#notifications",
-            web_contents->GetLastCommittedURL().spec());
+
+  std::string url = web_contents->GetLastCommittedURL().spec();
+  if (base::FeatureList::IsEnabled(features::kMaterialDesignSettings))
+    ASSERT_EQ("chrome://settings/content/notifications", url);
+  else
+    ASSERT_EQ("chrome://settings/contentExceptions#notifications", url);
 }
 
 IN_PROC_BROWSER_TEST_F(PlatformNotificationServiceBrowserTest,
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 292b004..fda3b28 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -31,6 +31,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/test_file_util.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/time/time.h"
@@ -83,6 +84,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_constants.h"
@@ -4168,13 +4170,17 @@
 
 // Test ArcBackupRestoreEnabled policy.
 IN_PROC_BROWSER_TEST_F(ArcPolicyTest, ArcBackupRestoreEnabled) {
-  const PrefService* const pref = browser()->profile()->GetPrefs();
+  PrefService* const pref = browser()->profile()->GetPrefs();
 
-  // ARC Backup & Restore is switched on by default.
-  EXPECT_TRUE(pref->GetBoolean(prefs::kArcBackupRestoreEnabled));
+  // ARC Backup & Restore is switched off by default.
+  EXPECT_FALSE(pref->GetBoolean(prefs::kArcBackupRestoreEnabled));
   EXPECT_FALSE(pref->IsManagedPreference(prefs::kArcBackupRestoreEnabled));
 
-  // Disable ARC Backup & Restore.
+  // Switch on ARC Backup & Restore in the user prefs.
+  pref->SetBoolean(prefs::kArcBackupRestoreEnabled, true);
+  EXPECT_TRUE(pref->GetBoolean(prefs::kArcBackupRestoreEnabled));
+
+  // Disable ARC Backup & Restore through the policy.
   PolicyMap policies;
   policies.Set(key::kArcBackupRestoreEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
@@ -4183,7 +4189,7 @@
   EXPECT_FALSE(pref->GetBoolean(prefs::kArcBackupRestoreEnabled));
   EXPECT_TRUE(pref->IsManagedPreference(prefs::kArcBackupRestoreEnabled));
 
-  // Enable ARC Backup & Restore.
+  // Enable ARC Backup & Restore through the policy.
   policies.Set(key::kArcBackupRestoreEnabled, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
                base::MakeUnique<base::FundamentalValue>(true), nullptr);
@@ -4195,7 +4201,7 @@
 // Test ArcLocationServiceEnabled policy and its interplay with the
 // DefaultGeolocationSetting policy.
 IN_PROC_BROWSER_TEST_F(ArcPolicyTest, ArcLocationServiceEnabled) {
-  const PrefService* const pref = browser()->profile()->GetPrefs();
+  PrefService* const pref = browser()->profile()->GetPrefs();
 
   // Values of the ArcLocationServiceEnabled policy to be tested.
   const std::vector<base::Value> test_policy_values = {
@@ -4211,6 +4217,14 @@
       base::FundamentalValue(3),  // 'AskGeolocation'
   };
 
+  // The pref is switched off by default.
+  EXPECT_FALSE(pref->GetBoolean(prefs::kArcLocationServiceEnabled));
+  EXPECT_FALSE(pref->IsManagedPreference(prefs::kArcLocationServiceEnabled));
+
+  // Switch on the pref in the user prefs.
+  pref->SetBoolean(prefs::kArcLocationServiceEnabled, true);
+  EXPECT_TRUE(pref->GetBoolean(prefs::kArcLocationServiceEnabled));
+
   for (const auto& test_policy_value : test_policy_values) {
     for (const auto& test_default_geo_policy_value :
          test_default_geo_policy_values) {
@@ -4352,6 +4366,9 @@
 };
 
 IN_PROC_BROWSER_TEST_F(ChromeOSPolicyTest, SystemTimezoneAutomaticDetection) {
+  base::test::ScopedFeatureList disable_md_settings;
+  disable_md_settings.InitAndDisableFeature(features::kMaterialDesignSettings);
+
   ui_test_utils::NavigateToURL(browser(), GURL("chrome://settings"));
   chromeos::system::TimeZoneResolverManager* manager =
       g_browser_process->platform_part()->GetTimezoneResolverManager();
diff --git a/chrome/browser/renderer_host/chrome_extension_message_filter.cc b/chrome/browser/renderer_host/chrome_extension_message_filter.cc
index 1870743..2306f56 100644
--- a/chrome/browser/renderer_host/chrome_extension_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_extension_message_filter.cc
@@ -29,8 +29,10 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/api/messaging/message.h"
 #include "extensions/common/extension_messages.h"
+#include "extensions/common/extension_set.h"
 #include "extensions/common/file_util.h"
 #include "extensions/common/manifest_handlers/default_locale_handler.h"
+#include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "extensions/common/message_bundle.h"
 
 using content::BrowserThread;
@@ -200,24 +202,66 @@
 
 void ChromeExtensionMessageFilter::OnGetExtMessageBundle(
     const std::string& extension_id, IPC::Message* reply_msg) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  const extensions::ExtensionSet& extension_set =
+      extension_info_map_->extensions();
+  const extensions::Extension* extension = extension_set.GetByID(extension_id);
+
+  if (!extension) {  // The extension has gone.
+    ExtensionHostMsg_GetMessageBundle::WriteReplyParams(
+        reply_msg, extensions::MessageBundle::SubstitutionMap());
+    Send(reply_msg);
+    return;
+  }
+
+  const std::string& default_locale =
+      extensions::LocaleInfo::GetDefaultLocale(extension);
+  if (default_locale.empty()) {
+    // A little optimization: send the answer here to avoid an extra thread hop.
+    std::unique_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map(
+        extensions::file_util::LoadNonLocalizedMessageBundleSubstitutionMap(
+            extension_id));
+    ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg,
+                                                        *dictionary_map);
+    Send(reply_msg);
+    return;
+  }
+
+  std::vector<base::FilePath> paths_to_load;
+  paths_to_load.push_back(extension->path());
+
+  auto imports = extensions::SharedModuleInfo::GetImports(extension);
+  // Iterate through the imports in reverse.  This will allow later imported
+  // modules to override earlier imported modules, as the list order is
+  // maintained from the definition in manifest.json of the imports.
+  for (auto it = imports.rbegin(); it != imports.rend(); ++it) {
+    const extensions::Extension* imported_extension =
+        extension_set.GetByID(it->extension_id);
+    if (!imported_extension) {
+      NOTREACHED() << "Missing shared module " << it->extension_id;
+      continue;
+    }
+    paths_to_load.push_back(imported_extension->path());
+  }
+
   BrowserThread::PostBlockingPoolTask(
       FROM_HERE,
       base::Bind(
           &ChromeExtensionMessageFilter::OnGetExtMessageBundleOnBlockingPool,
-          this, extension_id, reply_msg));
+          this, paths_to_load, extension_id, default_locale, reply_msg));
 }
 
 void ChromeExtensionMessageFilter::OnGetExtMessageBundleOnBlockingPool(
-    const std::string& extension_id,
+    const std::vector<base::FilePath>& extension_paths,
+    const std::string& main_extension_id,
+    const std::string& default_locale,
     IPC::Message* reply_msg) {
   DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
 
-  const extensions::ExtensionSet& extension_set =
-      extension_info_map_->extensions();
-
   std::unique_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map(
-      extensions::file_util::LoadMessageBundleSubstitutionMapWithImports(
-          extension_id, extension_set));
+      extensions::file_util::LoadMessageBundleSubstitutionMapFromPaths(
+          extension_paths, main_extension_id, default_locale));
 
   ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg,
                                                       *dictionary_map);
diff --git a/chrome/browser/renderer_host/chrome_extension_message_filter.h b/chrome/browser/renderer_host/chrome_extension_message_filter.h
index ddce9ca..b746f50 100644
--- a/chrome/browser/renderer_host/chrome_extension_message_filter.h
+++ b/chrome/browser/renderer_host/chrome_extension_message_filter.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_RENDERER_HOST_CHROME_EXTENSION_MESSAGE_FILTER_H_
 
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/sequenced_task_runner_helpers.h"
@@ -71,7 +72,9 @@
   void OnGetExtMessageBundle(const std::string& extension_id,
                              IPC::Message* reply_msg);
   void OnGetExtMessageBundleOnBlockingPool(
-      const std::string& extension_id,
+      const std::vector<base::FilePath>& extension_paths,
+      const std::string& main_extension_id,
+      const std::string& default_locale,
       IPC::Message* reply_msg);
   void OnAddAPIActionToExtensionActivityLog(
       const std::string& extension_id,
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index e6a122a..c8edb250 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -94,18 +94,7 @@
   }
 
   grit("settings_resources") {
-    if (use_vulcanize) {
-      source = "settings/settings_resources_vulcanized.grd"
-      deps = [
-        "//chrome/browser/resources/settings:vulcanize",
-      ]
-      grit_flags = [
-        "-E",
-        "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
-      ]
-    } else {
-      source = "settings/settings_resources.grd"
-    }
+    source = "settings/settings_resources.grd"
 
     # TODO(thestig): use_qualified_include = true
     defines = chrome_grit_defines
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
deleted file mode 100644
index 45cc80d1..0000000
--- a/chrome/browser/resources/settings/BUILD.gn
+++ /dev/null
@@ -1,31 +0,0 @@
-import("../vulcanize.gni")
-import("//tools/grit/grit_rule.gni")
-import("//chrome/common/features.gni")
-
-vulcanize("vulcanize") {
-  host = "md-settings"
-  html_in_file = "settings.html"
-  html_out_file = "vulcanized.html"
-  insert_in_head = "<base href=\"chrome://\$i18n{hostname}\">"
-  input = rebase_path(root_gen_dir, root_build_dir) +
-          "/chrome/browser/resources/settings/settings_resources.pak"
-  js_out_file = "crisper.js"
-
-  deps = [
-    ":flattened_resources",
-  ]
-}
-
-grit("flattened_resources") {
-  source = "settings_resources.grd"
-
-  # TODO(thestig): use_qualified_include = true
-  defines = chrome_grit_defines
-  outputs = [
-    "grit/settings_resources.h",
-    "grit/settings_resources_map.cc",
-    "grit/settings_resources_map.h",
-    "settings_resources.pak",
-  ]
-  output_dir = "$root_gen_dir/chrome/browser/resources/settings"
-}
diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html
index 15aaba4..3e4f029 100644
--- a/chrome/browser/resources/settings/about_page/about_page.html
+++ b/chrome/browser/resources/settings/about_page/about_page.html
@@ -91,13 +91,12 @@
               <span class="product-title">$i18n{aboutProductTitle}</span>
             </div>
             <div class="settings-box two-line">
-              <!-- TODO(dpapad): Investigate why vulcanize does not handle well
-                a new line after "getIconSrc_(", causes incorrect src URL -->
               <iron-icon
                   hidden="[[!showUpdateStatus_]]"
                   icon$="[[getIcon_(
                       obsoleteSystemInfo_, currentUpdateStatusEvent_)]]"
-                  src="[[getIconSrc_(obsoleteSystemInfo_, currentUpdateStatusEvent_)]]">
+                  src="[[getIconSrc_(
+                      obsoleteSystemInfo_, currentUpdateStatusEvent_)]]">
               </iron-icon>
               <div class="start">
                 <div id="updateStatusMessage" hidden="[[!showUpdateStatus_]]"
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html
index 33580fbb..34545a7 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -171,7 +171,7 @@
                     $i18n{inputMethodEnabled}
                   </div>
                 </div>
-                <paper-icon-button icon="cr:settings_icon"
+                <paper-icon-button icon="cr:settings"
                     on-tap="onInputMethodOptionsTap_"
                     hidden="[[!item.hasOptionsPage]]">
                 </paper-icon-button>
diff --git a/chrome/browser/resources/settings/settings.html b/chrome/browser/resources/settings/settings.html
index 2d4d4597..53975ff 100644
--- a/chrome/browser/resources/settings/settings.html
+++ b/chrome/browser/resources/settings/settings.html
@@ -3,9 +3,7 @@
 <head>
   <meta charset="utf-8">
   <title>$i18n{settings}</title>
-<if expr="not use_vulcanize">
   <base href="chrome://$i18n{hostname}">
-</if>
   <link rel="import" href="chrome://resources/html/polymer.html">
   <link rel="import" href="settings_ui/settings_ui.html">
   <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index f9dbb5b..6ce1ff7 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -961,7 +961,6 @@
                  file="system_page/system_page.js"
                  type="chrome_html" />
       <structure name="IDR_SETTINGS_SETTINGS_HTML"
-                 preprocess="true"
                  file="settings.html"
                  type="chrome_html" />
       <structure name="IDR_SETTINGS_USB_DEVICES_HTML"
diff --git a/chrome/browser/resources/settings/settings_resources_vulcanized.grd b/chrome/browser/resources/settings/settings_resources_vulcanized.grd
deleted file mode 100644
index 4187200..0000000
--- a/chrome/browser/resources/settings/settings_resources_vulcanized.grd
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
-  <outputs>
-    <output filename="grit/settings_resources.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="grit/settings_resources_map.cc"
-            type="resource_file_map_source" />
-    <output filename="grit/settings_resources_map.h"
-            type="resource_map_header" />
-    <output filename="settings_resources.pak" type="data_package" />
-  </outputs>
-  <release seq="1">
-    <includes>
-      <include name="IDR_MD_SETTINGS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
-      <include name="IDR_MD_SETTINGS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
-    </includes>
-  </release>
-</grit>
diff --git a/chrome/browser/resources/welcome/win10/inline.css b/chrome/browser/resources/welcome/win10/inline.css
index 6eb9d5d..ac9ce13 100644
--- a/chrome/browser/resources/welcome/win10/inline.css
+++ b/chrome/browser/resources/welcome/win10/inline.css
@@ -39,9 +39,8 @@
 
 .heading {
   font-size: 2.125em;
-  line-height: 1.6em;
-  margin-bottom: 0.5em;
-  margin-top: 1.2em;
+  padding-bottom: 2rem;
+  padding-top: 1rem;
 }
 
 .sections {
@@ -82,7 +81,6 @@
 
 .section-heading-expand {
   height: 1.25em;
-  opacity: 0.54;
   transition: transform 150ms cubic-bezier(.4, .2, 0, 1) 50ms;
   width: 1.25em;
 }
@@ -110,6 +108,7 @@
   max-height: 0;
   opacity: 0;
   transition: max-height 300ms cubic-bezier(.4, .2, 0, 1) 50ms, opacity 150ms;
+  visibility: hidden;
 }
 
 .section.expandable.expanded .section-steps {
@@ -117,6 +116,7 @@
   opacity: 1;
   transition: max-height 300ms cubic-bezier(.4, .2, 0, 1) 50ms,
               opacity 150ms 250ms;
+  visibility: visible;
 }
 
 .button {
diff --git a/chrome/browser/resources/welcome/win10/inline.html b/chrome/browser/resources/welcome/win10/inline.html
index 52014ae..96674098 100644
--- a/chrome/browser/resources/welcome/win10/inline.html
+++ b/chrome/browser/resources/welcome/win10/inline.html
@@ -5,6 +5,8 @@
 
   <link rel="import" href="chrome://resources/cr_elements/icons.html">
   <link rel="import" href="chrome://resources/html/cr.html">
+  <link rel="import" href="chrome://resources/html/action_link.html">
+  <link rel="import" href="chrome://resources/html/action_link_css.html">
   <link rel="import" href="chrome://resources/html/polymer.html">
   <link rel="import" href="chrome://resources/html/util.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
@@ -23,27 +25,36 @@
       <div class="heading">$i18n{headerText}</div>
       <div class="sections">
         <div class$="[[computeClasses(isCombined)]]">
-          <div class="section-heading" on-tap="onToggle">
-            <div class="section-heading-text">
-              $i18n{defaultBrowserSubheaderText}
-            </div>
-            <template is="dom-if" if="[[isCombined]]">
+          <template is="dom-if" if="[[isCombined]]">
+            <a is="action-link" class="section-heading" on-tap="onToggle">
+              <div class="section-heading-text">
+                $i18n{defaultBrowserSubheaderText}
+              </div>
               <iron-icon class="section-heading-expand" icon="cr:expand-more">
               </iron-icon>
-            </template>
-          </div>
+            </a>
+          </template>
+          <template is="dom-if" if="[[!isCombined]]">
+            <div class="section-heading">
+              <div class="section-heading-text">
+                $i18n{defaultBrowserSubheaderText}
+              </div>
+            </div>
+          </template>
           <ol class="section-steps">
             <li>
-              <a href="#" on-tap="onOpenSettings">$i18n{openSettingsText}</a>
+              <a is="action-link" on-tap="onOpenSettings">
+                $i18n{openSettingsText}
+              </a>
             </li>
             <li>
               <div>$i18nRaw{clickEdgeText}</div>
               <div class="screenshot-image" id="default-image">
                 <div class="screenshot-overlay" id="browser-overlay">
-                  <div>$i18n{webBrowserLabel}</div>
+                  <div aria-hidden="true">$i18n{webBrowserLabel}</div>
                 </div>
                 <div class="screenshot-overlay" id="edge-overlay">
-                  <div>$i18n{microsoftEdgeLabel}</div>
+                  <div aria-hidden="true">$i18n{microsoftEdgeLabel}</div>
                 </div>
               </div>
             </li>
@@ -52,18 +63,18 @@
         </div>
         <template is="dom-if" if="[[isCombined]]">
           <div class="section expandable">
-            <div class="section-heading" on-tap="onToggle">
+            <a is="action-link" class="section-heading" on-tap="onToggle">
               <div class="section-heading-text">$i18n{pinSubheaderText}</div>
               <iron-icon class="section-heading-expand" icon="cr:expand-more">
               </iron-icon>
-            </div>
+            </a>
             <ol class="section-steps">
               <li>$i18nRaw{rightClickText}</li>
               <li>
                 <div>$i18nRaw{pinInstructionText}</div>
                 <div class="screenshot-image" id="taskbar-image">
                   <div class="screenshot-overlay" id="taskbar-overlay">
-                    <div>$i18n{pinToTaskbarLabel}</div>
+                    <div aria-hidden="true">$i18n{pinToTaskbarLabel}</div>
                   </div>
                   <div class="screenshot-overlay" id="icon-overlay">
                   </div>
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc
index b8fdbf7..f20caf34 100644
--- a/chrome/browser/safe_browsing/ui_manager.cc
+++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -55,97 +55,51 @@
     sb_service_ = NULL;
 }
 
-void SafeBrowsingUIManager::DisplayBlockingPage(
+void SafeBrowsingUIManager::CreateAndSendHitReport(
     const UnsafeResource& resource) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (resource.is_subresource && !resource.is_subframe) {
-    // Sites tagged as serving Unwanted Software should only show a warning for
-    // main-frame or sub-frame resource. Similar warning restrictions should be
-    // applied to malware sites tagged as "landing sites" (see "Types of
-    // Malware sites" under
-    // https://developers.google.com/safe-browsing/developers_guide_v3#UserWarnings).
-    if (resource.threat_type == SB_THREAT_TYPE_URL_UNWANTED ||
-        (resource.threat_type == SB_THREAT_TYPE_URL_MALWARE &&
-         resource.threat_metadata.threat_pattern_type ==
-             ThreatPatternType::MALWARE_LANDING)) {
-      if (!resource.callback.is_null()) {
-        DCHECK(resource.callback_thread);
-        resource.callback_thread->PostTask(FROM_HERE,
-                                           base::Bind(resource.callback, true));
-      }
-
-      return;
-    }
-  }
-
-  // The tab might have been closed. If it was closed, just act as if "Don't
-  // Proceed" had been chosen.
   WebContents* web_contents = resource.web_contents_getter.Run();
-  if (!web_contents) {
-    std::vector<UnsafeResource> resources;
-    resources.push_back(resource);
-    OnBlockingPageDone(resources, false, web_contents,
-                       GetMainFrameWhitelistUrlForResource(resource));
-    return;
+  DCHECK(web_contents);
+  HitReport hit_report;
+  hit_report.malicious_url = resource.url;
+  hit_report.is_subresource = resource.is_subresource;
+  hit_report.threat_type = resource.threat_type;
+  hit_report.threat_source = resource.threat_source;
+  hit_report.population_id = resource.threat_metadata.population_id;
+
+  NavigationEntry* entry = resource.GetNavigationEntryForResource();
+  if (entry) {
+    hit_report.page_url = entry->GetURL();
+    hit_report.referrer_url = entry->GetReferrer().url;
   }
 
-  // Check if the user has already ignored a SB warning for the same WebContents
-  // and top-level domain.
-  if (IsWhitelisted(resource)) {
-    if (!resource.callback.is_null()) {
-      DCHECK(resource.callback_thread);
-      resource.callback_thread->PostTask(FROM_HERE,
-                                         base::Bind(resource.callback, true));
-    }
-    return;
+  // When the malicious url is on the main frame, and resource.original_url
+  // is not the same as the resource.url, that means we have a redirect from
+  // resource.original_url to resource.url.
+  // Also, at this point, page_url points to the _previous_ page that we
+  // were on. We replace page_url with resource.original_url and referrer
+  // with page_url.
+  if (!resource.is_subresource && !resource.original_url.is_empty() &&
+      resource.original_url != resource.url) {
+    hit_report.referrer_url = hit_report.page_url;
+    hit_report.page_url = resource.original_url;
   }
 
-  if (resource.threat_type != SB_THREAT_TYPE_SAFE) {
-    HitReport hit_report;
-    hit_report.malicious_url = resource.url;
-    hit_report.is_subresource = resource.is_subresource;
-    hit_report.threat_type = resource.threat_type;
-    hit_report.threat_source = resource.threat_source;
-    hit_report.population_id = resource.threat_metadata.population_id;
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  hit_report.extended_reporting_level =
+      profile ? GetExtendedReportingLevel(*profile->GetPrefs())
+              : SBER_LEVEL_OFF;
+  hit_report.is_metrics_reporting_active =
+      ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
 
-    NavigationEntry* entry = resource.GetNavigationEntryForResource();
-    if (entry) {
-      hit_report.page_url = entry->GetURL();
-      hit_report.referrer_url = entry->GetReferrer().url;
-    }
+  MaybeReportSafeBrowsingHit(hit_report);
 
-    // When the malicious url is on the main frame, and resource.original_url
-    // is not the same as the resource.url, that means we have a redirect from
-    // resource.original_url to resource.url.
-    // Also, at this point, page_url points to the _previous_ page that we
-    // were on. We replace page_url with resource.original_url and referrer
-    // with page_url.
-    if (!resource.is_subresource &&
-        !resource.original_url.is_empty() &&
-        resource.original_url != resource.url) {
-      hit_report.referrer_url = hit_report.page_url;
-      hit_report.page_url = resource.original_url;
-    }
+  for (Observer& observer : observer_list_)
+    observer.OnSafeBrowsingHit(resource);
+}
 
-    Profile* profile =
-        Profile::FromBrowserContext(web_contents->GetBrowserContext());
-    hit_report.extended_reporting_level =
-        profile ? GetExtendedReportingLevel(*profile->GetPrefs())
-                : SBER_LEVEL_OFF;
-    hit_report.is_metrics_reporting_active =
-        ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
-
-    MaybeReportSafeBrowsingHit(hit_report);
-  }
-
-  if (resource.threat_type != SB_THREAT_TYPE_SAFE) {
-    for (Observer& observer : observer_list_)
-      observer.OnSafeBrowsingHit(resource);
-  }
-  AddToWhitelistUrlSet(GetMainFrameWhitelistUrlForResource(resource),
-                       resource.web_contents_getter.Run(),
-                       true /* A decision is now pending */,
-                       resource.threat_type);
+void SafeBrowsingUIManager::ShowBlockingPageForResource(
+    const UnsafeResource& resource) {
   SafeBrowsingBlockingPage::ShowBlockingPage(this, resource);
 }
 
diff --git a/chrome/browser/safe_browsing/ui_manager.h b/chrome/browser/safe_browsing/ui_manager.h
index cbc2c0d00..7ac91d4 100644
--- a/chrome/browser/safe_browsing/ui_manager.h
+++ b/chrome/browser/safe_browsing/ui_manager.h
@@ -63,13 +63,6 @@
   // on IO thread. If shutdown is true, the manager is disabled permanently.
   void StopOnIOThread(bool shutdown) override;
 
-  // Called on the UI thread to display an interstitial page.
-  // |url| is the url of the resource that matches a safe browsing list.
-  // If the request contained a chain of redirects, |url| is the last url
-  // in the chain, and |original_url| is the first one (the root of the
-  // chain). Otherwise, |original_url| = |url|.
-  void DisplayBlockingPage(const UnsafeResource& resource) override;
-
   // Called on the IO thread by the ThreatDetails with the serialized
   // protocol buffer, so the service can send it over.
   void SendSerializedThreatDetails(const std::string& serialized) override;
@@ -107,6 +100,14 @@
   void ReportSafeBrowsingHitOnIOThread(
       const safe_browsing::HitReport& hit_report) override;
 
+  // Creates a hit report for the given resource and calls
+  // MaybeReportSafeBrowsingHit. This also notifies all observers in
+  // |observer_list_|.
+  void CreateAndSendHitReport(const UnsafeResource& resource) override;
+
+  // Calls SafeBrowsingBlockingPage::ShowBlockingPage().
+  void ShowBlockingPageForResource(const UnsafeResource& resource) override;
+
  private:
   friend class SafeBrowsingUIManagerTest;
   friend class TestSafeBrowsingUIManager;
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index d1272415..74d6549 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -82,6 +82,7 @@
 #include "net/base/load_flags.h"
 #include "net/base/network_change_notifier.h"
 #include "net/base/port_util.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
@@ -978,7 +979,8 @@
   GURL sync_url_status(sync_url.append("/healthz"));
   SyncServerStatusChecker delegate;
   std::unique_ptr<net::URLFetcher> fetcher =
-      net::URLFetcher::Create(sync_url_status, net::URLFetcher::GET, &delegate);
+      net::URLFetcher::Create(sync_url_status, net::URLFetcher::GET, &delegate,
+                              TRAFFIC_ANNOTATION_FOR_TESTS);
   fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
                         net::LOAD_DO_NOT_SEND_COOKIES |
                         net::LOAD_DO_NOT_SAVE_COOKIES);
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
index 538c7b0a..ca9f3bd 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl_browsertest.cc
@@ -1065,7 +1065,8 @@
 
 // Confirm that a tab can be moved between browsers while maintaining the
 // correct running state.
-IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, TabDragAndDrop) {
+// Disabled due to flake: crbug.com/693341.
+IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, DISABLED_TabDragAndDrop) {
   TabStripModel* tab_strip_model1 = browser()->tab_strip_model();
   EXPECT_EQ(1, tab_strip_model1->count());
   int browser_index = GetIndexOfShelfItemType(ash::TYPE_BROWSER_SHORTCUT);
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index df9d34c..6d268b3 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -826,6 +826,11 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Browser, Tab adding/showing functions:
 
+void Browser::WindowFullscreenStateWillChange() {
+  exclusive_access_manager_->fullscreen_controller()
+      ->WindowFullscreenStateWillChange();
+}
+
 void Browser::WindowFullscreenStateChanged() {
   exclusive_access_manager_->fullscreen_controller()
       ->WindowFullscreenStateChanged();
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index c741ab7..59da0950 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -368,9 +368,10 @@
 
   // External state change handling ////////////////////////////////////////////
 
-  // Invoked when the fullscreen state of the window changes.
-  // BrowserWindow::EnterFullscreen invokes this after the window has become
-  // fullscreen.
+  // BrowserWindow::EnterFullscreen invokes WindowFullscreenStateWillChange at
+  // the beginning of a fullscreen transition, and WindowFullscreenStateChanged
+  // at the end.
+  void WindowFullscreenStateWillChange();
   void WindowFullscreenStateChanged();
 
   // Assorted browser commands ////////////////////////////////////////////////
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index f084fb03..03216863 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -610,6 +610,7 @@
 
   [self setSheetHiddenForFullscreenTransition:YES];
   [self adjustUIForEnteringFullscreen];
+  browser_->WindowFullscreenStateWillChange();
 }
 
 - (void)windowDidEnterFullScreen:(NSNotification*)notification {
@@ -700,6 +701,7 @@
   } else {
     [self adjustUIForExitingFullscreen];
   }
+  browser_->WindowFullscreenStateWillChange();
 }
 
 - (void)windowDidExitFullScreen:(NSNotification*)notification {
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.h b/chrome/browser/ui/cocoa/download/download_shelf_controller.h
index f124bb8..071f806 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.h
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.h
@@ -102,7 +102,8 @@
 // directly, the shelf visibility state maintained by DownloadShelf and the
 // owning Browser will not be updated.
 - (void)showDownloadShelf:(BOOL)show
-             isUserAction:(BOOL)isUserAction;
+             isUserAction:(BOOL)isUserAction
+                  animate:(BOOL)animate;
 
 // Returns our view cast as an AnimatableView.
 - (AnimatableView*)animatableView;
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
index cc0cc76..364bf2a 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller.mm
@@ -227,7 +227,8 @@
 }
 
 - (void)showDownloadShelf:(BOOL)show
-             isUserAction:(BOOL)isUserAction {
+             isUserAction:(BOOL)isUserAction
+                  animate:(BOOL)animate {
   [self cancelAutoClose];
   shouldCloseOnMouseExit_ = NO;
 
@@ -251,11 +252,11 @@
   // do no animation over janky animation.  Find a way to make animating in
   // smoother.
   AnimatableView* view = [self animatableView];
-  if (show) {
-    [view setHeight:maxShelfHeight_];
-    [view setHidden:NO];
-  } else {
+  if (animate && !show) {
     [view animateToNewHeight:0 duration:kDownloadShelfCloseDuration];
+  } else {
+    [view setHeight:show ? maxShelfHeight_ : 0];
+    [view setHidden:!show];
   }
 
   barIsVisible_ = show;
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm b/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm
index c4b4e21..b444f061 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_controller_unittest.mm
@@ -11,7 +11,6 @@
 
 #import "base/mac/scoped_block.h"
 #import "base/mac/scoped_nsobject.h"
-#include "base/run_loop.h"
 #include "chrome/browser/download/download_shelf.h"
 #import "chrome/browser/ui/cocoa/download/download_item_controller.h"
 #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
@@ -171,8 +170,7 @@
 // immediately.
 TEST_F(DownloadShelfControllerTest, AddAndRemoveDownload) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   EXPECT_TRUE([shelf_ bridge]->IsShowing());
   [shelf_ add:item];
@@ -188,8 +186,7 @@
 TEST_F(DownloadShelfControllerTest, AddAndRemoveWithActiveItem) {
   base::scoped_nsobject<DownloadItemController> item1(CreateItemController());
   base::scoped_nsobject<DownloadItemController> item2(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item1.get()];
   [shelf_ add:item2.get()];
@@ -204,8 +201,7 @@
 // active downloads on it.
 TEST_F(DownloadShelfControllerTest, HideAndUnhide) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item.get()];
   [shelf_ bridge]->Hide();
@@ -220,8 +216,7 @@
 // active downloads are removed from the shelf while the shelf was hidden.
 TEST_F(DownloadShelfControllerTest, HideAutocloseUnhide) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item.get()];
   [shelf_ bridge]->Hide();
@@ -236,8 +231,7 @@
 // the download shelf at the time the autoclose is scheduled.
 TEST_F(DownloadShelfControllerTest, AutoCloseAfterOpenWithMouseInShelf) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item.get()];
   // Expect 2 cancelAutoClose calls: From the showDownloadShelf: call and the
@@ -273,8 +267,7 @@
 // Test of autoclosing behavior after opening a download item.
 TEST_F(DownloadShelfControllerTest, AutoCloseAfterOpenWithMouseOffShelf) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item.get()];
 
@@ -292,8 +285,7 @@
 // autoClose is cancelled.
 TEST_F(DownloadShelfControllerTest, CloseWithPendingAutoClose) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item.get()];
   // Expect 2 cancelAutoClose calls: From the showDownloadShelf: call and the
@@ -333,8 +325,7 @@
 // added to it.
 TEST_F(DownloadShelfControllerTest, AddItemWithPendingAutoClose) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item.get()];
   // Expect 2 cancelAutoClose calls: From the showDownloadShelf: call and the
@@ -373,8 +364,7 @@
 // Test that pending autoClose calls are cancelled when exiting.
 TEST_F(DownloadShelfControllerTest, CancelAutoCloseOnExit) {
   base::scoped_nsobject<DownloadItemController> item(CreateItemController());
-  [shelf_ showDownloadShelf:YES
-               isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:YES];
   EXPECT_TRUE([shelf_ isVisible]);
   [shelf_ add:item.get()];
   EXPECT_EQ(0, shelf_.get()->scheduleAutoCloseCount_);
@@ -386,24 +376,16 @@
   shelf_.reset();
 }
 
-// The view should not be hidden when the shelf is shown.
-// The view should be hidden after the closing animation.
-// Failing flakily on Mac 10.9, see: crbug.com/687447.
-TEST_F(DownloadShelfControllerTest, DISABLED_ViewVisibility) {
-  [shelf_ showDownloadShelf:YES isUserAction:NO];
+// The view should not be hidden when the shelf is open.
+// The view should be hidden when the shelf is closed.
+TEST_F(DownloadShelfControllerTest, ViewVisibility) {
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:NO];
   EXPECT_FALSE([[shelf_ view] isHidden]);
 
-  base::RunLoop run_loop;
-  base::RunLoop* const run_loop_ptr = &run_loop;
-
-  [shelf_ setCloseAnimationHandler:^{
-    run_loop_ptr->Quit();
-  }];
-  [shelf_ showDownloadShelf:NO isUserAction:NO];
-  run_loop.Run();
+  [shelf_ showDownloadShelf:NO isUserAction:NO animate:NO];
   EXPECT_TRUE([[shelf_ view] isHidden]);
 
-  [shelf_ showDownloadShelf:YES isUserAction:NO];
+  [shelf_ showDownloadShelf:YES isUserAction:NO animate:NO];
   EXPECT_FALSE([[shelf_ view] isHidden]);
 }
 
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_mac.h b/chrome/browser/ui/cocoa/download/download_shelf_mac.h
index 11a631db..2d78a595 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_mac.h
+++ b/chrome/browser/ui/cocoa/download/download_shelf_mac.h
@@ -26,8 +26,10 @@
 
  protected:
   void DoAddDownload(content::DownloadItem* download) override;
-  void DoShow() override;
+  void DoOpen() override;
   void DoClose(CloseReason reason) override;
+  void DoHide() override;
+  void DoUnhide() override;
 
  private:
   // The browser that owns this shelf.
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_mac.mm b/chrome/browser/ui/cocoa/download/download_shelf_mac.mm
index cf14be7..35ca1d3 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_mac.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_mac.mm
@@ -28,18 +28,28 @@
   return false;
 }
 
-void DownloadShelfMac::DoShow() {
-  [shelf_controller_ showDownloadShelf:YES
-                          isUserAction:NO];
+void DownloadShelfMac::DoOpen() {
+  [shelf_controller_ showDownloadShelf:YES isUserAction:NO animate:YES];
   browser_->UpdateDownloadShelfVisibility(true);
 }
 
 void DownloadShelfMac::DoClose(CloseReason reason) {
   [shelf_controller_ showDownloadShelf:NO
-                          isUserAction:reason == USER_ACTION];
+                          isUserAction:reason == USER_ACTION
+                               animate:YES];
   browser_->UpdateDownloadShelfVisibility(false);
 }
 
+void DownloadShelfMac::DoHide() {
+  [shelf_controller_ showDownloadShelf:NO isUserAction:NO animate:NO];
+  browser_->UpdateDownloadShelfVisibility(false);
+}
+
+void DownloadShelfMac::DoUnhide() {
+  [shelf_controller_ showDownloadShelf:YES isUserAction:NO animate:NO];
+  browser_->UpdateDownloadShelfVisibility(true);
+}
+
 Browser* DownloadShelfMac::browser() const {
   return browser_;
 }
diff --git a/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm b/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm
index b68ba95..d7a99e9 100644
--- a/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/download/download_shelf_mac_unittest.mm
@@ -23,7 +23,8 @@
 
 - (BOOL)isVisible;
 - (void)showDownloadShelf:(BOOL)enable
-             isUserAction:(BOOL)isUserAction;
+             isUserAction:(BOOL)isUserAction
+                  animate:(BOOL)animate;
 @end
 
 @implementation FakeDownloadShelfController
@@ -34,7 +35,8 @@
 }
 
 - (void)showDownloadShelf:(BOOL)enable
-             isUserAction:(BOOL)isUserAction {
+             isUserAction:(BOOL)isUserAction
+                  animate:(BOOL)animate {
   if (enable)
     ++callCountShow;
   else
@@ -69,7 +71,7 @@
   DownloadShelfMac shelf(browser(),
       (DownloadShelfController*)shelf_controller_.get());
   EXPECT_EQ(0, shelf_controller_.get()->callCountShow);
-  shelf.Show();
+  shelf.Open();
   EXPECT_EQ(1, shelf_controller_.get()->callCountShow);
 }
 
diff --git a/chrome/browser/ui/cocoa/tab_contents/OWNERS b/chrome/browser/ui/cocoa/tab_contents/OWNERS
index c16f00c..d67ec98 100644
--- a/chrome/browser/ui/cocoa/tab_contents/OWNERS
+++ b/chrome/browser/ui/cocoa/tab_contents/OWNERS
@@ -1,3 +1,5 @@
 avi@chromium.org
 miu@chromium.org
 thakis@chromium.org
+
+# COMPONENT: UI>Browser>TabContents
diff --git a/chrome/browser/ui/cocoa/tabs/OWNERS b/chrome/browser/ui/cocoa/tabs/OWNERS
index 0021790..5edf558 100644
--- a/chrome/browser/ui/cocoa/tabs/OWNERS
+++ b/chrome/browser/ui/cocoa/tabs/OWNERS
@@ -3,3 +3,5 @@
 
 # For changes related to the tab alert indicator/button.
 miu@chromium.org
+
+# COMPONENT: UI>Browser>TabStrip
diff --git a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
index b935b4c..dd26af6 100644
--- a/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
+++ b/chrome/browser/ui/cocoa/view_id_util_browsertest.mm
@@ -52,7 +52,7 @@
         DevToolsWindowTesting::OpenDevToolsWindowSync(browser(), true);
 
     // Make sure download shelf is created to test VIEW_ID_DOWNLOAD_SHELF
-    browser()->window()->GetDownloadShelf()->Show();
+    browser()->window()->GetDownloadShelf()->Open();
 
     // Create a bookmark to test VIEW_ID_BOOKMARK_BAR_ELEMENT
     BookmarkModel* bookmark_model =
diff --git a/chrome/browser/ui/exclusive_access/OWNERS b/chrome/browser/ui/exclusive_access/OWNERS
index 35e2632..192ee8f 100644
--- a/chrome/browser/ui/exclusive_access/OWNERS
+++ b/chrome/browser/ui/exclusive_access/OWNERS
@@ -1,3 +1,5 @@
 mgiuca@chromium.org
 miu@chromium.org
 scheib@chromium.org
+
+# COMPONENT: UI>Browser>FullScreen
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
index 04d2a6de..ca73d98 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -238,6 +238,16 @@
     ExclusiveAccessControllerBase::OnTabClosing(web_contents);
 }
 
+void FullscreenController::WindowFullscreenStateWillChange() {
+  ExclusiveAccessContext* exclusive_access_context =
+      exclusive_access_manager()->context();
+  if (exclusive_access_context->IsFullscreen()) {
+    exclusive_access_context->HideDownloadShelf();
+  } else {
+    exclusive_access_context->UnhideDownloadShelf();
+  }
+}
+
 void FullscreenController::WindowFullscreenStateChanged() {
   reentrant_window_state_change_call_check_ = true;
   ExclusiveAccessContext* const exclusive_access_context =
@@ -249,9 +259,6 @@
     toggled_into_fullscreen_ = false;
     extension_caused_fullscreen_ = GURL();
     NotifyTabExclusiveAccessLost();
-    exclusive_access_context->UnhideDownloadShelf();
-  } else {
-    exclusive_access_context->HideDownloadShelf();
   }
 }
 
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.h b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
index 0a234b28..58ce24b 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.h
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.h
@@ -123,6 +123,9 @@
   void ExitExclusiveAccessIfNecessary() override;
   // Callbacks /////////////////////////////////////////////////////////////////
 
+  // Called by Browser::WindowFullscreenStateWillChange.
+  void WindowFullscreenStateWillChange();
+
   // Called by Browser::WindowFullscreenStateChanged.
   void WindowFullscreenStateChanged();
 
diff --git a/chrome/browser/ui/tabs/OWNERS b/chrome/browser/ui/tabs/OWNERS
index a4ef29a..f933a2a 100644
--- a/chrome/browser/ui/tabs/OWNERS
+++ b/chrome/browser/ui/tabs/OWNERS
@@ -2,3 +2,5 @@
 
 # For changes related to the tab alert indicators.
 per-file tab_utils*=miu@chromium.org
+
+# COMPONENT: UI>Browser>TabStrip
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc
index 1e119e9..23b3297 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.cc
+++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -367,7 +367,7 @@
   return shelf_animation_.IsClosing();
 }
 
-void DownloadShelfView::DoShow() {
+void DownloadShelfView::DoOpen() {
   SetVisible(true);
   shelf_animation_.Show();
 }
@@ -384,6 +384,18 @@
   shelf_animation_.Hide();
 }
 
+void DownloadShelfView::DoHide() {
+  SetVisible(false);
+  parent_->ToolbarSizeChanged(false);
+  parent_->SetDownloadShelfVisible(false);
+}
+
+void DownloadShelfView::DoUnhide() {
+  SetVisible(true);
+  parent_->ToolbarSizeChanged(true);
+  parent_->SetDownloadShelfVisible(true);
+}
+
 Browser* DownloadShelfView::browser() const {
   return browser_;
 }
diff --git a/chrome/browser/ui/views/download/download_shelf_view.h b/chrome/browser/ui/views/download/download_shelf_view.h
index 6da340f..5bbec13d 100644
--- a/chrome/browser/ui/views/download/download_shelf_view.h
+++ b/chrome/browser/ui/views/download/download_shelf_view.h
@@ -96,8 +96,10 @@
  protected:
   // Implementation of DownloadShelf.
   void DoAddDownload(content::DownloadItem* download) override;
-  void DoShow() override;
+  void DoOpen() override;
   void DoClose(CloseReason reason) override;
+  void DoHide() override;
+  void DoUnhide() override;
 
   // From AccessiblePaneView
   views::View* GetDefaultFocusableChild() override;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index d0efcd36..a58f71b0 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -2319,6 +2319,7 @@
   if (ShouldUseImmersiveFullscreenForUrl(url))
     immersive_mode_controller_->SetEnabled(fullscreen);
 
+  browser_->WindowFullscreenStateWillChange();
   browser_->WindowFullscreenStateChanged();
 
   if (fullscreen && !chrome::IsRunningInAppMode()) {
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
index d165ab2..6504936 100644
--- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
@@ -12,10 +12,12 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/ui/views/payments/payment_request_dialog_view.h"
+#include "chrome/browser/ui/views/payments/payment_request_views_util.h"
 #include "chrome/browser/ui/views/payments/preselected_combobox_model.h"
 #include "chrome/browser/ui/views/payments/validating_combobox.h"
 #include "chrome/browser/ui/views/payments/validating_textfield.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
@@ -23,8 +25,14 @@
 #include "components/autofill/core/common/autofill_clock.h"
 #include "components/autofill/core/common/autofill_constants.h"
 #include "components/payments/payment_request.h"
+#include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/native_theme/native_theme.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
 #include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/view.h"
 
 namespace payments {
 
@@ -73,6 +81,59 @@
 
 CreditCardEditorViewController::~CreditCardEditorViewController() {}
 
+// Creates the "Cards accepted" view with a row of icons at the top of the
+// credit card editor.
+// +----------------------------------------------+
+// | Cards Accepted                               |
+// |                                              |
+// | | VISA | | MC | | AMEX |                     |
+// +----------------------------------------------+
+std::unique_ptr<views::View>
+CreditCardEditorViewController::CreateHeaderView() {
+  std::unique_ptr<views::View> view = base::MakeUnique<views::View>();
+
+  // 9dp is required between the first and second row.
+  constexpr int kRowVerticalInset = 9;
+  views::BoxLayout* layout = new views::BoxLayout(
+      views::BoxLayout::kVertical, payments::kPaymentRequestRowHorizontalInsets,
+      payments::kPaymentRequestRowVerticalInsets, kRowVerticalInset);
+  layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+  layout->set_cross_axis_alignment(
+      views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
+  view->SetLayoutManager(layout);
+
+  // "Cards accepted" label is "disabled" grey.
+  std::unique_ptr<views::Label> label = base::MakeUnique<views::Label>(
+      l10n_util::GetStringUTF16(IDS_PAYMENTS_ACCEPTED_CARDS_LABEL));
+  label->SetDisabledColor(label->GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_LabelDisabledColor));
+  label->SetEnabled(false);
+  view->AddChildView(label.release());
+
+  // 8dp padding is required between icons.
+  constexpr int kPaddingBetweenCardIcons = 8;
+  std::unique_ptr<views::View> icons_row = base::MakeUnique<views::View>();
+  views::BoxLayout* icons_layout = new views::BoxLayout(
+      views::BoxLayout::kHorizontal, 0, 0, kPaddingBetweenCardIcons);
+  icons_row->SetLayoutManager(icons_layout);
+
+  constexpr gfx::Size kCardIconSize = gfx::Size(30, 18);
+  for (const std::string& supported_network :
+       request()->supported_card_networks()) {
+    const std::string autofill_card_type =
+        autofill::data_util::GetCardTypeForBasicCardPaymentType(
+            supported_network);
+    std::unique_ptr<views::ImageView> card_icon_view =
+        CreateCardIconView(autofill_card_type);
+    card_icon_view->SetImageSize(kCardIconSize);
+
+    icons_row->AddChildView(card_icon_view.release());
+  }
+  view->AddChildView(icons_row.release());
+
+  return view;
+}
+
 std::vector<EditorField> CreditCardEditorViewController::GetFieldDefinitions() {
   return std::vector<EditorField>{
       {autofill::CREDIT_CARD_NAME_FULL,
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h
index 40420f2..4ea2ef7 100644
--- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h
+++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.h
@@ -24,6 +24,7 @@
   ~CreditCardEditorViewController() override;
 
   // EditorViewController:
+  std::unique_ptr<views::View> CreateHeaderView() override;
   std::vector<EditorField> GetFieldDefinitions() override;
   bool ValidateModelAndSave() override;
   std::unique_ptr<ValidationDelegate> CreateValidationDelegate(
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.cc b/chrome/browser/ui/views/payments/editor_view_controller.cc
index 239a04f..38eeee77 100644
--- a/chrome/browser/ui/views/payments/editor_view_controller.cc
+++ b/chrome/browser/ui/views/payments/editor_view_controller.cc
@@ -61,6 +61,8 @@
       views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
   content_view->SetLayoutManager(layout);
 
+  content_view->AddChildView(CreateHeaderView().release());
+
   // Create an input label/textfield for each field definition.
   std::vector<EditorField> fields = GetFieldDefinitions();
   for (const auto& field : fields) {
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.h b/chrome/browser/ui/views/payments/editor_view_controller.h
index c5851c8..09ab46d9 100644
--- a/chrome/browser/ui/views/payments/editor_view_controller.h
+++ b/chrome/browser/ui/views/payments/editor_view_controller.h
@@ -18,6 +18,7 @@
 #include "ui/views/controls/button/vector_icon_button_delegate.h"
 #include "ui/views/controls/combobox/combobox_listener.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/view.h"
 
 namespace ui {
 class ComboboxModel;
@@ -82,6 +83,7 @@
   // PaymentRequestSheetController:
   std::unique_ptr<views::View> CreateView() override;
 
+  virtual std::unique_ptr<views::View> CreateHeaderView() = 0;
   // Returns the field definitions used to build the UI.
   virtual std::vector<EditorField> GetFieldDefinitions() = 0;
   // Validates the data entered and attempts to save; returns true on success.
diff --git a/chrome/browser/ui/views/payments/payment_request_credit_card_editor_interactive_uitest.cc b/chrome/browser/ui/views/payments/payment_request_credit_card_editor_interactive_uitest.cc
index ac01aa1..3e7b5f3 100644
--- a/chrome/browser/ui/views/payments/payment_request_credit_card_editor_interactive_uitest.cc
+++ b/chrome/browser/ui/views/payments/payment_request_credit_card_editor_interactive_uitest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -13,6 +15,7 @@
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/autofill/core/browser/test_autofill_clock.h"
 #include "components/payments/payment_request.h"
+#include "content/public/test/browser_test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -176,4 +179,144 @@
   EXPECT_TRUE(textfield->invalid());
 }
 
+class PaymentRequestCreditCardBasicCardTest
+    : public PaymentRequestInteractiveTestBase {
+ protected:
+  PaymentRequestCreditCardBasicCardTest()
+      : PaymentRequestInteractiveTestBase(
+            "/payment_request_basic_card_test.html") {}
+
+  void InvokePaymentRequestWithJs(const std::string& js) {
+    ResetEventObserver(DialogEvent::DIALOG_OPENED);
+
+    ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), js));
+
+    WaitForObservedEvent();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PaymentRequestCreditCardBasicCardTest);
+};
+
+// One network is specified in 'basic-card' data, one in supportedMethods.
+IN_PROC_BROWSER_TEST_F(PaymentRequestCreditCardBasicCardTest,
+                       BasicCard_NetworksSpecified) {
+  InvokePaymentRequestWithJs("buy();");
+
+  std::vector<PaymentRequest*> requests =
+      GetPaymentRequests(GetActiveWebContents());
+  EXPECT_EQ(1u, requests.size());
+  std::vector<std::string> supported_card_networks =
+      requests[0]->supported_card_networks();
+  EXPECT_EQ(2u, supported_card_networks.size());
+  // The networks appear in the order in which they were specified by the
+  // merchant.
+  EXPECT_EQ("mastercard", supported_card_networks[0]);
+  EXPECT_EQ("visa", supported_card_networks[1]);
+}
+
+// Only specifying 'basic-card' with no supportedNetworks means all networks are
+// supported.
+IN_PROC_BROWSER_TEST_F(PaymentRequestCreditCardBasicCardTest,
+                       BasicCard_NoNetworksSpecified) {
+  InvokePaymentRequestWithJs("buyBasicCard();");
+
+  std::vector<PaymentRequest*> requests =
+      GetPaymentRequests(GetActiveWebContents());
+  EXPECT_EQ(1u, requests.size());
+  std::vector<std::string> supported_card_networks =
+      requests[0]->supported_card_networks();
+  // The default ordering is alphabetical.
+  EXPECT_EQ(8u, supported_card_networks.size());
+  EXPECT_EQ("amex", supported_card_networks[0]);
+  EXPECT_EQ("diners", supported_card_networks[1]);
+  EXPECT_EQ("discover", supported_card_networks[2]);
+  EXPECT_EQ("jcb", supported_card_networks[3]);
+  EXPECT_EQ("mastercard", supported_card_networks[4]);
+  EXPECT_EQ("mir", supported_card_networks[5]);
+  EXPECT_EQ("unionpay", supported_card_networks[6]);
+  EXPECT_EQ("visa", supported_card_networks[7]);
+}
+
+// Specifying 'basic-card' after having explicitely included a network yields
+// the expected order when in different supportedMethods lists.
+IN_PROC_BROWSER_TEST_F(PaymentRequestCreditCardBasicCardTest,
+                       BasicCard_NetworkThenBasicCard_DifferentList) {
+  InvokePaymentRequestWithJs(
+      "buyHelper([{"
+      "  supportedMethods: ['mastercard'],"
+      "}, {"
+      "  supportedMethods: ['basic-card']"
+      "}]);");
+
+  std::vector<PaymentRequest*> requests =
+      GetPaymentRequests(GetActiveWebContents());
+  EXPECT_EQ(1u, requests.size());
+  std::vector<std::string> supported_card_networks =
+      requests[0]->supported_card_networks();
+  // 'mastercard' is first because it was explicitely specified first. The rest
+  // is alphabetical.
+  EXPECT_EQ(8u, supported_card_networks.size());
+  EXPECT_EQ("mastercard", supported_card_networks[0]);
+  EXPECT_EQ("amex", supported_card_networks[1]);
+  EXPECT_EQ("diners", supported_card_networks[2]);
+  EXPECT_EQ("discover", supported_card_networks[3]);
+  EXPECT_EQ("jcb", supported_card_networks[4]);
+  EXPECT_EQ("mir", supported_card_networks[5]);
+  EXPECT_EQ("unionpay", supported_card_networks[6]);
+  EXPECT_EQ("visa", supported_card_networks[7]);
+}
+
+// Specifying 'basic-card' after having explicitely included a network yields
+// the expected order when in the same supportedMethods list.
+IN_PROC_BROWSER_TEST_F(PaymentRequestCreditCardBasicCardTest,
+                       BasicCard_NetworkThenBasicCard_SameList) {
+  InvokePaymentRequestWithJs(
+      "buyHelper([{"
+      "  supportedMethods: ['visa', 'basic-card']"
+      "}]);");
+
+  std::vector<PaymentRequest*> requests =
+      GetPaymentRequests(GetActiveWebContents());
+  EXPECT_EQ(1u, requests.size());
+  std::vector<std::string> supported_card_networks =
+      requests[0]->supported_card_networks();
+  // 'visa' is first because it was explicitely specified first. The rest
+  // is alphabetical.
+  EXPECT_EQ(8u, supported_card_networks.size());
+  EXPECT_EQ("visa", supported_card_networks[0]);
+  EXPECT_EQ("amex", supported_card_networks[1]);
+  EXPECT_EQ("diners", supported_card_networks[2]);
+  EXPECT_EQ("discover", supported_card_networks[3]);
+  EXPECT_EQ("jcb", supported_card_networks[4]);
+  EXPECT_EQ("mastercard", supported_card_networks[5]);
+  EXPECT_EQ("mir", supported_card_networks[6]);
+  EXPECT_EQ("unionpay", supported_card_networks[7]);
+}
+
+// Specifying 'basic-card' with some networks after having explicitely included
+// the same networks does not yield duplicates and has the expected order.
+IN_PROC_BROWSER_TEST_F(PaymentRequestCreditCardBasicCardTest,
+                       BasicCard_NetworkThenBasicCardWithSameNetwork) {
+  InvokePaymentRequestWithJs(
+      "buyHelper([{"
+      "  supportedMethods: ['mastercard', 'visa']"
+      "}, {"
+      "  supportedMethods: ['basic-card'],"
+      "  data: {"
+      "    supportedNetworks: ['visa', 'mastercard', 'jcb'],"
+      "  }"
+      "}]);");
+
+  std::vector<PaymentRequest*> requests =
+      GetPaymentRequests(GetActiveWebContents());
+  EXPECT_EQ(1u, requests.size());
+  std::vector<std::string> supported_card_networks =
+      requests[0]->supported_card_networks();
+  EXPECT_EQ(3u, supported_card_networks.size());
+  EXPECT_EQ("mastercard", supported_card_networks[0]);
+  EXPECT_EQ("visa", supported_card_networks[1]);
+  EXPECT_EQ("jcb", supported_card_networks[2]);
+}
+
 }  // namespace payments
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc
index 21e5fa1..74e5b02 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.cc
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -10,10 +10,13 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/views/payments/payment_request_sheet_controller.h"
+#include "components/autofill/core/browser/autofill_data_util.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_type.h"
+#include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/point_f.h"
@@ -23,6 +26,7 @@
 #include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/vector_icon_button.h"
+#include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/layout/grid_layout.h"
@@ -114,6 +118,24 @@
   return container;
 }
 
+std::unique_ptr<views::ImageView> CreateCardIconView(
+    const std::string& card_type) {
+  std::unique_ptr<views::ImageView> card_icon_view =
+      base::MakeUnique<views::ImageView>();
+  card_icon_view->set_interactive(false);
+  card_icon_view->SetImage(
+      ResourceBundle::GetSharedInstance()
+          .GetImageNamed(autofill::data_util::GetPaymentRequestData(card_type)
+                             .icon_resource_id)
+          .AsImageSkia());
+  card_icon_view->SetTooltipText(
+      autofill::CreditCard::TypeForDisplay(card_type));
+  card_icon_view->SetBorder(views::CreateRoundedRectBorder(
+      1, 3, card_icon_view->GetNativeTheme()->GetSystemColor(
+                ui::NativeTheme::kColorId_UnfocusedBorderColor)));
+  return card_icon_view;
+}
+
 std::unique_ptr<views::View> GetShippingAddressLabel(
     AddressStyleType type,
     const std::string& locale,
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.h b/chrome/browser/ui/views/payments/payment_request_views_util.h
index de9c6a3bf..016e9c7 100644
--- a/chrome/browser/ui/views/payments/payment_request_views_util.h
+++ b/chrome/browser/ui/views/payments/payment_request_views_util.h
@@ -16,6 +16,7 @@
 
 namespace views {
 class Border;
+class ImageView;
 class VectorIconButtonDelegate;
 class View;
 }
@@ -49,6 +50,11 @@
     const base::string16& title,
     views::VectorIconButtonDelegate* delegate);
 
+// Returns a card image view for the given |card_type|. Includes a rounded rect
+// border. Callers need to set the size of the resulting ImageView.
+std::unique_ptr<views::ImageView> CreateCardIconView(
+    const std::string& card_type);
+
 // Represents formatting options for each of the different contexts in which an
 // Address label may be displayed.
 enum class AddressStyleType { SUMMARY, DETAILED };
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
index 95fc1af..21129d6 100644
--- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -29,12 +29,10 @@
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/range/range.h"
-#include "ui/views/border.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/image_view.h"
@@ -325,18 +323,8 @@
             autofill::AutofillType(autofill::CREDIT_CARD_NAME_FULL),
             g_browser_process->GetApplicationLocale())));
 
-    card_icon_view = base::MakeUnique<views::ImageView>();
-    card_icon_view->set_interactive(false);
-    card_icon_view->SetImage(
-      ResourceBundle::GetSharedInstance()
-          .GetImageNamed(autofill::data_util::GetPaymentRequestData(
-              selected_card->type()).icon_resource_id)
-          .AsImageSkia());
-    card_icon_view->SetBorder(
-        views::CreateRoundedRectBorder(1, 3, SK_ColorLTGRAY));
-
-    constexpr gfx::Size kCardIconSize = gfx::Size(32, 20);
-    card_icon_view->SetImageSize(kCardIconSize);
+    card_icon_view = CreateCardIconView(selected_card->type());
+    card_icon_view->SetImageSize(gfx::Size(32, 20));
   }
 
   std::unique_ptr<views::Button> section = CreatePaymentSheetRow(
diff --git a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
index c9e1308..3d1545b 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
@@ -35,6 +35,7 @@
 
  protected:
   void SetUpInProcessBrowserTestFixture() override {
+    options::OptionsUIBrowserTest::SetUpInProcessBrowserTestFixture();
 #if defined(OS_CHROMEOS)
     device_policy_test_helper_.MarkAsEnterpriseOwned();
 #endif
diff --git a/chrome/browser/ui/webui/options/language_dictionary_interactive_uitest.cc b/chrome/browser/ui/webui/options/language_dictionary_interactive_uitest.cc
index fb09683..dbdad4f2 100644
--- a/chrome/browser/ui/webui/options/language_dictionary_interactive_uitest.cc
+++ b/chrome/browser/ui/webui/options/language_dictionary_interactive_uitest.cc
@@ -4,11 +4,13 @@
 
 #include "base/macros.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
@@ -25,6 +27,8 @@
 
   // Navigate to the editDictionary page.
   void SetUpOnMainThread() override {
+    disable_md_settings_.InitAndDisableFeature(
+        features::kMaterialDesignSettings);
     const GURL url = chrome::GetSettingsUrl("editDictionary");
     ui_test_utils::NavigateToURL(browser(), url);
   }
@@ -177,6 +181,7 @@
 
  private:
   std::unique_ptr<content::DOMMessageQueue> dom_message_queue_;
+  base::test::ScopedFeatureList disable_md_settings_;
 
   DISALLOW_COPY_AND_ASSIGN(LanguageDictionaryWebUITest);
 };
diff --git a/chrome/browser/ui/webui/options/language_options_interactive_uitest.cc b/chrome/browser/ui/webui/options/language_options_interactive_uitest.cc
index 394e071..e9fa0e27 100644
--- a/chrome/browser/ui/webui/options/language_options_interactive_uitest.cc
+++ b/chrome/browser/ui/webui/options/language_options_interactive_uitest.cc
@@ -3,11 +3,13 @@
 // found in the LICENSE file.
 
 #include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -30,6 +32,11 @@
  public:
   LanguageOptionsWebUITest() {}
 
+  void SetUpInProcessBrowserTestFixture() override {
+    disable_md_settings_.InitAndDisableFeature(
+        features::kMaterialDesignSettings);
+  }
+
   // This method will navigate to the language settings page and show
   // a subset of languages from the list of available languages.
   void SetUpOnMainThread() override {
@@ -84,6 +91,8 @@
   }
 
  private:
+  base::test::ScopedFeatureList disable_md_settings_;
+
   DISALLOW_COPY_AND_ASSIGN(LanguageOptionsWebUITest);
 };
 
diff --git a/chrome/browser/ui/webui/options/options_ui_browsertest.cc b/chrome/browser/ui/webui/options/options_ui_browsertest.cc
index 255cc61f..b375226 100644
--- a/chrome/browser/ui/webui/options/options_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/options/options_ui_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
 #include "chrome/browser/ui/webui/uber/uber_ui.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -107,6 +108,11 @@
 OptionsUIBrowserTest::OptionsUIBrowserTest() {
 }
 
+void OptionsUIBrowserTest::SetUpInProcessBrowserTestFixture() {
+  InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
+  disable_md_settings_.InitAndDisableFeature(features::kMaterialDesignSettings);
+}
+
 void OptionsUIBrowserTest::NavigateToSettings() {
   NavigateToSettingsSubpage("");
 }
diff --git a/chrome/browser/ui/webui/options/options_ui_browsertest.h b/chrome/browser/ui/webui/options/options_ui_browsertest.h
index aa75e2b..35b49b2 100644
--- a/chrome/browser/ui/webui/options/options_ui_browsertest.h
+++ b/chrome/browser/ui/webui/options/options_ui_browsertest.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/test/base/in_process_browser_test.h"
 
 namespace content {
@@ -20,6 +21,8 @@
  public:
   OptionsUIBrowserTest();
 
+  void SetUpInProcessBrowserTestFixture() override;
+
   // Navigate to the Uber/Settings page and block until it has loaded.
   void NavigateToSettings();
 
@@ -44,6 +47,8 @@
   content::RenderFrameHost* GetSettingsFrame();
 
  private:
+  base::test::ScopedFeatureList disable_md_settings_;
+
   DISALLOW_COPY_AND_ASSIGN(OptionsUIBrowserTest);
 };
 
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index 2cd4c0b..e5a9ae4 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -190,20 +190,14 @@
   // Add the metrics handler to write uma stats.
   web_ui->AddMessageHandler(base::MakeUnique<MetricsHandler>());
 
-#if BUILDFLAG(USE_VULCANIZE)
-  html_source->AddResourcePath("crisper.js", IDR_MD_SETTINGS_CRISPER_JS);
-  html_source->SetDefaultResource(IDR_MD_SETTINGS_VULCANIZED_HTML);
-  html_source->UseGzip(std::unordered_set<std::string>());
-#else
   // Add all settings resources.
   for (size_t i = 0; i < kSettingsResourcesSize; ++i) {
     html_source->AddResourcePath(kSettingsResources[i].name,
                                  kSettingsResources[i].value);
   }
-  html_source->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML);
-#endif
 
   AddLocalizedStrings(html_source, profile);
+  html_source->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML);
 
   content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
                                 html_source);
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 4f62bd8..ab7b093 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -157,7 +157,7 @@
 // Enables or disables the Material Design version of chrome://settings.
 // Also affects chrome://help.
 const base::Feature kMaterialDesignSettings{"MaterialDesignSettings",
-                                            base::FEATURE_DISABLED_BY_DEFAULT};
+                                            base::FEATURE_ENABLED_BY_DEFAULT};
 
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
 // Enables media content bitstream remoting, an optimization that can activate
diff --git a/chrome/test/base/run_all_unittests.cc b/chrome/test/base/run_all_unittests.cc
index 8536390..89f2415 100644
--- a/chrome/test/base/run_all_unittests.cc
+++ b/chrome/test/base/run_all_unittests.cc
@@ -6,10 +6,15 @@
 #include "base/command_line.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_io_thread.h"
+#include "build/build_config.h"
 #include "chrome/test/base/chrome_unit_test_suite.h"
 #include "content/public/test/unittest_test_suite.h"
 #include "mojo/edk/embedder/scoped_ipc_support.h"
 
+#if defined(OS_WIN)
+#include "chrome/install_static/test/scoped_install_details.h"
+#endif
+
 int main(int argc, char **argv) {
   content::UnitTestTestSuite test_suite(new ChromeUnitTestSuite(argc, argv));
 
@@ -18,6 +23,10 @@
       test_io_thread.task_runner(),
       mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST);
 
+#if defined(OS_WIN)
+  install_static::ScopedInstallDetails scoped_install_details;
+#endif
+
   return base::LaunchUnitTests(
       argc, argv, base::Bind(&content::UnitTestTestSuite::Run,
                              base::Unretained(&test_suite)));
diff --git a/components/guest_view/renderer/guest_view_container.h b/components/guest_view/renderer/guest_view_container.h
index e8f53d82..7025d95 100644
--- a/components/guest_view/renderer/guest_view_container.h
+++ b/components/guest_view/renderer/guest_view_container.h
@@ -66,6 +66,7 @@
   // BrowserPluginGuestDelegate public implementation.
   void SetElementInstanceID(int element_instance_id) final;
   void DidResizeElement(const gfx::Size& new_size) override;
+  base::WeakPtr<BrowserPluginDelegate> GetWeakPtr() final;
 
  protected:
   ~GuestViewContainer() override;
@@ -89,7 +90,6 @@
   // BrowserPluginDelegate implementation.
   void Ready() final;
   void DidDestroyElement() final;
-  base::WeakPtr<BrowserPluginDelegate> GetWeakPtr() final;
 
   int element_instance_id_;
   content::RenderFrame* render_frame_;
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc
index b6e96c51..cd03e32 100644
--- a/components/ntp_snippets/pref_names.cc
+++ b/components/ntp_snippets/pref_names.cc
@@ -17,6 +17,9 @@
 const char kSnippetSoftFetchingIntervalOnUsageEvent[] =
     "ntp_snippets.soft_fetching_interval_on_usage_event";
 
+const char kSnippetSoftFetchingIntervalOnNtpOpened[] =
+    "ntp_snippets.soft_fetching_interval_on_ntp_opened";
+
 const char kSnippetPersistentFetchingIntervalWifi[] =
     "ntp_snippets.fetching_interval_wifi";
 
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h
index 7ff783d..ee60486 100644
--- a/components/ntp_snippets/pref_names.h
+++ b/components/ntp_snippets/pref_names.h
@@ -20,8 +20,11 @@
 extern const char kSnippetLastFetchAttempt[];
 // The pref name for the currently applied minimal interval between two
 // successive soft background fetches that react to user activity (such as
-// opening an NTP).
+// opening Chrome).
 extern const char kSnippetSoftFetchingIntervalOnUsageEvent[];
+// The pref name for the currently applied minimal interval between two
+// successive soft brackground fetches when the New Tab Page is opened.
+extern const char kSnippetSoftFetchingIntervalOnNtpOpened[];
 
 // The pref name for the currently-scheduled background fetching interval when
 // there is WiFi connectivity.
diff --git a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc
index 614907b5..deb218a 100644
--- a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc
+++ b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.cc
@@ -38,6 +38,7 @@
   PERSISTENT_FALLBACK,
   PERSISTENT_WIFI,
   SOFT_ON_USAGE_EVENT,
+  SOFT_ON_NTP_OPENED,
   COUNT
 };
 
@@ -47,25 +48,30 @@
 // The values of each array specify a default time interval for the intervals
 // defined by the enum FetchingInterval. The default time intervals defined in
 // the arrays can be overridden using different variation parameters.
-const double kDefaultFetchingIntervalHoursRareNtpUser[] = {48.0, 24.0, 12.0};
-const double kDefaultFetchingIntervalHoursActiveNtpUser[] = {24.0, 6.0, 2.0};
+const double kDefaultFetchingIntervalHoursRareNtpUser[] = {48.0, 24.0, 12.0,
+                                                           6.0};
+const double kDefaultFetchingIntervalHoursActiveNtpUser[] = {24.0, 6.0, 2.0,
+                                                             2.0};
 const double kDefaultFetchingIntervalHoursActiveSuggestionsConsumer[] = {
-    24.0, 6.0, 2.0};
+    24.0, 6.0, 2.0, 1.0};
 
 // Variation parameters than can be used to override the default fetching
 // intervals.
 const char* kFetchingIntervalParamNameRareNtpUser[] = {
     "fetching_interval_hours-fallback-rare_ntp_user",
     "fetching_interval_hours-wifi-rare_ntp_user",
-    "soft_fetching_interval_hours-active-rare_ntp_user"};
+    "soft_fetching_interval_hours-active-rare_ntp_user",
+    "soft_on_ntp_opened_interval_hours-rare_ntp_user"};
 const char* kFetchingIntervalParamNameActiveNtpUser[] = {
     "fetching_interval_hours-fallback-active_ntp_user",
     "fetching_interval_hours-wifi-active_ntp_user",
-    "soft_fetching_interval_hours-active-active_ntp_user"};
+    "soft_fetching_interval_hours-active-active_ntp_user",
+    "soft_on_ntp_opened_interval_hours-active_ntp_user"};
 const char* kFetchingIntervalParamNameActiveSuggestionsConsumer[] = {
     "fetching_interval_hours-fallback-active_suggestions_consumer",
     "fetching_interval_hours-wifi-active_suggestions_consumer",
-    "soft_fetching_interval_hours-active-active_suggestions_consumer"};
+    "soft_fetching_interval_hours-active-active_suggestions_consumer",
+    "soft_on_ntp_opened_interval_hours-active_suggestions_consumer"};
 
 static_assert(
     static_cast<unsigned int>(FetchingInterval::COUNT) ==
@@ -129,14 +135,15 @@
 SchedulingRemoteSuggestionsProvider::FetchingSchedule
 SchedulingRemoteSuggestionsProvider::FetchingSchedule::Empty() {
   return FetchingSchedule{base::TimeDelta(), base::TimeDelta(),
-                          base::TimeDelta()};
+                          base::TimeDelta(), base::TimeDelta()};
 }
 
 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator==(
     const FetchingSchedule& other) const {
   return interval_persistent_wifi == other.interval_persistent_wifi &&
          interval_persistent_fallback == other.interval_persistent_fallback &&
-         interval_soft_on_usage_event == other.interval_soft_on_usage_event;
+         interval_soft_on_usage_event == other.interval_soft_on_usage_event &&
+         interval_soft_on_ntp_opened == other.interval_soft_on_ntp_opened;
 }
 
 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::operator!=(
@@ -147,7 +154,8 @@
 bool SchedulingRemoteSuggestionsProvider::FetchingSchedule::is_empty() const {
   return interval_persistent_wifi.is_zero() &&
          interval_persistent_fallback.is_zero() &&
-         interval_soft_on_usage_event.is_zero();
+         interval_soft_on_usage_event.is_zero() &&
+         interval_soft_on_ntp_opened.is_zero();
 }
 
 // The TriggerType enum specifies values for the events that can trigger
@@ -203,6 +211,8 @@
   registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnUsageEvent,
                               0);
   registry->RegisterInt64Pref(prefs::kSnippetLastFetchAttempt, 0);
+  registry->RegisterInt64Pref(prefs::kSnippetSoftFetchingIntervalOnNtpOpened,
+                              0);
 }
 
 void SchedulingRemoteSuggestionsProvider::RescheduleFetching() {
@@ -218,7 +228,7 @@
 void SchedulingRemoteSuggestionsProvider::OnBrowserForegrounded() {
   // TODO(jkrcal): Consider that this is called whenever we open or return to an
   // Activity. Therefore, keep work light for fast start up calls.
-  if (!ShouldRefetchInTheBackgroundNow()) {
+  if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_FOREGROUNDED)) {
     return;
   }
 
@@ -228,7 +238,7 @@
 void SchedulingRemoteSuggestionsProvider::OnBrowserColdStart() {
   // TODO(fhorschig|jkrcal): Consider that work here must be kept light for fast
   // cold start ups.
-  if (!ShouldRefetchInTheBackgroundNow()) {
+  if (!ShouldRefetchInTheBackgroundNow(TriggerType::BROWSER_COLD_START)) {
     return;
   }
 
@@ -236,7 +246,7 @@
 }
 
 void SchedulingRemoteSuggestionsProvider::OnNTPOpened() {
-  if (!ShouldRefetchInTheBackgroundNow()) {
+  if (!ShouldRefetchInTheBackgroundNow(TriggerType::NTP_OPENED)) {
     return;
   }
 
@@ -394,6 +404,8 @@
       FetchingInterval::PERSISTENT_FALLBACK, user_class);
   schedule.interval_soft_on_usage_event = GetDesiredFetchingInterval(
       FetchingInterval::SOFT_ON_USAGE_EVENT, user_class);
+  schedule.interval_soft_on_ntp_opened = GetDesiredFetchingInterval(
+      FetchingInterval::SOFT_ON_NTP_OPENED, user_class);
 
   return schedule;
 }
@@ -406,6 +418,8 @@
           prefs::kSnippetPersistentFetchingIntervalFallback));
   schedule_.interval_soft_on_usage_event = base::TimeDelta::FromInternalValue(
       pref_service_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnUsageEvent));
+  schedule_.interval_soft_on_ntp_opened = base::TimeDelta::FromInternalValue(
+      pref_service_->GetInt64(prefs::kSnippetSoftFetchingIntervalOnNtpOpened));
 }
 
 void SchedulingRemoteSuggestionsProvider::StoreFetchingSchedule() {
@@ -417,6 +431,9 @@
   pref_service_->SetInt64(
       prefs::kSnippetSoftFetchingIntervalOnUsageEvent,
       schedule_.interval_soft_on_usage_event.ToInternalValue());
+  pref_service_->SetInt64(
+      prefs::kSnippetSoftFetchingIntervalOnNtpOpened,
+      schedule_.interval_soft_on_ntp_opened.ToInternalValue());
 }
 
 void SchedulingRemoteSuggestionsProvider::RefetchInTheBackgroundIfEnabled(
@@ -432,11 +449,26 @@
   RefetchInTheBackground(/*callback=*/nullptr);
 }
 
-bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow() {
-  base::Time first_allowed_fetch_time =
-      base::Time::FromInternalValue(
-          pref_service_->GetInt64(prefs::kSnippetLastFetchAttempt)) +
-      schedule_.interval_soft_on_usage_event;
+bool SchedulingRemoteSuggestionsProvider::ShouldRefetchInTheBackgroundNow(
+    SchedulingRemoteSuggestionsProvider::TriggerType trigger) {
+  const base::Time last_fetch_attempt_time = base::Time::FromInternalValue(
+      pref_service_->GetInt64(prefs::kSnippetLastFetchAttempt));
+  base::Time first_allowed_fetch_time;
+  switch (trigger) {
+    case TriggerType::NTP_OPENED:
+      first_allowed_fetch_time =
+          last_fetch_attempt_time + schedule_.interval_soft_on_ntp_opened;
+      break;
+    case TriggerType::BROWSER_FOREGROUNDED:
+    case TriggerType::BROWSER_COLD_START:
+      first_allowed_fetch_time =
+          last_fetch_attempt_time + schedule_.interval_soft_on_usage_event;
+      break;
+    case TriggerType::PERSISTENT_SCHEDULER_WAKE_UP:
+    case TriggerType::COUNT:
+      NOTREACHED();
+      break;
+  }
   return first_allowed_fetch_time <= clock_->Now();
 }
 
diff --git a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.h b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.h
index 7a42b47..d0639cb 100644
--- a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.h
+++ b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider.h
@@ -114,6 +114,7 @@
       base::TimeDelta interval_persistent_wifi;
       base::TimeDelta interval_persistent_fallback;
       base::TimeDelta interval_soft_on_usage_event;
+      base::TimeDelta interval_soft_on_ntp_opened;
   };
 
   enum class TriggerType;
@@ -137,7 +138,7 @@
 
   // Checks whether it is time to perform a soft background fetch, according to
   // |schedule|.
-  bool ShouldRefetchInTheBackgroundNow();
+  bool ShouldRefetchInTheBackgroundNow(TriggerType trigger);
 
   // Returns whether background fetching (for the given |trigger|) is disabled.
   bool BackgroundFetchesDisabled(TriggerType trigger) const;
diff --git a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc
index 950923f..0acb45c 100644
--- a/components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc
+++ b/components/ntp_snippets/remote/scheduling_remote_suggestions_provider_unittest.cc
@@ -419,7 +419,7 @@
 }
 
 TEST_F(SchedulingRemoteSuggestionsProviderTest,
-       ShouldFetchAgainOnNTPOpenedLaterAgain) {
+       ShouldFetchAgainOnBrowserForgroundLaterAgain) {
   RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
   {
     InSequence s;
@@ -438,11 +438,11 @@
   ChangeStatusOfUnderlyingProvider(
       RemoteSuggestionsProvider::ProviderStatus::ACTIVE);
   // Make the first soft fetch successful.
-  scheduling_provider_->OnNTPOpened();
+  scheduling_provider_->OnBrowserForegrounded();
   signal_fetch_done.Run(Status::Success());
   // Open NTP again after 2hrs.
   test_clock_->Advance(base::TimeDelta::FromHours(2));
-  scheduling_provider_->OnNTPOpened();
+  scheduling_provider_->OnBrowserForegrounded();
 }
 
 TEST_F(SchedulingRemoteSuggestionsProviderTest,
@@ -586,4 +586,92 @@
       RemoteSuggestionsProvider::ProviderStatus::ACTIVE);
 }
 
+TEST_F(SchedulingRemoteSuggestionsProviderTest,
+       ReschedulesWhenOnNtpOpenedParamChanges) {
+  EXPECT_CALL(persistent_scheduler_, Schedule(_, _)).Times(2);
+  ChangeStatusOfUnderlyingProvider(
+      RemoteSuggestionsProvider::ProviderStatus::ACTIVE);
+
+  // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
+  // null. Change the fallback interval for this class.
+  SetVariationParameter("soft_on_ntp_opened_interval_hours-active_ntp_user",
+                        "1.5");
+
+  // Schedule() should get called for the second time after params have changed.
+  ChangeStatusOfUnderlyingProvider(
+      RemoteSuggestionsProvider::ProviderStatus::ACTIVE);
+}
+
+TEST_F(SchedulingRemoteSuggestionsProviderTest,
+       FetchIntervalForNtpOpenedTrigger) {
+  RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
+  {
+    InSequence s;
+    // Initial scheduling after being enabled.
+    EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
+    // The first call to NTPOpened results in a fetch.
+    EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
+        .WillOnce(SaveArg<0>(&signal_fetch_done));
+    // Rescheduling after a succesful fetch.
+    EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
+    // The third call to NTPOpened 35min later again results in a fetch.
+    EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
+  }
+
+  ChangeStatusOfUnderlyingProvider(
+      RemoteSuggestionsProvider::ProviderStatus::ACTIVE);
+
+  scheduling_provider_->OnNTPOpened();
+  signal_fetch_done.Run(Status::Success());
+
+  // UserClassifier defaults to UserClass::ACTIVE_NTP_USER which uses a 2h time
+  // interval by default for soft backgroudn fetches on ntp open events.
+
+  // Open NTP again after 20min. This time no fetch is executed.
+  test_clock_->Advance(base::TimeDelta::FromMinutes(20));
+  scheduling_provider_->OnNTPOpened();
+
+  // Open NTP again after 101min (121min since first opened). Since the default
+  // time interval has passed refetch again.
+  test_clock_->Advance(base::TimeDelta::FromMinutes(101));
+  scheduling_provider_->OnNTPOpened();
+}
+
+TEST_F(SchedulingRemoteSuggestionsProviderTest,
+       OverrideFetchIntervalForNtpOpenedTrigger) {
+  // UserClassifier defaults to UserClass::ACTIVE_NTP_USER if PrefService is
+  // null. Change the on usage interval for this class from 2h to 30min.
+  SetVariationParameter("soft_on_ntp_opened_interval_hours-active_ntp_user",
+                        "0.5");
+
+  RemoteSuggestionsProvider::FetchStatusCallback signal_fetch_done;
+  {
+    InSequence s;
+    // Initial scheduling after being enabled.
+    EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
+    // The first call to NTPOpened results in a fetch.
+    EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_))
+        .WillOnce(SaveArg<0>(&signal_fetch_done));
+    // Rescheduling after a succesful fetch.
+    EXPECT_CALL(persistent_scheduler_, Schedule(_, _));
+    // The third call to NTPOpened 35min later again results in a fetch.
+    EXPECT_CALL(*underlying_provider_, RefetchInTheBackground(_));
+  }
+
+  ChangeStatusOfUnderlyingProvider(
+      RemoteSuggestionsProvider::ProviderStatus::ACTIVE);
+
+  scheduling_provider_->OnNTPOpened();
+  signal_fetch_done.Run(Status::Success());
+
+  // Open NTP again after 20min. No fetch request is issues since the 30 min
+  // time interval has not passed yet.
+  test_clock_->Advance(base::TimeDelta::FromMinutes(20));
+  scheduling_provider_->OnNTPOpened();
+
+  // Open NTP again after 15min (35min since first opened)
+  test_clock_->Advance(base::TimeDelta::FromMinutes(15));
+  scheduling_provider_->OnNTPOpened();
+}
+
 }  // namespace ntp_snippets
diff --git a/components/payments/payment_request.cc b/components/payments/payment_request.cc
index fd2fc4f5..9ea28a8 100644
--- a/components/payments/payment_request.cc
+++ b/components/payments/payment_request.cc
@@ -10,8 +10,17 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 
+using payments::mojom::BasicCardNetwork;
+
 namespace payments {
 
+namespace {
+
+// Identifier for the basic card payment method in the PaymentMethodData.
+const char* const kBasicCardMethodName = "basic-card";
+
+}  // namespace
+
 PaymentRequest::PaymentRequest(
     content::WebContents* web_contents,
     std::unique_ptr<PaymentRequestDelegate> delegate,
@@ -37,7 +46,7 @@
 
 void PaymentRequest::Init(
     payments::mojom::PaymentRequestClientPtr client,
-    std::vector<payments::mojom::PaymentMethodDataPtr> methodData,
+    std::vector<payments::mojom::PaymentMethodDataPtr> method_data,
     payments::mojom::PaymentDetailsPtr details,
     payments::mojom::PaymentOptionsPtr options) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -49,6 +58,7 @@
   }
   client_ = std::move(client);
   details_ = std::move(details);
+  PopulateValidatedMethodData(method_data);
   PopulateProfileCache();
   SetDefaultProfileSelections();
 }
@@ -160,4 +170,75 @@
     set_selected_contact_profile(contact_profiles()[0]);
 }
 
+void PaymentRequest::PopulateValidatedMethodData(
+    const std::vector<payments::mojom::PaymentMethodDataPtr>& method_data) {
+  if (method_data.empty()) {
+    LOG(ERROR) << "Invalid payment methods or data";
+    OnConnectionTerminated();
+    return;
+  }
+
+  std::set<std::string> card_networks{"amex",     "diners",     "discover",
+                                      "jcb",      "mastercard", "mir",
+                                      "unionpay", "visa"};
+  for (const payments::mojom::PaymentMethodDataPtr& method_data_entry :
+       method_data) {
+    std::vector<std::string> supported_methods =
+        method_data_entry->supported_methods;
+    if (supported_methods.empty()) {
+      LOG(ERROR) << "Invalid payment methods or data";
+      OnConnectionTerminated();
+      return;
+    }
+
+    for (const std::string& method : supported_methods) {
+      if (method.empty())
+        continue;
+
+      // If a card network is specified right in "supportedMethods", add it.
+      auto card_it = card_networks.find(method);
+      if (card_it != card_networks.end()) {
+        supported_card_networks_.push_back(method);
+        // |method| removed from |card_networks| so that it is not doubly added
+        // to |supported_card_networks_| if "basic-card" is specified with no
+        // supported networks.
+        card_networks.erase(card_it);
+      } else if (method == kBasicCardMethodName) {
+        // For the "basic-card" method, check "supportedNetworks".
+        if (method_data_entry->supported_networks.empty()) {
+          // Empty |supported_networks| means all networks are supported.
+          supported_card_networks_.insert(supported_card_networks_.end(),
+                                          card_networks.begin(),
+                                          card_networks.end());
+          // Clear the set so that no further networks are added to
+          // |supported_card_networks_|.
+          card_networks.clear();
+        } else {
+          // The merchant has specified a few basic card supported networks. Use
+          // the mapping to transform to known basic-card types.
+          std::unordered_map<BasicCardNetwork, std::string> networks = {
+              {BasicCardNetwork::AMEX, "amex"},
+              {BasicCardNetwork::DINERS, "diners"},
+              {BasicCardNetwork::DISCOVER, "discover"},
+              {BasicCardNetwork::JCB, "jcb"},
+              {BasicCardNetwork::MASTERCARD, "mastercard"},
+              {BasicCardNetwork::MIR, "mir"},
+              {BasicCardNetwork::UNIONPAY, "unionpay"},
+              {BasicCardNetwork::VISA, "visa"}};
+          for (const BasicCardNetwork& supported_network :
+               method_data_entry->supported_networks) {
+            // Make sure that the network was not already added to
+            // |supported_card_networks_|.
+            auto card_it = card_networks.find(networks[supported_network]);
+            if (card_it != card_networks.end()) {
+              supported_card_networks_.push_back(networks[supported_network]);
+              card_networks.erase(card_it);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
 }  // namespace payments
diff --git a/components/payments/payment_request.h b/components/payments/payment_request.h
index cd54b7c..bde05954 100644
--- a/components/payments/payment_request.h
+++ b/components/payments/payment_request.h
@@ -39,7 +39,7 @@
 
   // payments::mojom::PaymentRequest "stub"
   void Init(payments::mojom::PaymentRequestClientPtr client,
-            std::vector<payments::mojom::PaymentMethodDataPtr> methodData,
+            std::vector<payments::mojom::PaymentMethodDataPtr> method_data,
             payments::mojom::PaymentDetailsPtr details,
             payments::mojom::PaymentOptionsPtr options) override;
   void Show() override;
@@ -101,6 +101,9 @@
   }
 
   payments::mojom::PaymentDetails* details() { return details_.get(); }
+  const std::vector<std::string>& supported_card_networks() {
+    return supported_card_networks_;
+  }
   content::WebContents* web_contents() { return web_contents_; }
 
  private:
@@ -111,6 +114,10 @@
   // Sets the default values for the selected Shipping and Contact profiles.
   void SetDefaultProfileSelections();
 
+  // Validates the |method_data| and fills |supported_card_networks_|.
+  void PopulateValidatedMethodData(
+      const std::vector<payments::mojom::PaymentMethodDataPtr>& method_data);
+
   content::WebContents* web_contents_;
   std::unique_ptr<PaymentRequestDelegate> delegate_;
   // |manager_| owns this PaymentRequest.
@@ -119,6 +126,8 @@
   payments::mojom::PaymentRequestClientPtr client_;
   payments::mojom::PaymentDetailsPtr details_;
   std::unique_ptr<CurrencyFormatter> currency_formatter_;
+  // A set of supported basic card networks.
+  std::vector<std::string> supported_card_networks_;
 
   // Profiles may change due to (e.g.) sync events, so profiles are cached after
   // loading and owned here. They are populated once only, and ordered by
diff --git a/components/safe_browsing/base_ui_manager.cc b/components/safe_browsing/base_ui_manager.cc
index 9ea77fe..f951896d 100644
--- a/components/safe_browsing/base_ui_manager.cc
+++ b/components/safe_browsing/base_ui_manager.cc
@@ -215,13 +215,15 @@
     return;
   }
 
-  // BaseUIManager does not send SafeBrowsingHitReport. Subclasses should
-  // implement the reporting logic themselves if needed.
+  if (resource.threat_type != SB_THREAT_TYPE_SAFE) {
+    CreateAndSendHitReport(resource);
+  }
+
   AddToWhitelistUrlSet(GetMainFrameWhitelistUrlForResource(resource),
                        resource.web_contents_getter.Run(),
                        true /* A decision is now pending */,
                        resource.threat_type);
-  BaseBlockingPage::ShowBlockingPage(this, resource);
+  ShowBlockingPageForResource(resource);
 }
 
 void BaseUIManager::EnsureWhitelistCreated(
@@ -234,6 +236,13 @@
   return;
 }
 
+void BaseUIManager::CreateAndSendHitReport(const UnsafeResource& resource) {}
+
+void BaseUIManager::ShowBlockingPageForResource(
+    const UnsafeResource& resource) {
+  BaseBlockingPage::ShowBlockingPage(this, resource);
+}
+
 // A safebrowsing hit is sent after a blocking page for malware/phishing
 // or after the warning dialog for download urls, only for
 // UMA || extended_reporting users.
diff --git a/components/safe_browsing/base_ui_manager.h b/components/safe_browsing/base_ui_manager.h
index 638e0cd4..1230417 100644
--- a/components/safe_browsing/base_ui_manager.h
+++ b/components/safe_browsing/base_ui_manager.h
@@ -136,6 +136,14 @@
   static GURL GetMainFrameWhitelistUrlForResource(
       const security_interstitials::UnsafeResource& resource);
 
+  // BaseUIManager does not send SafeBrowsingHitReport. Subclasses should
+  // implement the reporting logic themselves if needed.
+  virtual void CreateAndSendHitReport(const UnsafeResource& resource);
+
+  // Calls BaseBlockingPage::ShowBlockingPage(). Override this if using a
+  // different blocking page.
+  virtual void ShowBlockingPageForResource(const UnsafeResource& resource);
+
  private:
   friend class base::RefCountedThreadSafe<BaseUIManager>;
 
diff --git a/content/browser/android/synchronous_compositor_browser_filter.cc b/content/browser/android/synchronous_compositor_browser_filter.cc
index 838c80e..f4e661965 100644
--- a/content/browser/android/synchronous_compositor_browser_filter.cc
+++ b/content/browser/android/synchronous_compositor_browser_filter.cc
@@ -194,12 +194,14 @@
   if (!render_process_host_->Send(
           new SyncCompositorMsg_SynchronizeRendererState(routing_ids,
                                                          &params))) {
+    compositor_host_pending_renderer_state_.clear();
     return;
   }
 
   if (compositor_host_pending_renderer_state_.size() != params.size()) {
     bad_message::ReceivedBadMessage(render_process_host_,
                                     bad_message::SCO_INVALID_ARGUMENT);
+    compositor_host_pending_renderer_state_.clear();
     return;
   }
 
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 9e954d8..7b92187 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -448,6 +448,7 @@
       should_normally_be_visible_(true),
       did_first_set_visible_(false),
       is_being_destroyed_(false),
+      is_notifying_observers_(false),
       notify_disconnection_(false),
       dialog_manager_(NULL),
       is_showing_before_unload_dialog_(false),
@@ -494,6 +495,11 @@
 WebContentsImpl::~WebContentsImpl() {
   is_being_destroyed_ = true;
 
+  // A WebContents should never be deleted while it is notifying observers,
+  // since this will lead to a use-after-free as it continues to notfiy later
+  // observers.
+  CHECK(!is_notifying_observers_);
+
   rwh_input_event_router_.reset();
 
   for (auto& entry : binding_sets_)
@@ -4558,8 +4564,10 @@
     RenderFrameHost* render_frame_host) {
   ShowInsecureLocalhostWarningIfNeeded();
 
+  is_notifying_observers_ = true;
   for (auto& observer : observers_)
     observer.DocumentOnLoadCompletedInMainFrame();
+  is_notifying_observers_ = false;
 
   // TODO(avi): Remove. http://crbug.com/170921
   NotificationService::current()->Notify(
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index a88e34b8e..cf9f25f 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -1307,6 +1307,10 @@
   // See getter above.
   bool is_being_destroyed_;
 
+  // Keep track of whether this WebContents is currently iterating over its list
+  // of observers, during which time it should not be deleted.
+  bool is_notifying_observers_;
+
   // Indicates whether we should notify about disconnection of this
   // WebContentsImpl. This is used to ensure disconnection notifications only
   // happen if a connection notification has happened and that they happen only
diff --git a/content/browser/zygote_host/OWNERS b/content/browser/zygote_host/OWNERS
index 8a7f8eb..75b96d59 100644
--- a/content/browser/zygote_host/OWNERS
+++ b/content/browser/zygote_host/OWNERS
@@ -1,3 +1,6 @@
 jln@chromium.org
 mdempsky@chromium.org
 rickyz@chromium.org
+
+# TEAM: security-dev@chromium.org
+# COMPONENT: Internals>Sandbox
diff --git a/content/common/sandbox_linux/OWNERS b/content/common/sandbox_linux/OWNERS
index 4f1c402..444aa4e 100644
--- a/content/common/sandbox_linux/OWNERS
+++ b/content/common/sandbox_linux/OWNERS
@@ -3,3 +3,6 @@
 mdempsky@chromium.org
 rickyz@chromium.org
 rsesek@chromium.org
+
+# TEAM: security-dev@chromium.org
+# COMPONENT: Internals>Sandbox
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index ea65b56..bd5b2962 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -505,6 +505,10 @@
         ['mac', 'amd'], bug=645298)
 
     # Mac Pro with AMD GPU
+    self.Fail('deqp/functional/gles3/fborender/recreate_color_02.html',
+        ['mac', ('amd', 0x679e)], bug=679682)
+    self.Fail('deqp/functional/gles3/fborender/resize_01.html',
+        ['mac', ('amd', 0x679e)], bug=679682)
     self.Flaky('deqp/functional/gles3/shaderindexing/mat_01.html',
         ['mac', ('amd', 0x679e)], bug=636648)
     self.Flaky('deqp/functional/gles3/shaderindexing/tmp.html',
@@ -515,10 +519,6 @@
         ['mac', ('amd', 0x679e)], bug=483282)
 
     # Mac Multi-vendor failures.
-    self.Fail('deqp/functional/gles3/fborender/recreate_color_02.html',
-        ['mac', 'nvidia', 'amd'], bug=679682)
-    self.Fail('deqp/functional/gles3/fborender/resize_01.html',
-        ['mac', 'nvidia', 'amd'], bug=679682)
     self.Fail('deqp/functional/gles3/fragmentoutput/basic.float.html',
         ['mac', 'nvidia', 'amd'], bug=679684)
     self.Fail('deqp/functional/gles3/fragmentoutput/array.float.html',
diff --git a/content/zygote/OWNERS b/content/zygote/OWNERS
index 8a7f8eb..75b96d59 100644
--- a/content/zygote/OWNERS
+++ b/content/zygote/OWNERS
@@ -1,3 +1,6 @@
 jln@chromium.org
 mdempsky@chromium.org
 rickyz@chromium.org
+
+# TEAM: security-dev@chromium.org
+# COMPONENT: Internals>Sandbox
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn
index 4e22715..9fb1235 100644
--- a/device/usb/BUILD.gn
+++ b/device/usb/BUILD.gn
@@ -34,6 +34,8 @@
     "usb_device_handle_android.h",
     "usb_device_linux.cc",
     "usb_device_linux.h",
+    "usb_device_win.cc",
+    "usb_device_win.h",
     "usb_endpoint_android.cc",
     "usb_endpoint_android.h",
     "usb_ids.cc",
@@ -89,6 +91,10 @@
     deps += [ "//third_party/libusb" ]
   }
 
+  if (is_win) {
+    libs = [ "setupapi.lib" ]
+  }
+
   if (is_android || is_chromeos || is_linux) {
     sources += [
       "usb_device_handle_usbfs.cc",
diff --git a/device/usb/usb_device.cc b/device/usb/usb_device.cc
index c7ffa73c..b6198d0 100644
--- a/device/usb/usb_device.cc
+++ b/device/usb/usb_device.cc
@@ -14,6 +14,8 @@
 
 void UsbDevice::Observer::OnDeviceRemoved(scoped_refptr<UsbDevice> device) {}
 
+UsbDevice::UsbDevice() : guid_(base::GenerateGUID()) {}
+
 UsbDevice::UsbDevice(const UsbDeviceDescriptor& descriptor,
                      const base::string16& manufacturer_string,
                      const base::string16& product_string,
@@ -47,8 +49,7 @@
   descriptor_.device_version = device_version;
 }
 
-UsbDevice::~UsbDevice() {
-}
+UsbDevice::~UsbDevice() {}
 
 void UsbDevice::CheckUsbAccess(const ResultCallback& callback) {
   // By default assume that access to the device is allowed. This is implemented
diff --git a/device/usb/usb_device.h b/device/usb/usb_device.h
index 58c9792..4dc115c 100644
--- a/device/usb/usb_device.h
+++ b/device/usb/usb_device.h
@@ -96,6 +96,7 @@
  protected:
   friend class UsbService;
 
+  UsbDevice();
   UsbDevice(const UsbDeviceDescriptor& descriptor,
             const base::string16& manufacturer_string,
             const base::string16& product_string,
@@ -134,6 +135,7 @@
   friend class UsbServiceAndroid;
   friend class UsbServiceImpl;
   friend class UsbServiceLinux;
+  friend class UsbServiceWin;
 
   void OnDisconnect();
   void HandleClosed(UsbDeviceHandle* handle);
diff --git a/device/usb/usb_device_win.cc b/device/usb/usb_device_win.cc
new file mode 100644
index 0000000..172858d
--- /dev/null
+++ b/device/usb/usb_device_win.cc
@@ -0,0 +1,35 @@
+// 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.
+
+#include "device/usb/usb_device_win.h"
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/device_event_log/device_event_log.h"
+#include "device/usb/usb_device_handle.h"
+
+namespace device {
+
+UsbDeviceWin::UsbDeviceWin(
+    const std::string& device_path,
+    const std::string& hub_path,
+    int port_number,
+    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
+    : device_path_(device_path),
+      hub_path_(hub_path),
+      port_number_(port_number),
+      task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      blocking_task_runner_(std::move(blocking_task_runner)) {}
+
+UsbDeviceWin::~UsbDeviceWin() {}
+
+void UsbDeviceWin::Open(const OpenCallback& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  task_runner_->PostTask(FROM_HERE, base::Bind(callback, nullptr));
+}
+
+}  // namespace device
diff --git a/device/usb/usb_device_win.h b/device/usb/usb_device_win.h
new file mode 100644
index 0000000..0a74c06
--- /dev/null
+++ b/device/usb/usb_device_win.h
@@ -0,0 +1,55 @@
+// 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.
+
+#ifndef DEVICE_USB_USB_DEVICE_WIN_H_
+#define DEVICE_USB_USB_DEVICE_WIN_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "device/usb/usb_device.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace device {
+
+class UsbDeviceWin : public UsbDevice {
+ public:
+  // UsbDevice implementation:
+  void Open(const OpenCallback& callback) override;
+
+ protected:
+  friend class UsbServiceWin;
+  friend class UsbDeviceHandleWin;
+
+  // Called by UsbServiceWin only;
+  UsbDeviceWin(const std::string& device_path,
+               const std::string& hub_path,
+               int port_number,
+               scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+  ~UsbDeviceWin() override;
+
+  const std::string& device_path() const { return device_path_; }
+  int port_number() const { return port_number_; }
+
+ private:
+  base::ThreadChecker thread_checker_;
+
+  const std::string device_path_;
+  const std::string hub_path_;
+  const int port_number_;
+
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(UsbDeviceWin);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_USB_USB_DEVICE_WIN_H_
diff --git a/device/usb/usb_service_impl.h b/device/usb/usb_service_impl.h
index e5467fb..c644842 100644
--- a/device/usb/usb_service_impl.h
+++ b/device/usb/usb_service_impl.h
@@ -34,6 +34,8 @@
 typedef struct libusb_device* PlatformUsbDevice;
 typedef struct libusb_context* PlatformUsbContext;
 
+class UsbDeviceImpl;
+
 class UsbServiceImpl :
 #if defined(OS_WIN)
     public DeviceMonitorWin::Observer,
diff --git a/device/usb/usb_service_win.cc b/device/usb/usb_service_win.cc
index 6feea89..131fdb33 100644
--- a/device/usb/usb_service_win.cc
+++ b/device/usb/usb_service_win.cc
@@ -4,12 +4,386 @@
 
 #include "device/usb/usb_service_win.h"
 
+#include <setupapi.h>
+#include <stdint.h>
+#include <usbiodef.h>
+
+#define INITGUID
+#include <devpkey.h>
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/memory/free_deleter.h"
+#include "base/memory/ptr_util.h"
+#include "base/scoped_generic.h"
+#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/win/scoped_handle.h"
+#include "components/device_event_log/device_event_log.h"
+#include "device/usb/usb_descriptors.h"
+#include "device/usb/usb_device_handle.h"
+#include "device/usb/webusb_descriptors.h"
+
 namespace device {
 
+namespace {
+
+struct DevInfoScopedTraits {
+  static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
+  static void Free(HDEVINFO h) { SetupDiDestroyDeviceInfoList(h); }
+};
+
+using ScopedDevInfo = base::ScopedGeneric<HDEVINFO, DevInfoScopedTraits>;
+
+bool GetDeviceUint32Property(HDEVINFO dev_info,
+                             SP_DEVINFO_DATA* dev_info_data,
+                             const DEVPROPKEY& property,
+                             uint32_t* property_buffer) {
+  DEVPROPTYPE property_type;
+  if (!SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
+                                &property_type,
+                                reinterpret_cast<PBYTE>(property_buffer),
+                                sizeof(*property_buffer), nullptr, 0) ||
+      property_type != DEVPROP_TYPE_UINT32) {
+    return false;
+  }
+
+  return true;
+}
+
+bool GetDeviceStringProperty(HDEVINFO dev_info,
+                             SP_DEVINFO_DATA* dev_info_data,
+                             const DEVPROPKEY& property,
+                             std::string* property_buffer) {
+  DEVPROPTYPE property_type;
+  DWORD required_size;
+  if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
+                               &property_type, nullptr, 0, &required_size, 0) ||
+      GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
+      property_type != DEVPROP_TYPE_STRING) {
+    return false;
+  }
+
+  std::wstring wide_buffer;
+  if (!SetupDiGetDeviceProperty(
+          dev_info, dev_info_data, &property, &property_type,
+          reinterpret_cast<PBYTE>(base::WriteInto(&wide_buffer, required_size)),
+          required_size, nullptr, 0)) {
+    return false;
+  }
+
+  *property_buffer = base::SysWideToUTF8(wide_buffer);
+  return true;
+}
+
+bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
+                               SP_DEVICE_INTERFACE_DATA* device_interface_data,
+                               std::string* device_path,
+                               uint32_t* port_number,
+                               std::string* parent_instance_id) {
+  DWORD required_size;
+  if (SetupDiGetDeviceInterfaceDetail(dev_info, device_interface_data, nullptr,
+                                      0, &required_size, nullptr) ||
+      GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+    return false;
+  }
+
+  std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>
+  device_interface_detail_data(
+      static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(required_size)));
+  device_interface_detail_data->cbSize = sizeof(*device_interface_detail_data);
+
+  SP_DEVINFO_DATA dev_info_data;
+  dev_info_data.cbSize = sizeof(dev_info_data);
+
+  if (!SetupDiGetDeviceInterfaceDetail(
+          dev_info, device_interface_data, device_interface_detail_data.get(),
+          required_size, nullptr, &dev_info_data)) {
+    USB_PLOG(ERROR) << "SetupDiGetDeviceInterfaceDetail";
+    return false;
+  }
+
+  if (device_path) {
+    *device_path =
+        base::SysWideToUTF8(device_interface_detail_data->DevicePath);
+  }
+
+  if (port_number) {
+    if (!GetDeviceUint32Property(dev_info, &dev_info_data,
+                                 DEVPKEY_Device_Address, port_number)) {
+      USB_PLOG(ERROR) << "Failed to get device address";
+      return false;
+    }
+  }
+
+  if (parent_instance_id) {
+    if (!GetDeviceStringProperty(dev_info, &dev_info_data,
+                                 DEVPKEY_Device_Parent, parent_instance_id)) {
+      USB_PLOG(ERROR) << "Failed to get the device parent";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool GetHubDevicePath(const std::string& instance_id,
+                      std::string* device_path) {
+  ScopedDevInfo dev_info(
+      SetupDiGetClassDevsA(&GUID_DEVINTERFACE_USB_HUB, instance_id.c_str(), 0,
+                           DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
+  if (!dev_info.is_valid()) {
+    USB_PLOG(ERROR) << "SetupDiGetClassDevs";
+    return false;
+  }
+
+  SP_DEVICE_INTERFACE_DATA device_interface_data;
+  device_interface_data.cbSize = sizeof(device_interface_data);
+  if (!SetupDiEnumDeviceInterfaces(dev_info.get(), nullptr,
+                                   &GUID_DEVINTERFACE_USB_HUB, 0,
+                                   &device_interface_data)) {
+    USB_PLOG(ERROR) << "SetupDiEnumDeviceInterfaces";
+    return false;
+  }
+
+  return GetDeviceInterfaceDetails(dev_info.get(), &device_interface_data,
+                                   device_path, nullptr, nullptr);
+}
+
+}  // namespace
+
+class UsbServiceWin::BlockingThreadHelper {
+ public:
+  explicit BlockingThreadHelper(base::WeakPtr<UsbServiceWin> service)
+      : service_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+        service_(service) {}
+  ~BlockingThreadHelper() {}
+
+  void EnumerateDevices() {
+    ScopedDevInfo dev_info(
+        SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, 0,
+                            DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
+    if (!dev_info.is_valid()) {
+      USB_PLOG(ERROR) << "Failed to set up device enumeration";
+      service_task_runner_->PostTask(
+          FROM_HERE, base::Bind(&UsbServiceWin::HelperStarted, service_));
+      return;
+    }
+
+    SP_DEVICE_INTERFACE_DATA device_interface_data;
+    device_interface_data.cbSize = sizeof(device_interface_data);
+    for (DWORD i = 0; SetupDiEnumDeviceInterfaces(dev_info.get(), nullptr,
+                                                  &GUID_DEVINTERFACE_USB_DEVICE,
+                                                  i, &device_interface_data);
+         ++i) {
+      std::string device_path;
+      uint32_t port_number;
+      std::string parent_instance_id;
+      if (!GetDeviceInterfaceDetails(dev_info.get(), &device_interface_data,
+                                     &device_path, &port_number,
+                                     &parent_instance_id)) {
+        continue;
+      }
+
+      std::string& hub_path = hub_paths_[parent_instance_id];
+      if (hub_path.empty()) {
+        std::string parent_path;
+        if (!GetHubDevicePath(parent_instance_id, &parent_path))
+          continue;
+
+        hub_path = parent_path;
+      }
+
+      service_task_runner_->PostTask(
+          FROM_HERE, base::Bind(&UsbServiceWin::CreateDeviceObject, service_,
+                                device_path, hub_path, port_number));
+    }
+
+    if (GetLastError() != ERROR_NO_MORE_ITEMS)
+      USB_PLOG(ERROR) << "Failed to enumerate devices";
+
+    service_task_runner_->PostTask(
+        FROM_HERE, base::Bind(&UsbServiceWin::HelperStarted, service_));
+  }
+
+  void EnumerateDevicePath(const std::string& device_path) {
+    ScopedDevInfo dev_info(
+        SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, 0,
+                            DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
+    if (!dev_info.is_valid()) {
+      USB_PLOG(ERROR) << "Failed to set up device enumeration";
+      return;
+    }
+
+    SP_DEVICE_INTERFACE_DATA device_interface_data;
+    device_interface_data.cbSize = sizeof(device_interface_data);
+    if (!SetupDiOpenDeviceInterfaceA(dev_info.get(), device_path.c_str(), 0,
+                                     &device_interface_data)) {
+      USB_PLOG(ERROR) << "Failed to add device interface: " << device_path;
+      return;
+    }
+
+    uint32_t port_number;
+    std::string parent_instance_id;
+    if (!GetDeviceInterfaceDetails(dev_info.get(), &device_interface_data,
+                                   nullptr, &port_number,
+                                   &parent_instance_id)) {
+      return;
+    }
+
+    std::string& hub_path = hub_paths_[parent_instance_id];
+    if (hub_path.empty()) {
+      std::string parent_path;
+      if (!GetHubDevicePath(parent_instance_id, &parent_path))
+        return;
+
+      hub_path = parent_path;
+    }
+
+    service_task_runner_->PostTask(
+        FROM_HERE, base::Bind(&UsbServiceWin::CreateDeviceObject, service_,
+                              device_path, hub_path, port_number));
+  }
+
+ private:
+  std::unordered_map<std::string, std::string> hub_paths_;
+
+  // Calls back to |service_| must be posted to |service_task_runner_|, which
+  // runs tasks on the thread where that object lives.
+  scoped_refptr<base::SingleThreadTaskRunner> service_task_runner_;
+  base::WeakPtr<UsbServiceWin> service_;
+};
+
 UsbServiceWin::UsbServiceWin(
     scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
-    : UsbService(blocking_task_runner) {}
+    : UsbService(blocking_task_runner),
+      device_observer_(this),
+      weak_factory_(this) {
+  DeviceMonitorWin* device_monitor =
+      DeviceMonitorWin::GetForDeviceInterface(GUID_DEVINTERFACE_USB_DEVICE);
+  if (device_monitor)
+    device_observer_.Add(device_monitor);
+
+  helper_ = new BlockingThreadHelper(weak_factory_.GetWeakPtr());
+  blocking_task_runner->PostTask(
+      FROM_HERE, base::Bind(&BlockingThreadHelper::EnumerateDevices,
+                            base::Unretained(helper_)));
+}
 
 UsbServiceWin::~UsbServiceWin() {}
 
+void UsbServiceWin::GetDevices(const GetDevicesCallback& callback) {
+  DCHECK(CalledOnValidThread());
+  if (enumeration_ready())
+    UsbService::GetDevices(callback);
+  else
+    enumeration_callbacks_.push_back(callback);
+}
+
+void UsbServiceWin::OnDeviceAdded(const GUID& class_guid,
+                                  const std::string& device_path) {
+  blocking_task_runner()->PostTask(
+      FROM_HERE, base::Bind(&BlockingThreadHelper::EnumerateDevicePath,
+                            base::Unretained(helper_), device_path));
+}
+
+void UsbServiceWin::OnDeviceRemoved(const GUID& class_guid,
+                                    const std::string& device_path) {
+  DCHECK(CalledOnValidThread());
+  auto by_path_it = devices_by_path_.find(device_path);
+  if (by_path_it == devices_by_path_.end())
+    return;
+
+  scoped_refptr<UsbDeviceWin> device = by_path_it->second;
+  devices_by_path_.erase(by_path_it);
+  device->OnDisconnect();
+
+  auto by_guid_it = devices().find(device->guid());
+  if (by_guid_it != devices().end() && enumeration_ready()) {
+    USB_LOG(USER) << "USB device removed: path=" << device->device_path()
+                  << " guid=" << device->guid();
+
+    devices().erase(by_guid_it);
+    NotifyDeviceRemoved(device);
+  }
+}
+
+void UsbServiceWin::HelperStarted() {
+  DCHECK(CalledOnValidThread());
+  helper_started_ = true;
+  if (enumeration_ready()) {
+    std::vector<scoped_refptr<UsbDevice>> result;
+    result.reserve(devices().size());
+    for (const auto& map_entry : devices())
+      result.push_back(map_entry.second);
+    for (const auto& callback : enumeration_callbacks_)
+      callback.Run(result);
+    enumeration_callbacks_.clear();
+  }
+}
+
+void UsbServiceWin::CreateDeviceObject(const std::string& device_path,
+                                       const std::string& hub_path,
+                                       int port_number) {
+  // Devices that appear during initial enumeration are gathered into the first
+  // result returned by GetDevices() and prevent device add/remove notifications
+  // from being sent.
+  if (!enumeration_ready())
+    ++first_enumeration_countdown_;
+
+  scoped_refptr<UsbDeviceWin> device(new UsbDeviceWin(
+      device_path, hub_path, port_number, blocking_task_runner()));
+  devices_by_path_[device->device_path()] = device;
+
+  // TODO(reillyg): Read device descriptors.
+  DeviceReady(device, true);
+}
+
+void UsbServiceWin::DeviceReady(scoped_refptr<UsbDeviceWin> device,
+                                bool success) {
+  DCHECK(CalledOnValidThread());
+
+  bool enumeration_became_ready = false;
+  if (!enumeration_ready()) {
+    DCHECK_GT(first_enumeration_countdown_, 0u);
+    first_enumeration_countdown_--;
+    if (enumeration_ready())
+      enumeration_became_ready = true;
+  }
+
+  // If |device| was disconnected while descriptors were being read then it
+  // will have been removed from |devices_by_path_|.
+  auto it = devices_by_path_.find(device->device_path());
+  if (it == devices_by_path_.end()) {
+    success = false;
+  } else if (success) {
+    DCHECK(!base::ContainsKey(devices(), device->guid()));
+    devices()[device->guid()] = device;
+
+    USB_LOG(USER) << "USB device added: path=" << device->device_path()
+                  << " vendor=" << device->vendor_id() << " \""
+                  << device->manufacturer_string()
+                  << "\", product=" << device->product_id() << " \""
+                  << device->product_string() << "\", serial=\""
+                  << device->serial_number() << "\", guid=" << device->guid();
+  } else {
+    devices_by_path_.erase(it);
+  }
+
+  if (enumeration_became_ready) {
+    std::vector<scoped_refptr<UsbDevice>> result;
+    result.reserve(devices().size());
+    for (const auto& map_entry : devices())
+      result.push_back(map_entry.second);
+    for (const auto& callback : enumeration_callbacks_)
+      callback.Run(result);
+    enumeration_callbacks_.clear();
+  } else if (success && enumeration_ready()) {
+    NotifyDeviceAdded(device);
+  }
+}
+
 }  // namespace device
diff --git a/device/usb/usb_service_win.h b/device/usb/usb_service_win.h
index a6feb81..a915577 100644
--- a/device/usb/usb_service_win.h
+++ b/device/usb/usb_service_win.h
@@ -4,17 +4,63 @@
 
 #include "device/usb/usb_service.h"
 
+#include <list>
+#include <unordered_map>
+
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
+#include "device/base/device_monitor_win.h"
+#include "device/usb/usb_device_win.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
 
 namespace device {
 
-class UsbServiceWin : public UsbService {
+class UsbServiceWin : public DeviceMonitorWin::Observer, public UsbService {
  public:
   explicit UsbServiceWin(
       scoped_refptr<base::SequencedTaskRunner> blocking_task_runner);
   ~UsbServiceWin() override;
 
  private:
+  class BlockingThreadHelper;
+
+  // device::UsbService implementation
+  void GetDevices(const GetDevicesCallback& callback) override;
+
+  // device::DeviceMonitorWin::Observer implementation
+  void OnDeviceAdded(const GUID& class_guid,
+                     const std::string& device_path) override;
+  void OnDeviceRemoved(const GUID& class_guid,
+                       const std::string& device_path) override;
+
+  // Methods called by BlockingThreadHelper
+  void HelperStarted();
+  void CreateDeviceObject(const std::string& device_path,
+                          const std::string& hub_path,
+                          int port_number);
+
+  void DeviceReady(scoped_refptr<UsbDeviceWin> device, bool success);
+
+  bool enumeration_ready() {
+    return helper_started_ && first_enumeration_countdown_ == 0;
+  }
+
+  // Enumeration callbacks are queued until an enumeration completes.
+  bool helper_started_ = false;
+  uint32_t first_enumeration_countdown_ = 0;
+  std::list<GetDevicesCallback> enumeration_callbacks_;
+
+  BlockingThreadHelper* helper_;
+  std::unordered_map<std::string, scoped_refptr<UsbDeviceWin>> devices_by_path_;
+
+  ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_;
+
+  base::WeakPtrFactory<UsbServiceWin> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(UsbServiceWin);
 };
 
diff --git a/extensions/browser/info_map.cc b/extensions/browser/info_map.cc
index c97832c..7efb7365 100644
--- a/extensions/browser/info_map.cc
+++ b/extensions/browser/info_map.cc
@@ -49,6 +49,16 @@
 InfoMap::InfoMap() {
 }
 
+const ExtensionSet& InfoMap::extensions() const {
+  CheckOnValidThread();
+  return extensions_;
+}
+
+const ExtensionSet& InfoMap::disabled_extensions() const {
+  CheckOnValidThread();
+  return disabled_extensions_;
+}
+
 void InfoMap::AddExtension(const Extension* extension,
                            base::Time install_time,
                            bool incognito_enabled,
diff --git a/extensions/browser/info_map.h b/extensions/browser/info_map.h
index 2deafec..c895007 100644
--- a/extensions/browser/info_map.h
+++ b/extensions/browser/info_map.h
@@ -30,10 +30,8 @@
  public:
   InfoMap();
 
-  const ExtensionSet& extensions() const { return extensions_; }
-  const ExtensionSet& disabled_extensions() const {
-    return disabled_extensions_;
-  }
+  const ExtensionSet& extensions() const;
+  const ExtensionSet& disabled_extensions() const;
 
   // Information about which extensions are assigned to which render processes.
   const ProcessMap& process_map() const { return process_map_; }
diff --git a/extensions/common/file_util.cc b/extensions/common/file_util.cc
index 96982d06..2e986c430 100644
--- a/extensions/common/file_util.cc
+++ b/extensions/common/file_util.cc
@@ -38,7 +38,6 @@
 #include "extensions/common/manifest_handler.h"
 #include "extensions/common/manifest_handlers/default_locale_handler.h"
 #include "extensions/common/manifest_handlers/icons_handler.h"
-#include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "grit/extensions_strings.h"
 #include "net/base/escape.h"
 #include "net/base/filename_util.h"
@@ -514,77 +513,40 @@
     const base::FilePath& extension_path,
     const std::string& extension_id,
     const std::string& default_locale) {
+  return LoadMessageBundleSubstitutionMapFromPaths(
+      {extension_path}, extension_id, default_locale);
+}
+
+MessageBundle::SubstitutionMap* LoadNonLocalizedMessageBundleSubstitutionMap(
+    const std::string& extension_id) {
   MessageBundle::SubstitutionMap* return_value =
       new MessageBundle::SubstitutionMap();
-  if (!default_locale.empty()) {
-    // Touch disk only if extension is localized.
-    std::string error;
-    std::unique_ptr<MessageBundle> bundle(
-        LoadMessageBundle(extension_path, default_locale, &error));
 
-    if (bundle.get())
-      *return_value = *bundle->dictionary();
-  }
-
-  // Add @@extension_id reserved message here, so it's available to
-  // non-localized extensions too.
+  // Add @@extension_id reserved message here.
   return_value->insert(
       std::make_pair(MessageBundle::kExtensionIdKey, extension_id));
 
   return return_value;
 }
 
-MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapWithImports(
+MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths(
+    const std::vector<base::FilePath>& paths,
     const std::string& extension_id,
-    const ExtensionSet& extension_set) {
-  const Extension* extension = extension_set.GetByID(extension_id);
+    const std::string& default_locale) {
   MessageBundle::SubstitutionMap* return_value =
-      new MessageBundle::SubstitutionMap();
-
-  // Add @@extension_id reserved message here, so it's available to
-  // non-localized extensions too.
-  return_value->insert(
-      std::make_pair(MessageBundle::kExtensionIdKey, extension_id));
-
-  base::FilePath extension_path;
-  std::string default_locale;
-  if (!extension) {
-    NOTREACHED() << "Missing extension " << extension_id;
-    return return_value;
-  }
+      LoadNonLocalizedMessageBundleSubstitutionMap(extension_id);
 
   // Touch disk only if extension is localized.
-  default_locale = LocaleInfo::GetDefaultLocale(extension);
-  if (default_locale.empty()) {
+  if (default_locale.empty())
     return return_value;
-  }
 
   std::string error;
-  std::unique_ptr<MessageBundle> bundle(
-      LoadMessageBundle(extension->path(), default_locale, &error));
+  for (const base::FilePath& path : paths) {
+    std::unique_ptr<MessageBundle> bundle(
+        LoadMessageBundle(path, default_locale, &error));
 
-  if (bundle.get()) {
-    for (auto iter : *bundle->dictionary()) {
-      return_value->insert(std::make_pair(iter.first, iter.second));
-    }
-  }
-
-  auto imports = extensions::SharedModuleInfo::GetImports(extension);
-  // Iterate through the imports in reverse.  This will allow later imported
-  // modules to override earlier imported modules, as the list order is
-  // maintained from the definition in manifest.json of the imports.
-  for (auto it = imports.rbegin(); it != imports.rend(); ++it) {
-    const extensions::Extension* imported_extension =
-        extension_set.GetByID(it->extension_id);
-    if (!imported_extension) {
-      NOTREACHED() << "Missing shared module " << it->extension_id;
-      continue;
-    }
-    std::unique_ptr<MessageBundle> imported_bundle(
-        LoadMessageBundle(imported_extension->path(), default_locale, &error));
-
-    if (imported_bundle.get()) {
-      for (auto iter : *imported_bundle->dictionary()) {
+    if (bundle) {
+      for (const auto& iter : *bundle->dictionary()) {
         // |insert| only adds new entries, and does not replace entries in
         // the main extension or previously processed imports.
         return_value->insert(std::make_pair(iter.first, iter.second));
diff --git a/extensions/common/file_util.h b/extensions/common/file_util.h
index bc080edb..6678163 100644
--- a/extensions/common/file_util.h
+++ b/extensions/common/file_util.h
@@ -23,7 +23,6 @@
 
 namespace extensions {
 class Extension;
-class ExtensionSet;
 struct InstallWarning;
 
 // Utilities for manipulating the on-disk storage of extensions.
@@ -135,12 +134,18 @@
     const std::string& extension_id,
     const std::string& default_locale);
 
-// Loads the extension message bundle substitution map, including messages from
-// Shared Modules that the given extension imports. Contains at least the
-// extension_id item.
-MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapWithImports(
+// Loads the extension message bundle substitution map for a non-localized
+// extension. Contains only the extension_id item.
+// This doesn't require hitting disk, so it's safe to call on any thread.
+MessageBundle::SubstitutionMap* LoadNonLocalizedMessageBundleSubstitutionMap(
+    const std::string& extension_id);
+
+// Loads the extension message bundle substitution map from the specified paths.
+// Contains at least the extension_id item.
+MessageBundle::SubstitutionMap* LoadMessageBundleSubstitutionMapFromPaths(
+    const std::vector<base::FilePath>& paths,
     const std::string& extension_id,
-    const ExtensionSet& extension_set);
+    const std::string& default_locale);
 
 // Helper functions for getting paths for files used in content verification.
 base::FilePath GetVerifiedContentsPath(const base::FilePath& extension_path);
diff --git a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc
index bec7d1c..77bc51f 100644
--- a/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc
+++ b/extensions/renderer/guest_view/guest_view_internal_custom_bindings.cc
@@ -15,6 +15,7 @@
 #include "components/guest_view/renderer/iframe_guest_view_request.h"
 #include "content/public/child/v8_value_converter.h"
 #include "content/public/renderer/render_frame.h"
+#include "content/public/renderer/render_frame_observer.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "extensions/common/extension.h"
@@ -57,6 +58,18 @@
   return content::RenderFrame::FromWebFrame(frame);
 }
 
+class RenderFrameStatus : public content::RenderFrameObserver {
+ public:
+  explicit RenderFrameStatus(content::RenderFrame* render_frame)
+      : content::RenderFrameObserver(render_frame) {}
+  ~RenderFrameStatus() final {}
+
+  bool is_ok() { return render_frame() != nullptr; }
+
+  // RenderFrameObserver implementation.
+  void OnDestruct() final {}
+};
+
 }  // namespace
 
 GuestViewInternalCustomBindings::GuestViewInternalCustomBindings(
@@ -144,6 +157,8 @@
   // is invalid?
   if (!guest_view_container)
     return;
+  // Retain a weak pointer so we can easily test if the container goes away.
+  auto weak_ptr = guest_view_container->GetWeakPtr();
 
   int guest_instance_id = args[1]->Int32Value();
 
@@ -155,6 +170,12 @@
     params = base::DictionaryValue::From(std::move(params_as_value));
     CHECK(params);
   }
+  // We should be careful that some malicious JS in the GuestView's embedder
+  // hasn't destroyed |guest_view_container| during the enumeration of the
+  // properties of the guest's object during extraction of |params| above
+  // (see https://crbug.com/683523).
+  if (!weak_ptr)
+    return;
 
   // Add flag to |params| to indicate that the element size is specified in
   // logical units.
@@ -221,6 +242,12 @@
   int element_instance_id = args[0]->Int32Value();
   int guest_instance_id = args[1]->Int32Value();
 
+  // Get the WebLocalFrame before (possibly) executing any user-space JS while
+  // getting the |params|. We track the status of the RenderFrame via an
+  // observer in case it is deleted during user code execution.
+  content::RenderFrame* render_frame = GetRenderFrame(args[3]);
+  RenderFrameStatus render_frame_status(render_frame);
+
   std::unique_ptr<base::DictionaryValue> params;
   {
     std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create());
@@ -229,19 +256,19 @@
     params = base::DictionaryValue::From(std::move(params_as_value));
     CHECK(params);
   }
+  if (!render_frame_status.is_ok())
+    return;
 
-  // Add flag to |params| to indicate that the element size is specified in
-  // logical units.
-  params->SetBoolean(guest_view::kElementSizeIsLogical, true);
-
-  content::RenderFrame* render_frame = GetRenderFrame(args[3]);
   blink::WebLocalFrame* frame = render_frame->GetWebFrame();
-
   // Parent must exist.
   blink::WebFrame* parent_frame = frame->parent();
   DCHECK(parent_frame);
   DCHECK(parent_frame->isWebLocalFrame());
 
+  // Add flag to |params| to indicate that the element size is specified in
+  // logical units.
+  params->SetBoolean(guest_view::kElementSizeIsLogical, true);
+
   content::RenderFrame* embedder_parent_frame =
       content::RenderFrame::FromWebFrame(parent_frame);
 
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index 6a71d9c..61bfe2a1 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -102,6 +102,7 @@
     "//ios/net",
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/native_app_launcher",
+    "//ios/shared/chrome/browser/tabs",
     "//ios/web",
     "//net",
     "//ui/base",
@@ -127,6 +128,7 @@
     "//base",
     "//ios/chrome/browser",
     "//ios/chrome/browser/browser_state",
+    "//ios/shared/chrome/browser/tabs",
     "//ios/web",
   ]
   libs = [ "Foundation.framework" ]
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm
index 81d4528f2..c9799c0 100644
--- a/ios/chrome/browser/tabs/tab_model.mm
+++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/tabs/tab_model.h"
 
+#include <cstdint>
 #include <utility>
 #include <vector>
 
@@ -28,12 +29,16 @@
 #import "ios/chrome/browser/sessions/session_window.h"
 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
 #include "ios/chrome/browser/tab_parenting_global_observer.h"
+#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model_list.h"
 #import "ios/chrome/browser/tabs/tab_model_observers.h"
 #import "ios/chrome/browser/tabs/tab_model_order_controller.h"
 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
 #import "ios/chrome/browser/xcallback_parameters.h"
+#import "ios/shared/chrome/browser/tabs/web_state_list.h"
+#import "ios/shared/chrome/browser/tabs/web_state_list_fast_enumeration_helper.h"
+#import "ios/shared/chrome/browser/tabs/web_state_list_observer.h"
 #import "ios/web/navigation/crw_session_certificate_policy_manager.h"
 #import "ios/web/navigation/crw_session_controller.h"
 #include "ios/web/public/browser_state.h"
@@ -79,38 +84,62 @@
       updateCertificatePolicyCache:policy_cache];
 }
 
-// Populates the certificate policy cache based on the WebStates of |tab_model|.
+// Populates the certificate policy cache based on the WebStates of
+// |web_state_list|.
 void RestoreCertificatePolicyCacheFromModel(
     const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
-    TabModel* tab_model) {
+    WebStateList* web_state_list) {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
-  for (Tab* tab in tab_model)
-    UpdateCertificatePolicyCacheFromWebState(policy_cache, tab.webState);
+  for (int index = 0; index < web_state_list->count(); ++index) {
+    UpdateCertificatePolicyCacheFromWebState(
+        policy_cache, web_state_list->GetWebStateAt(index));
+  }
 }
 
 // Scrubs the certificate policy cache of all certificates policies except
-// those for the current entries in |tab_model|.
+// those for the current entries in |web_state_list|.
 void CleanCertificatePolicyCache(
     base::CancelableTaskTracker* task_tracker,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     const scoped_refptr<web::CertificatePolicyCache>& policy_cache,
-    TabModel* tab_model) {
-  DCHECK(tab_model);
+    WebStateList* web_state_list) {
   DCHECK(policy_cache);
+  DCHECK(web_state_list);
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
   task_tracker->PostTaskAndReply(
       task_runner.get(), FROM_HERE,
       base::Bind(&web::CertificatePolicyCache::ClearCertificatePolicies,
                  policy_cache),
       base::Bind(&RestoreCertificatePolicyCacheFromModel, policy_cache,
-                 base::Unretained(tab_model)));
+                 base::Unretained(web_state_list)));
 }
 
 }  // anonymous namespace
 
+@interface TabModelWebStateProxyFactory : NSObject<WebStateProxyFactory>
+@end
+
+@implementation TabModelWebStateProxyFactory
+
+- (id)proxyForWebState:(web::WebState*)webState {
+  return LegacyTabHelper::GetTabForWebState(webState);
+}
+
+@end
+
 @interface TabModel ()<TabUsageRecorderDelegate> {
-  // Array of |Tab| objects.
-  base::scoped_nsobject<NSMutableArray> _tabs;
+  // Underlying shared model implementation.
+  WebStateList _webStateList;
+
+  // Helper providing NSFastEnumeration implementation over the WebStateList.
+  base::scoped_nsobject<WebStateListFastEnumerationHelper>
+      _fastEnumerationHelper;
+
+  // Used to keep the Tabs alive while the corresponding WebStates are stored
+  // in the WebStateList (as Tabs currently own their WebState). Remove once
+  // WebState owns the associated Tab.
+  base::scoped_nsobject<NSMutableSet<Tab*>> _tabRetainer;
+
   // Maintains policy for where new tabs go and the selection when a tab
   // is removed.
   base::scoped_nsobject<TabModelOrderController> _orderController;
@@ -214,7 +243,7 @@
 }
 
 - (void)setCurrentTab:(Tab*)newTab {
-  DCHECK([_tabs containsObject:newTab]);
+  DCHECK_NE([self indexOfTab:newTab], static_cast<NSUInteger>(NSNotFound));
   if (_currentTab != newTab) {
     base::RecordAction(base::UserMetricsAction("MobileTabSwitched"));
     [self updateSnapshotCache:newTab];
@@ -238,19 +267,25 @@
 }
 
 - (BOOL)isEmpty {
-  return self.count == 0;
+  return _webStateList.empty();
 }
 
 - (NSUInteger)count {
-  return [_tabs count];
+  DCHECK_GE(_webStateList.count(), 0);
+  return static_cast<NSUInteger>(_webStateList.count());
 }
 
 - (instancetype)initWithSessionWindow:(SessionWindowIOS*)window
                        sessionService:(SessionServiceIOS*)service
                          browserState:(ios::ChromeBrowserState*)browserState {
   if ((self = [super init])) {
+    _tabRetainer.reset([[NSMutableSet alloc] init]);
     _observers.reset([[TabModelObservers observers] retain]);
 
+    _fastEnumerationHelper.reset([[WebStateListFastEnumerationHelper alloc]
+        initWithWebStateList:&_webStateList
+                proxyFactory:[[TabModelWebStateProxyFactory alloc] init]]);
+
     _browserState = browserState;
     DCHECK(_browserState);
 
@@ -267,7 +302,6 @@
     }
     _syncedWindowDelegate.reset(new TabModelSyncedWindowDelegate(self));
 
-    _tabs.reset([[NSMutableArray alloc] init]);
     if (window) {
       DCHECK([_observers empty]);
       // Restore the session and reset the session metrics (as the event have
@@ -316,7 +350,7 @@
 - (void)saveSessionImmediately:(BOOL)immediately {
   // Do nothing if there are tabs in the model but no selected tab. This is
   // a transitional state.
-  if ((!_currentTab && [_tabs count]) || !_browserState)
+  if ((!_currentTab && _webStateList.count()) || !_browserState)
     return;
   [_sessionService saveWindow:self.windowForSavingSession
               forBrowserState:_browserState
@@ -324,17 +358,24 @@
 }
 
 - (Tab*)tabAtIndex:(NSUInteger)index {
-  return [_tabs objectAtIndex:index];
+  DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
+  return LegacyTabHelper::GetTabForWebState(
+      _webStateList.GetWebStateAt(static_cast<int>(index)));
 }
 
 - (NSUInteger)indexOfTab:(Tab*)tab {
-  return [_tabs indexOfObject:tab];
+  int index = _webStateList.GetIndexOfWebState(tab.webState);
+  if (index == WebStateList::kInvalidIndex)
+    return NSNotFound;
+
+  DCHECK_GE(index, 0);
+  return static_cast<NSUInteger>(index);
 }
 
 - (Tab*)tabWithWindowName:(NSString*)windowName {
   if (!windowName)
     return nil;
-  for (Tab* tab in _tabs.get()) {
+  for (Tab* tab in self) {
     if ([windowName isEqualToString:tab.windowName]) {
       return tab;
     }
@@ -353,8 +394,8 @@
   if (startIndex == NSNotFound)
     return nil;
   NSString* parentID = tab.tabId;
-  for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) {
-    Tab* current = [_tabs objectAtIndex:i];
+  for (NSUInteger i = startIndex + 1; i < self.count; ++i) {
+    Tab* current = [self tabAtIndex:i];
     DCHECK([current navigationManager]);
     CRWSessionController* sessionController =
         [current navigationManager]->GetSessionController();
@@ -379,8 +420,8 @@
   // tabs whose opener's id and opener's navigation index match. The navigation
   // index is used in addition to the session id to detect navigations changes
   // within the same session.
-  for (NSUInteger i = startIndex + 1; i < [_tabs count]; ++i) {
-    Tab* tabToCheck = [_tabs objectAtIndex:i];
+  for (NSUInteger i = startIndex + 1; i < self.count; ++i) {
+    Tab* tabToCheck = [self tabAtIndex:i];
     DCHECK([tabToCheck navigationManager]);
     CRWSessionController* sessionController =
         [tabToCheck navigationManager]->GetSessionController();
@@ -400,7 +441,7 @@
   NSString* openerId = [tab navigationManager]->GetSessionController().openerId;
   if (!openerId.length)  // Short-circuit if opener is empty.
     return nil;
-  for (Tab* iteratedTab in _tabs.get()) {
+  for (Tab* iteratedTab in self) {
     if ([iteratedTab.tabId isEqualToString:openerId])
       return iteratedTab;
   }
@@ -493,10 +534,12 @@
 
 - (void)insertTab:(Tab*)tab atIndex:(NSUInteger)index {
   DCHECK(tab);
-  DCHECK(index <= [_tabs count]);
+  DCHECK(![_tabRetainer containsObject:tab]);
+  DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
   [tab fetchFavicon];
-  [_tabs insertObject:tab atIndex:index];
 
+  [_tabRetainer addObject:tab];
+  _webStateList.InsertWebState(static_cast<int>(index), tab.webState);
   TabParentingGlobalObserver::GetInstance()->OnTabParented(tab.webState);
   [_observers tabModel:self didInsertTab:tab atIndex:index inForeground:NO];
   [_observers tabModelDidChangeTabCount:self];
@@ -507,36 +550,41 @@
   // state properly. If it does eventually become active, another save will
   // be triggered to properly capture the end result.
   [self saveSessionImmediately:NO];
+
   ++_newTabCount;
 }
 
 - (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex {
-  NSUInteger fromIndex = [self indexOfTab:tab];
-  DCHECK_NE(NSNotFound, static_cast<NSInteger>(fromIndex));
-  DCHECK_LT(toIndex, self.count);
-  if (fromIndex == NSNotFound || toIndex >= self.count ||
-      fromIndex == toIndex) {
+  if ([self tabAtIndex:toIndex] == tab)
     return;
-  }
 
-  base::scoped_nsobject<Tab> tabSaver([tab retain]);
-  [_tabs removeObject:tab];
-  [_tabs insertObject:tab atIndex:toIndex];
-
+  DCHECK([_tabRetainer containsObject:tab]);
+  DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX));
+  int fromIndex = _webStateList.GetIndexOfWebState(tab.webState);
+  _webStateList.MoveWebStateAt(fromIndex, static_cast<int>(toIndex));
   [_observers tabModel:self didMoveTab:tab fromIndex:fromIndex toIndex:toIndex];
 }
 
 - (void)replaceTab:(Tab*)oldTab withTab:(Tab*)newTab {
-  NSUInteger index = [self indexOfTab:oldTab];
-  DCHECK_NE(NSNotFound, static_cast<NSInteger>(index));
+  DCHECK([_tabRetainer containsObject:oldTab]);
+  DCHECK(![_tabRetainer containsObject:newTab]);
+
+  int index = _webStateList.GetIndexOfWebState(oldTab.webState);
+  DCHECK_NE(index, WebStateList::kInvalidIndex);
+  DCHECK_GE(index, 0);
 
   base::scoped_nsobject<Tab> tabSaver([oldTab retain]);
   [newTab fetchFavicon];
-  [_tabs replaceObjectAtIndex:index withObject:newTab];
+  [_tabRetainer removeObject:oldTab];
+  [_tabRetainer addObject:newTab];
   [newTab setParentTabModel:self];
 
+  _webStateList.ReplaceWebStateAt(index, newTab.webState);
   TabParentingGlobalObserver::GetInstance()->OnTabParented(newTab.webState);
-  [_observers tabModel:self didReplaceTab:oldTab withTab:newTab atIndex:index];
+  [_observers tabModel:self
+         didReplaceTab:oldTab
+               withTab:newTab
+               atIndex:static_cast<NSUInteger>(index)];
 
   if (self.currentTab == oldTab)
     [self changeSelectedTabFrom:nil to:newTab persistState:NO];
@@ -550,8 +598,8 @@
 }
 
 - (void)closeTabAtIndex:(NSUInteger)index {
-  DCHECK(index < [_tabs count]);
-  [self closeTab:[_tabs objectAtIndex:index]];
+  DCHECK(index < self.count);
+  [self closeTab:[self tabAtIndex:index]];
 }
 
 - (void)closeTab:(Tab*)tab {
@@ -571,7 +619,7 @@
 }
 
 - (void)haltAllTabs {
-  for (Tab* tab in _tabs.get()) {
+  for (Tab* tab in self) {
     [tab terminateNetworkActivity];
   }
 }
@@ -608,7 +656,7 @@
 }
 
 - (void)resetAllWebViews {
-  for (Tab* tab in _tabs.get()) {
+  for (Tab* tab in self) {
     [tab.webController reinitializeWebViewAndReload:(tab == _currentTab)];
   }
 }
@@ -617,7 +665,7 @@
   if (webUsageEnabled_ == webUsageEnabled)
     return;
   webUsageEnabled_ = webUsageEnabled;
-  for (Tab* tab in _tabs.get()) {
+  for (Tab* tab in self) {
     tab.webUsageEnabled = webUsageEnabled;
   }
 }
@@ -632,7 +680,7 @@
   if (!_browserState)
     return referencedFiles;
   // Check the currently open tabs for external files.
-  for (Tab* tab in _tabs.get()) {
+  for (Tab* tab in self) {
     if (UrlIsExternalFileReference(tab.url)) {
       NSString* fileName = base::SysUTF8ToNSString(tab.url.ExtractFileName());
       [referencedFiles addObject:fileName];
@@ -669,9 +717,12 @@
 // Called when a tab is closing, but before its CRWWebController is destroyed.
 // Equivalent to DetachTabContentsAt() in Chrome's TabStripModel.
 - (void)didCloseTab:(Tab*)closedTab {
-  NSUInteger closedTabIndex = [_tabs indexOfObject:closedTab];
   DCHECK(closedTab);
-  DCHECK(closedTabIndex != NSNotFound);
+  DCHECK([_tabRetainer containsObject:closedTab]);
+  int closedTabIndex = _webStateList.GetIndexOfWebState(closedTab.webState);
+  DCHECK_NE(closedTabIndex, WebStateList::kInvalidIndex);
+  DCHECK_GE(closedTabIndex, 0);
+
   // Let the sessions::TabRestoreService know about that new tab.
   sessions::TabRestoreService* restoreService =
       _browserState
@@ -683,13 +734,13 @@
   if (restoreService && (![self isNTPTab:closedTab] || itemCount > 1)) {
     restoreService->CreateHistoricalTab(
         sessions::IOSLiveTab::GetForWebState(closedTab.webState),
-        static_cast<int>(closedTabIndex));
+        closedTabIndex);
   }
   // This needs to be called before the tab is removed from the list.
   Tab* newSelection =
       [_orderController determineNewSelectedTabFromRemovedTab:closedTab];
+
   base::scoped_nsobject<Tab> kungFuDeathGrip([closedTab retain]);
-  [_tabs removeObject:closedTab];
 
   // If closing the current tab, clear |_currentTab| before sending any
   // notification. This avoids various parts of the code getting confused
@@ -698,7 +749,13 @@
   if (closedTab == _currentTab)
     _currentTab.reset(nil);
 
-  [_observers tabModel:self didRemoveTab:closedTab atIndex:closedTabIndex];
+  DCHECK([_tabRetainer containsObject:closedTab]);
+  [_tabRetainer removeObject:closedTab];
+
+  _webStateList.DetachWebStateAt(closedTabIndex);
+  [_observers tabModel:self
+          didRemoveTab:closedTab
+               atIndex:static_cast<NSUInteger>(closedTabIndex)];
   [_observers tabModelDidChangeTabCount:self];
 
   // Current tab has closed, update the selected tab and swap in its
@@ -745,15 +802,16 @@
 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
                                   objects:(id*)objects
                                     count:(NSUInteger)count {
-  return [_tabs countByEnumeratingWithState:state objects:objects count:count];
+  return [_fastEnumerationHelper countByEnumeratingWithState:state
+                                                     objects:objects
+                                                       count:count];
 }
 
 #pragma mark - TabUsageRecorderDelegate
 
 - (NSUInteger)liveTabsCount {
   NSUInteger count = 0;
-  NSArray* tabs = _tabs.get();
-  for (Tab* tab in tabs) {
+  for (Tab* tab in self) {
     if ([tab.webController isViewAlive])
       count++;
   }
@@ -924,7 +982,9 @@
   if (!sessions.count)
     return NO;
 
-  size_t oldCount = [_tabs count];
+  int oldCount = _webStateList.count();
+  DCHECK_GE(oldCount, 0);
+
   web::WebState::CreateParams params(_browserState);
   scoped_refptr<web::CertificatePolicyCache> policyCache =
       web::BrowserState::GetCertificatePolicyCache(_browserState);
@@ -934,19 +994,19 @@
         web::WebState::Create(params, session);
     DCHECK_EQ(webState->GetBrowserState(), _browserState);
     Tab* tab =
-        [self insertTabWithWebState:std::move(webState) atIndex:[_tabs count]];
+        [self insertTabWithWebState:std::move(webState) atIndex:self.count];
     tab.webController.usePlaceholderOverlay = YES;
 
     // Restore the CertificatePolicyCache (note that webState is invalid after
     // passing it via move semantic to -insertTabWithWebState:atIndex:).
     UpdateCertificatePolicyCacheFromWebState(policyCache, tab.webState);
   }
-  DCHECK_GT([_tabs count], oldCount);
+  DCHECK_GT(_webStateList.count(), oldCount);
 
   // Update the selected tab if there was a selected Tab in the saved session.
   if (window.selectedIndex != NSNotFound) {
     NSUInteger selectedIndex = window.selectedIndex + oldCount;
-    DCHECK_LT(selectedIndex, [_tabs count]);
+    DCHECK_LT(selectedIndex, self.count);
     DCHECK([self tabAtIndex:selectedIndex]);
     [self changeSelectedTabFrom:_currentTab
                              to:[self tabAtIndex:selectedIndex]
@@ -956,7 +1016,7 @@
   // If there was only one tab and it was the new tab page, clobber it.
   BOOL closedNTPTab = NO;
   if (oldCount == 1) {
-    Tab* tab = [_tabs objectAtIndex:0];
+    Tab* tab = [self tabAtIndex:0];
     if (tab.url == GURL(kChromeUINewTabURL)) {
       [self closeTab:tab];
       closedNTPTab = YES;
@@ -964,10 +1024,13 @@
     }
   }
   if (_tabUsageRecorder) {
-    _tabUsageRecorder->InitialRestoredTabs(
-        _currentTab,
-        [_tabs
-            subarrayWithRange:NSMakeRange(oldCount, [_tabs count] - oldCount)]);
+    NSMutableArray<Tab*>* restoredTabs =
+        [NSMutableArray arrayWithCapacity:_webStateList.count() - oldCount];
+    for (int index = oldCount; index < _webStateList.count(); ++index) {
+      web::WebState* webState = _webStateList.GetWebStateAt(index);
+      [restoredTabs addObject:LegacyTabHelper::GetTabForWebState(webState)];
+    }
+    _tabUsageRecorder->InitialRestoredTabs(_currentTab, restoredTabs);
   }
   return closedNTPTab;
 }
@@ -992,7 +1055,8 @@
   CleanCertificatePolicyCache(
       &_clearPoliciesTaskTracker,
       web::WebThread::GetTaskRunnerForThread(web::WebThread::IO),
-      web::BrowserState::GetCertificatePolicyCache(_browserState), self);
+      web::BrowserState::GetCertificatePolicyCache(_browserState),
+      &_webStateList);
 
   if (_tabUsageRecorder)
     _tabUsageRecorder->AppDidEnterBackground();
diff --git a/ios/chrome/browser/tabs/tab_model_order_controller_unittest.mm b/ios/chrome/browser/tabs/tab_model_order_controller_unittest.mm
index bde32a3..052ef9c 100644
--- a/ios/chrome/browser/tabs/tab_model_order_controller_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_model_order_controller_unittest.mm
@@ -86,10 +86,10 @@
   IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_;
   base::scoped_nsobject<SessionWindowIOS> sessionWindow_;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
+  base::mac::ScopedNSAutoreleasePool pool_;
   base::scoped_nsobject<Tab> dummy_tab_;
   base::scoped_nsobject<TabModelOrderController> orderController_;
   base::scoped_nsobject<TabModel> tabModel_;
-  base::mac::ScopedNSAutoreleasePool pool_;
 };
 
 // Verifies that tabs added in the background (e.g. from context menu -> Open in
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.png
index 69c1f5a..ef386f07 100644
--- a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.png
+++ b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe.png
Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@2x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@2x.png
index b8d99dd..11a90f5a 100644
--- a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@2x.png
+++ b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@3x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@3x.png
index 601c28c..e910790 100644
--- a/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@3x.png
+++ b/ios/chrome/browser/ui/reading_list/resources/reading_list_side_swipe@3x.png
Binary files differ
diff --git a/ios/chrome/share_extension/share_extension_view.mm b/ios/chrome/share_extension/share_extension_view.mm
index a072574..3a0e146 100644
--- a/ios/chrome/share_extension/share_extension_view.mm
+++ b/ios/chrome/share_extension/share_extension_view.mm
@@ -309,10 +309,13 @@
   [navigationBar setTranslucent:YES];
   [navigationBar setTranslatesAutoresizingMaskIntoConstraints:NO];
 
+  UIButton* systemButton = [UIButton buttonWithType:UIButtonTypeSystem];
+  UIColor* systemColor = [systemButton titleColorForState:UIControlStateNormal];
   UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc]
       initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
                            target:self
                            action:@selector(cancelPressed:)];
+  [cancelButton setTintColor:systemColor];
 
   NSString* appName =
       [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 322051c..5a84a02 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -418,8 +418,6 @@
     "public/test/http_server_util.mm",
     "public/test/js_test_util.h",
     "public/test/js_test_util.mm",
-    "public/test/mock_image_data_fetcher.h",
-    "public/test/mock_image_data_fetcher.mm",
     "public/test/native_controller_test_util.h",
     "public/test/native_controller_test_util.mm",
     "public/test/navigation_test_util.h",
diff --git a/ios/web/public/image_fetcher/BUILD.gn b/ios/web/public/image_fetcher/BUILD.gn
index 7c93ce1d..3a1cf83 100644
--- a/ios/web/public/image_fetcher/BUILD.gn
+++ b/ios/web/public/image_fetcher/BUILD.gn
@@ -5,14 +5,11 @@
 source_set("image_fetcher") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
-    "image_data_fetcher.h",
-    "image_data_fetcher.mm",
     "webp_decoder.h",
     "webp_decoder.mm",
   ]
   deps = [
     "//base",
-    "//net",
     "//third_party/libwebp:libwebp_dec",
   ]
 }
@@ -21,15 +18,12 @@
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
-    "image_data_fetcher_unittest.mm",
     "webp_decoder_unittest.mm",
   ]
   deps = [
     ":image_fetcher",
     ":webp_transcode_unit_tests_bundle_data",
     "//base",
-    "//net",
-    "//net:test_support",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/ios/web/public/image_fetcher/image_data_fetcher.h b/ios/web/public/image_fetcher/image_data_fetcher.h
deleted file mode 100644
index 797a2d3e9..0000000
--- a/ios/web/public/image_fetcher/image_data_fetcher.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2011 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 IOS_WEB_PUBLIC_IMAGE_FETCHER_IMAGE_DATA_FETCHER_H_
-#define IOS_WEB_PUBLIC_IMAGE_FETCHER_IMAGE_DATA_FETCHER_H_
-
-#include <map>
-
-#include "base/mac/scoped_block.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_request.h"
-
-class GURL;
-@class NSData;
-
-namespace base {
-class TaskRunner;
-}
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-namespace web {
-
-// Callback that informs of the download of an image encoded in |data|,
-// downloaded from |url|, and with the http status |http_response_code|. If the
-// url is a data URL, |http_response_code| is always 200.
-using ImageFetchedCallback = void (^)(const GURL& url,
-                                      int http_response_code,
-                                      NSData* data);
-
-// Utility class that will retrieve an image from an URL. The image is returned
-// as NSData which can be used with +[UIImage imageWithData:]. This class
-// usually returns the raw bytes retrieved from the network without any
-// processing, with the exception of WebP encoded images. Those are decoded and
-// then reencoded in a format suitable for UIImage.
-// An instance of this class can download a number of images at the same time.
-class ImageDataFetcher : public net::URLFetcherDelegate {
- public:
-  // The TaskRunner is used to eventually decode the image.
-  explicit ImageDataFetcher(const scoped_refptr<base::TaskRunner>& task_runner);
-  ~ImageDataFetcher() override;
-
-  // Start downloading the image at the given |url|. The |callback| will be
-  // called with the downloaded image, or nil if any error happened. The
-  // |referrer| and |referrer_policy| will be passed on to the underlying
-  // URLFetcher.
-  // This method assumes the request context getter has been set.
-  // (virtual for testing)
-  virtual void StartDownload(const GURL& url,
-                             ImageFetchedCallback callback,
-                             const std::string& referrer,
-                             net::URLRequest::ReferrerPolicy referrer_policy);
-
-  // Helper method to call StartDownload without a referrer.
-  // (virtual for testing)
-  virtual void StartDownload(const GURL& url, ImageFetchedCallback callback);
-
-  // A valid request context getter is required before starting the download.
-  // (virtual for testing)
-  virtual void SetRequestContextGetter(
-      const scoped_refptr<net::URLRequestContextGetter>&
-          request_context_getter);
-
-  // net::URLFetcherDelegate:
-  void OnURLFetchComplete(const net::URLFetcher* source) override;
-
- private:
-  // Runs the callback with the given arguments.
-  void RunCallback(const base::mac::ScopedBlock<ImageFetchedCallback>& callback,
-                   const GURL& url,
-                   const int http_response_code,
-                   NSData* data);
-
-  // Tracks open download requests.  The key is the URLFetcher object doing the
-  // fetch; the value is the callback to use when the download request
-  // completes. When a download request completes, the URLFetcher must be
-  // deleted and the callback called and released.
-  std::map<const net::URLFetcher*, ImageFetchedCallback> downloads_in_progress_;
-  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
-
-  // The task runner used to decode images if necessary.
-  const scoped_refptr<base::TaskRunner> task_runner_;
-
-  // The WeakPtrFactory is used to cancel callbacks if ImageDataFetcher is
-  // destroyed during WebP decoding.
-  base::WeakPtrFactory<ImageDataFetcher> weak_factory_;
-};
-
-#endif  // IOS_WEB_PUBLIC_IMAGE_FETCHER_IMAGE_DATA_FETCHER_H_
-
-}  // namespace web
diff --git a/ios/web/public/image_fetcher/image_data_fetcher.mm b/ios/web/public/image_fetcher/image_data_fetcher.mm
deleted file mode 100644
index 11a237a..0000000
--- a/ios/web/public/image_fetcher/image_data_fetcher.mm
+++ /dev/null
@@ -1,179 +0,0 @@
-// 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.
-
-#import "ios/web/public/image_fetcher/image_data_fetcher.h"
-
-#import <Foundation/Foundation.h>
-#include <stddef.h>
-
-#include "base/bind.h"
-#include "base/location.h"
-#import "base/mac/scoped_nsobject.h"
-#include "base/task_runner.h"
-#include "base/task_runner_util.h"
-#import "ios/web/public/image_fetcher/webp_decoder.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context_getter.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-class WebpDecoderDelegate : public webp_transcode::WebpDecoder::Delegate {
- public:
-  NSData* data() const { return decoded_image_; }
-
-  // WebpDecoder::Delegate methods
-  void OnFinishedDecoding(bool success) override {
-    if (!success)
-      decoded_image_.reset();
-  }
-  void SetImageFeatures(
-      size_t total_size,
-      webp_transcode::WebpDecoder::DecodedImageFormat format) override {
-    decoded_image_.reset([[NSMutableData alloc] initWithCapacity:total_size]);
-  }
-  void OnDataDecoded(NSData* data) override {
-    DCHECK(decoded_image_);
-    [decoded_image_ appendData:data];
-  }
-
- private:
-  ~WebpDecoderDelegate() override {}
-  base::scoped_nsobject<NSMutableData> decoded_image_;
-};
-
-// Content-type header for WebP images.
-static const char kWEBPMimeType[] = "image/webp";
-
-// Returns a NSData object containing the decoded image.
-// Returns nil in case of failure.
-base::scoped_nsobject<NSData> DecodeWebpImage(
-    const base::scoped_nsobject<NSData>& webp_image) {
-  scoped_refptr<WebpDecoderDelegate> delegate(new WebpDecoderDelegate);
-  scoped_refptr<webp_transcode::WebpDecoder> decoder(
-      new webp_transcode::WebpDecoder(delegate.get()));
-  decoder->OnDataReceived(webp_image);
-  DLOG_IF(ERROR, !delegate->data()) << "WebP image decoding failed.";
-  return base::scoped_nsobject<NSData>(delegate->data());
-}
-
-}  // namespace
-
-namespace web {
-
-ImageDataFetcher::ImageDataFetcher(
-    const scoped_refptr<base::TaskRunner>& task_runner)
-    : request_context_getter_(nullptr),
-      task_runner_(task_runner),
-      weak_factory_(this) {
-  DCHECK(task_runner_.get());
-}
-
-ImageDataFetcher::~ImageDataFetcher() {
-  // Delete all the entries in the |downloads_in_progress_| map.  This will in
-  // turn cancel all of the requests.
-  for (const auto& pair : downloads_in_progress_) {
-    delete pair.first;
-  }
-}
-
-void ImageDataFetcher::StartDownload(
-    const GURL& url,
-    ImageFetchedCallback callback,
-    const std::string& referrer,
-    net::URLRequest::ReferrerPolicy referrer_policy) {
-  DCHECK(request_context_getter_.get());
-  net::URLFetcher* fetcher =
-      net::URLFetcher::Create(url, net::URLFetcher::GET, this).release();
-  downloads_in_progress_[fetcher] = [callback copy];
-  fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
-                        net::LOAD_DO_NOT_SAVE_COOKIES |
-                        net::LOAD_DO_NOT_SEND_AUTH_DATA);
-  fetcher->SetRequestContext(request_context_getter_.get());
-  fetcher->SetReferrer(referrer);
-  fetcher->SetReferrerPolicy(referrer_policy);
-  fetcher->Start();
-}
-
-void ImageDataFetcher::StartDownload(const GURL& url,
-                                     ImageFetchedCallback callback) {
-  ImageDataFetcher::StartDownload(url, callback, std::string(),
-                                  net::URLRequest::NEVER_CLEAR_REFERRER);
-}
-
-// Delegate callback that is called when URLFetcher completes.  If the image
-// was fetched successfully, creates a new NSData and returns it to the
-// callback, otherwise returns nil to the callback.
-void ImageDataFetcher::OnURLFetchComplete(const net::URLFetcher* fetcher) {
-  if (downloads_in_progress_.find(fetcher) == downloads_in_progress_.end()) {
-    LOG(ERROR) << "Received callback for unknown URLFetcher " << fetcher;
-    return;
-  }
-
-  // Ensures that |fetcher| will be deleted in the event of early return.
-  std::unique_ptr<const net::URLFetcher> fetcher_deleter(fetcher);
-
-  // Retrieves the callback and ensures that it will be deleted in the event
-  // of early return.
-  base::mac::ScopedBlock<ImageFetchedCallback> callback(
-      downloads_in_progress_[fetcher]);
-
-  // Remove |fetcher| from the map.
-  downloads_in_progress_.erase(fetcher);
-
-  // Make sure the request was successful. For "data" requests, the response
-  // code has no meaning, because there is no actual server (data is encoded
-  // directly in the URL). In that case, set the response code to 200 (OK).
-  const GURL& original_url = fetcher->GetOriginalURL();
-  const int http_response_code =
-      original_url.SchemeIs("data") ? 200 : fetcher->GetResponseCode();
-  if (http_response_code != 200) {
-    (callback.get())(original_url, http_response_code, nil);
-    return;
-  }
-
-  std::string response;
-  if (!fetcher->GetResponseAsString(&response)) {
-    (callback.get())(original_url, http_response_code, nil);
-    return;
-  }
-
-  // Create a NSData from the returned data and notify the callback.
-  base::scoped_nsobject<NSData> data([[NSData alloc]
-      initWithBytes:reinterpret_cast<const unsigned char*>(response.data())
-             length:response.size()]);
-
-  if (fetcher->GetResponseHeaders()) {
-    std::string mime_type;
-    fetcher->GetResponseHeaders()->GetMimeType(&mime_type);
-    if (mime_type == kWEBPMimeType) {
-      base::PostTaskAndReplyWithResult(
-          task_runner_.get(), FROM_HERE, base::Bind(&DecodeWebpImage, data),
-          base::Bind(&ImageDataFetcher::RunCallback, weak_factory_.GetWeakPtr(),
-                     callback, original_url, http_response_code));
-      return;
-    }
-  }
-  (callback.get())(original_url, http_response_code, data);
-}
-
-void ImageDataFetcher::RunCallback(
-    const base::mac::ScopedBlock<ImageFetchedCallback>& callback,
-    const GURL& url,
-    int http_response_code,
-    NSData* data) {
-  (callback.get())(url, http_response_code, data);
-}
-
-void ImageDataFetcher::SetRequestContextGetter(
-    const scoped_refptr<net::URLRequestContextGetter>& request_context_getter) {
-  request_context_getter_ = request_context_getter;
-}
-
-}  // namespace web
diff --git a/ios/web/public/image_fetcher/image_data_fetcher_unittest.mm b/ios/web/public/image_fetcher/image_data_fetcher_unittest.mm
deleted file mode 100644
index 72d79419..0000000
--- a/ios/web/public/image_fetcher/image_data_fetcher_unittest.mm
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2011 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 "ios/web/public/image_fetcher/image_data_fetcher.h"
-
-#import <UIKit/UIKit.h>
-
-#include "base/ios/ios_util.h"
-#include "base/mac/scoped_block.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace {
-
-static unsigned char kJPGImage[] = {
-    255, 216, 255, 224, 0,   16,  74,  70, 73, 70, 0,   1,   1,   1,   0,
-    72,  0,   72,  0,   0,   255, 254, 0,  19, 67, 114, 101, 97,  116, 101,
-    100, 32,  119, 105, 116, 104, 32,  71, 73, 77, 80,  255, 219, 0,   67,
-    0,   5,   3,   4,   4,   4,   3,   5,  4,  4,  4,   5,   5,   5,   6,
-    7,   12,  8,   7,   7,   7,   7,   15, 11, 11, 9,   12,  17,  15,  18,
-    18,  17,  15,  17,  17,  19,  22,  28, 23, 19, 20,  26,  21,  17,  17,
-    24,  33,  24,  26,  29,  29,  31,  31, 31, 19, 23,  34,  36,  34,  30,
-    36,  28,  30,  31,  30,  255, 219, 0,  67, 1,  5,   5,   5,   7,   6,
-    7,   14,  8,   8,   14,  30,  20,  17, 20, 30, 30,  30,  30,  30,  30,
-    30,  30,  30,  30,  30,  30,  30,  30, 30, 30, 30,  30,  30,  30,  30,
-    30,  30,  30,  30,  30,  30,  30,  30, 30, 30, 30,  30,  30,  30,  30,
-    30,  30,  30,  30,  30,  30,  30,  30, 30, 30, 30,  30,  30,  30,  255,
-    192, 0,   17,  8,   0,   1,   0,   1,  3,  1,  34,  0,   2,   17,  1,
-    3,   17,  1,   255, 196, 0,   21,  0,  1,  1,  0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,  0,  0,  8,   255, 196, 0,   20,
-    16,  1,   0,   0,   0,   0,   0,   0,  0,  0,  0,   0,   0,   0,   0,
-    0,   0,   0,   255, 196, 0,   20,  1,  1,  0,  0,   0,   0,   0,   0,
-    0,   0,   0,   0,   0,   0,   0,   0,  0,  0,  255, 196, 0,   20,  17,
-    1,   0,   0,   0,   0,   0,   0,   0,  0,  0,  0,   0,   0,   0,   0,
-    0,   0,   255, 218, 0,   12,  3,   1,  0,  2,  17,  3,   17,  0,   63,
-    0,   178, 192, 7,   255, 217};
-
-static unsigned char kPNGImage[] = {
-    137, 80,  78,  71,  13,  10,  26,  10,  0,   0,   0,   13,  73,  72,  68,
-    82,  0,   0,   0,   1,   0,   0,   0,   1,   1,   0,   0,   0,   0,   55,
-    110, 249, 36,  0,   0,   0,   2,   98,  75,  71,  68,  0,   1,   221, 138,
-    19,  164, 0,   0,   0,   9,   112, 72,  89,  115, 0,   0,   11,  18,  0,
-    0,   11,  18,  1,   210, 221, 126, 252, 0,   0,   0,   9,   118, 112, 65,
-    103, 0,   0,   0,   1,   0,   0,   0,   1,   0,   199, 149, 95,  237, 0,
-    0,   0,   10,  73,  68,  65,  84,  8,   215, 99,  104, 0,   0,   0,   130,
-    0,   129, 221, 67,  106, 244, 0,   0,   0,   25,  116, 69,  88,  116, 99,
-    111, 109, 109, 101, 110, 116, 0,   67,  114, 101, 97,  116, 101, 100, 32,
-    119, 105, 116, 104, 32,  71,  73,  77,  80,  231, 175, 64,  203, 0,   0,
-    0,   37,  116, 69,  88,  116, 100, 97,  116, 101, 58,  99,  114, 101, 97,
-    116, 101, 0,   50,  48,  49,  49,  45,  48,  54,  45,  50,  50,  84,  49,
-    54,  58,  49,  54,  58,  52,  54,  43,  48,  50,  58,  48,  48,  31,  248,
-    231, 223, 0,   0,   0,   37,  116, 69,  88,  116, 100, 97,  116, 101, 58,
-    109, 111, 100, 105, 102, 121, 0,   50,  48,  49,  49,  45,  48,  54,  45,
-    50,  50,  84,  49,  54,  58,  49,  54,  58,  52,  54,  43,  48,  50,  58,
-    48,  48,  110, 165, 95,  99,  0,   0,   0,   17,  116, 69,  88,  116, 106,
-    112, 101, 103, 58,  99,  111, 108, 111, 114, 115, 112, 97,  99,  101, 0,
-    50,  44,  117, 85,  159, 0,   0,   0,   32,  116, 69,  88,  116, 106, 112,
-    101, 103, 58,  115, 97,  109, 112, 108, 105, 110, 103, 45,  102, 97,  99,
-    116, 111, 114, 0,   50,  120, 50,  44,  49,  120, 49,  44,  49,  120, 49,
-    73,  250, 166, 180, 0,   0,   0,   0,   73,  69,  78,  68,  174, 66,  96,
-    130};
-
-static unsigned char kWEBPImage[] = {
-    82, 73, 70, 70, 74,  0, 0,  0,   87,  69,  66,  80,  86,  80, 56, 88, 10,
-    0,  0,  0,  16, 0,   0, 0,  0,   0,   0,   0,   0,   0,   65, 76, 80, 72,
-    12, 0,  0,  0,  1,   7, 16, 17,  253, 15,  68,  68,  255, 3,  0,  0,  86,
-    80, 56, 32, 24, 0,   0, 0,  48,  1,   0,   157, 1,   42,  1,  0,  1,  0,
-    3,  0,  52, 37, 164, 0, 3,  112, 0,   254, 251, 253, 80,  0};
-
-static const char kTestUrl[] = "http://www.img.com";
-
-static const char kWEBPHeaderResponse[] =
-    "HTTP/1.1 200 OK\0Content-type: image/webp\0\0";
-
-}  // namespace
-
-namespace web {
-
-class ImageDataFetcherTest : public PlatformTest {
- protected:
-  ImageDataFetcherTest()
-      : worker_thread_("TestThread"),
-        callback_(
-            [^(const GURL& original_url, int http_response_code, NSData* data) {
-              result_ = [UIImage imageWithData:data];
-              called_ = true;
-            } copy]) {
-    worker_thread_.Start();
-
-    image_fetcher_ =
-        base::MakeUnique<ImageDataFetcher>(worker_thread_.task_runner());
-    image_fetcher_->SetRequestContextGetter(
-        new net::TestURLRequestContextGetter(
-            base::ThreadTaskRunnerHandle::Get()));
-  }
-
-  net::TestURLFetcher* SetupFetcher() {
-    image_fetcher_->StartDownload(GURL(kTestUrl), callback_);
-    EXPECT_EQ(nil, result_);
-    EXPECT_EQ(false, called_);
-    net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-    DCHECK(fetcher);
-    DCHECK(fetcher->delegate());
-    return fetcher;
-  }
-
-  // Message loop for the main test thread.
-  base::MessageLoop loop_;
-
-  // Worker thread used for ImageFetcher's asynchronous work.
-  base::Thread worker_thread_;
-
-  base::mac::ScopedBlock<ImageFetchedCallback> callback_;
-  net::TestURLFetcherFactory factory_;
-  std::unique_ptr<ImageDataFetcher> image_fetcher_;
-  UIImage* result_ = nil;
-  bool called_ = false;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ImageDataFetcherTest);
-};
-
-TEST_F(ImageDataFetcherTest, TestError) {
-  net::TestURLFetcher* fetcher = SetupFetcher();
-  fetcher->set_response_code(404);
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  EXPECT_EQ(nil, result_);
-  EXPECT_TRUE(called_);
-}
-
-TEST_F(ImageDataFetcherTest, TestJpg) {
-  net::TestURLFetcher* fetcher = SetupFetcher();
-  fetcher->set_response_code(200);
-  fetcher->SetResponseString(std::string((char*)kJPGImage, sizeof(kJPGImage)));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  EXPECT_NE(nil, result_);
-  EXPECT_TRUE(called_);
-}
-
-TEST_F(ImageDataFetcherTest, TestPng) {
-  net::TestURLFetcher* fetcher = SetupFetcher();
-  fetcher->set_response_code(200);
-  fetcher->SetResponseString(std::string((char*)kPNGImage, sizeof(kPNGImage)));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  EXPECT_NE(nil, result_);
-  EXPECT_TRUE(called_);
-}
-
-TEST_F(ImageDataFetcherTest, TestGoodWebP) {
-  net::TestURLFetcher* fetcher = SetupFetcher();
-  fetcher->set_response_code(200);
-  fetcher->SetResponseString(
-      std::string((char*)kWEBPImage, sizeof(kWEBPImage)));
-  scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders(
-      std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse))));
-  fetcher->set_response_headers(headers);
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  worker_thread_.FlushForTesting();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_NE(nil, result_);
-  EXPECT_TRUE(called_);
-}
-
-TEST_F(ImageDataFetcherTest, TestBadWebP) {
-  net::TestURLFetcher* fetcher = SetupFetcher();
-  fetcher->set_response_code(200);
-  fetcher->SetResponseString("This is not a valid WebP image");
-  scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders(
-      std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse))));
-  fetcher->set_response_headers(headers);
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  worker_thread_.FlushForTesting();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(nil, result_);
-  EXPECT_TRUE(called_);
-}
-
-TEST_F(ImageDataFetcherTest, DeleteDuringWebPDecoding) {
-  net::TestURLFetcher* fetcher = SetupFetcher();
-  fetcher->set_response_code(200);
-  fetcher->SetResponseString(
-      std::string((char*)kWEBPImage, sizeof(kWEBPImage)));
-  scoped_refptr<net::HttpResponseHeaders> headers(new net::HttpResponseHeaders(
-      std::string(kWEBPHeaderResponse, arraysize(kWEBPHeaderResponse))));
-  fetcher->set_response_headers(headers);
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  // Delete the image fetcher, and check that the callback is not called.
-  image_fetcher_.reset();
-  worker_thread_.FlushForTesting();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(nil, result_);
-  EXPECT_FALSE(called_);
-}
-
-TEST_F(ImageDataFetcherTest, TestCallbacksNotCalledDuringDeletion) {
-  image_fetcher_->StartDownload(GURL(kTestUrl), callback_);
-  image_fetcher_.reset();
-  EXPECT_FALSE(called_);
-}
-
-}  // namespace web
diff --git a/ios/web/public/test/mock_image_data_fetcher.h b/ios/web/public/test/mock_image_data_fetcher.h
deleted file mode 100644
index 65e7b40..0000000
--- a/ios/web/public/test/mock_image_data_fetcher.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_WEB_PUBLIC_TEST_MOCK_IMAGE_DATA_FETCHER_H_
-#define IOS_WEB_PUBLIC_TEST_MOCK_IMAGE_DATA_FETCHER_H_
-
-#import "ios/web/public/image_fetcher/image_data_fetcher.h"
-
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace web {
-
-// Mocks the ImageDataFetcher utility class, which can be used to asynchronously
-// retrieve an image from an URL.
-class MockImageDataFetcher : public ImageDataFetcher {
- public:
-  explicit MockImageDataFetcher(
-      const scoped_refptr<base::TaskRunner>& task_runner);
-  ~MockImageDataFetcher() override;
-
-  MOCK_METHOD4(StartDownload,
-               void(const GURL& url,
-                    ImageFetchedCallback callback,
-                    const std::string& referrer,
-                    net::URLRequest::ReferrerPolicy referrer_policy));
-  MOCK_METHOD2(StartDownload,
-               void(const GURL& url, ImageFetchedCallback callback));
-  MOCK_METHOD1(SetRequestContextGetter,
-               void(const scoped_refptr<net::URLRequestContextGetter>&
-                        request_context_getter));
-};
-
-}  // namespace web
-
-#endif  // IOS_WEB_PUBLIC_TEST_MOCK_IMAGE_DATA_FETCHER_H_
diff --git a/ios/web/public/test/mock_image_data_fetcher.mm b/ios/web/public/test/mock_image_data_fetcher.mm
deleted file mode 100644
index fbdfd57..0000000
--- a/ios/web/public/test/mock_image_data_fetcher.mm
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/web/public/test/mock_image_data_fetcher.h"
-
-namespace web {
-
-MockImageDataFetcher::MockImageDataFetcher(
-    const scoped_refptr<base::TaskRunner>& task_runner)
-    : ImageDataFetcher(task_runner) {}
-
-MockImageDataFetcher::~MockImageDataFetcher() {}
-
-}  // namespace web
diff --git a/media/capture/content/OWNERS b/media/capture/content/OWNERS
index 02bdb39..980d5f2 100644
--- a/media/capture/content/OWNERS
+++ b/media/capture/content/OWNERS
@@ -1 +1,3 @@
 miu@chromium.org
+
+# COMPONENT: UI>Browser>TabCapture
diff --git a/media/cast/OWNERS b/media/cast/OWNERS
index 586a2f54..41c70ee 100644
--- a/media/cast/OWNERS
+++ b/media/cast/OWNERS
@@ -1,2 +1,4 @@
 hubbe@chromium.org
 miu@chromium.org
+
+# COMPONENT: Internals>Cast>Streaming
diff --git a/media/remoting/OWNERS b/media/remoting/OWNERS
index 98698443..e85c2ba 100644
--- a/media/remoting/OWNERS
+++ b/media/remoting/OWNERS
@@ -1,2 +1,4 @@
 erickung@chromium.org
 miu@chromium.org
+
+# COMPONENT: Internals>Cast>Streaming
diff --git a/net/proxy/polling_proxy_config_service.cc b/net/proxy/polling_proxy_config_service.cc
index defe507..af6fc9cb 100644
--- a/net/proxy/polling_proxy_config_service.cc
+++ b/net/proxy/polling_proxy_config_service.cc
@@ -11,8 +11,8 @@
 #include "base/observer_list.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/task_scheduler/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "base/threading/worker_pool.h"
 #include "net/proxy/proxy_config.h"
 
 namespace net {
@@ -90,17 +90,17 @@
     last_poll_time_ = base::TimeTicks::Now();
     poll_task_outstanding_ = true;
     poll_task_queued_ = false;
-    base::WorkerPool::PostTask(
-        FROM_HERE,
-        base::Bind(&Core::PollOnWorkerThread, this, get_config_func_),
-        true);
+    base::PostTaskWithTraits(
+        FROM_HERE, base::TaskTraits().MayBlock().WithShutdownBehavior(
+                       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN),
+        base::Bind(&Core::PollAsync, this, get_config_func_));
   }
 
  private:
   friend class base::RefCountedThreadSafe<Core>;
   ~Core() {}
 
-  void PollOnWorkerThread(GetConfigFunction func) {
+  void PollAsync(GetConfigFunction func) {
     ProxyConfig config;
     func(&config);
 
diff --git a/net/url_request/url_request_context_builder_unittest.cc b/net/url_request/url_request_context_builder_unittest.cc
index cd8f21d..dabd8c5 100644
--- a/net/url_request/url_request_context_builder_unittest.cc
+++ b/net/url_request/url_request_context_builder_unittest.cc
@@ -7,7 +7,9 @@
 #include <memory>
 
 #include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_scheduler.h"
 #include "build/build_config.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_auth_challenge_tokenizer.h"
@@ -58,7 +60,8 @@
 
 class URLRequestContextBuilderTest : public PlatformTest {
  protected:
-  URLRequestContextBuilderTest() {
+  URLRequestContextBuilderTest()
+      : scoped_task_scheduler_(base::MessageLoop::current()) {
     test_server_.AddDefaultHandlers(
         base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest")));
 #if defined(OS_LINUX) || defined(OS_ANDROID)
@@ -69,6 +72,9 @@
 
   EmbeddedTestServer test_server_;
   URLRequestContextBuilder builder_;
+
+ private:
+  base::test::ScopedTaskScheduler scoped_task_scheduler_;
 };
 
 TEST_F(URLRequestContextBuilderTest, DefaultSettings) {
diff --git a/sandbox/linux/OWNERS b/sandbox/linux/OWNERS
index c05fa11..84977847 100644
--- a/sandbox/linux/OWNERS
+++ b/sandbox/linux/OWNERS
@@ -5,3 +5,6 @@
 # Emeritus
 mdempsky@chromium.org
 rickyz@chromium.org
+
+# TEAM: security-dev@chromium.org
+# COMPONENT: Internals>Sandbox
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 2c4cc74c..13a3833 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1847,9 +1847,14 @@
 crbug.com/688854 external/wpt/hr-time/window-worker-time-origin.html [ Failure ]
 
 # 2017-02-14: These directories were just imported but expectations and baselines haven't been set yet.
-crbug.com/692105 external/wpt/referrer-policy [ Skip ]
 crbug.com/692105 external/wpt/mixed-content [ Skip ]
 
+# These policies are not implemented yet.
+crbug.com/627968 external/wpt/referrer-policy/origin-when-cross-origin/http-rp/same-origin/ [ Skip ]
+crbug.com/627968 external/wpt/referrer-policy/same-origin/ [ Skip ]
+crbug.com/627968 external/wpt/referrer-policy/strict-origin/ [ Skip ]
+crbug.com/627968 external/wpt/referrer-policy/strict-origin-when-cross-origin/ [ Skip ]
+
 # ====== New tests from w3c-test-autoroller added here ======
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html [ Failure ]
@@ -1909,6 +1914,8 @@
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html [ Failure ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html [ Failure ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html [ Failure ]
+crbug.com/626703 external/wpt/referrer-policy/generic/subresource-test/image-decoding.html [ Timeout ]
+crbug.com/626703 external/wpt/referrer-policy/generic/unsupported-csp-referrer-directive.html [ Timeout ]
 crbug.com/626703 external/wpt/streams/writable-streams/close.dedicatedworker.html [ Timeout ]
 crbug.com/626703 external/wpt/streams/writable-streams/close.html [ Timeout ]
 crbug.com/626703 external/wpt/streams/writable-streams/close.serviceworker.https.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-shadow.html
index b4f72581..fc46ba6 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-drawImage-shadow.html
@@ -18,7 +18,6 @@
 
 // Create the image object to be drawn on the master canvas.
 var img = new Image();
-img.onload = drawImageToCanvasAndCheckPixels;
 img.src = aCanvas.toDataURL(); // set a data URI of the base64 enconded image as the source
 
 // Create master canvas.
@@ -28,6 +27,34 @@
 canvas.setAttribute('height', '600');
 var ctx = canvas.getContext('2d');
 
+var testScenarios = [
+    ['Test solid shadow 1', 260, 300, [0, 0, 0, 0]],
+    ['Test solid shadow 2', 350, 100, [240, 50, 50, 255]],
+    ['Test solid shadow 3', 400, 200, [240, 50, 50, 255]],
+    ['Test solid shadow 4', 490, 65, [0, 0, 0, 0]],
+    ['Test solid shadow 5', 485, 65, [0, 0, 0, 0]],
+
+    ['Test blurry shadow 1', 260, 400, [0, 0, 0, 0]],
+    ['Test blurry shadow 2', 350, 300, [0, 0, 255, 'neq', 255]],
+    ['Test blurry shadow 3', 300, 400, [0, 0, 255, 'neq', 255]],
+    ['Test blurry shadow 4', 300, 500, [0, 0, 255, 'neq', 255]],
+    ['Test blurry shadow 5', 400, 500, [0, 0, 255, 'neq', 255]],
+    ['Test blurry shadow 6', 400, 400, [0, 0, 255]],
+    ['Test blurry shadow 7', 490, 315, [0, 0, 0, 0]],
+    ['Test blurry shadow 8', 485, 320, [0, 0, 0, 0]],   
+];
+
+function runTestScenario(x, y, expectedColor)
+{
+    imageData = ctx.getImageData(x, y, 1, 1).data;
+    if (expectedColor.length == 5) {
+        assert_array_equals(imageData.slice(0,3), expectedColor.slice(0,3));
+        assert_not_equals(imageData[3], expectedColor[4]);
+    } else {
+        assert_array_equals(imageData.slice(0, expectedColor.length), expectedColor);
+    }
+}
+
 function drawImageToCanvasAndCheckPixels() {
     ctx.shadowOffsetX = 250;
     ctx.shadowColor = 'rgba(240, 50, 50, 1.0)';
@@ -39,106 +66,16 @@
     ctx.shadowColor = 'rgba(0, 0, 255, 1.0)';
     ctx.drawImage(img, 50, 300);
 
-    checkPixels();
-}
+    for (var i = 0; i < testScenarios.length; i++)
+        runTestScenario(testScenarios[i][1],
+                        testScenarios[i][2],
+                        testScenarios[i][3]);}
 
-function checkPixels() {
-    test(function(t) {
-        var imageData, data;
-    
-        // Verify solid shadow.
-        imageData = ctx.getImageData(260, 300, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 0);
-        assert_equals(d[3], 0);
-    
-        imageData = ctx.getImageData(350, 100, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 240);
-        assert_equals(d[1], 50);
-        assert_equals(d[2], 50);
-        assert_equals(d[3], 255);
-    
-        imageData = ctx.getImageData(400, 200, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 240);
-        assert_equals(d[1], 50);
-        assert_equals(d[2], 50);
-        assert_equals(d[3], 255);
-    
-        imageData = ctx.getImageData(490, 65, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 0);
-        assert_equals(d[3], 0);
-    
-        imageData = ctx.getImageData(485, 65, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 0);
-        assert_equals(d[3], 0);
-    
-        // Verify blurry shadow.
-        imageData = ctx.getImageData(260, 400, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 0);
-        assert_equals(d[3], 0);
-    
-        imageData = ctx.getImageData(350, 300, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 255);
-        assert_not_equals(d[3], 255);
-    
-        imageData = ctx.getImageData(300, 400, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 255);
-        assert_not_equals(d[3], 255);
-    
-        imageData = ctx.getImageData(300, 500, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 255);
-        assert_not_equals(d[3], 255);
-    
-        imageData = ctx.getImageData(400, 500, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 255);
-        assert_not_equals(d[3], 255);
-    
-        imageData = ctx.getImageData(400, 400, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 255);
-    
-        imageData = ctx.getImageData(490, 315, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 0);
-        assert_equals(d[3], 0);
-    
-        imageData = ctx.getImageData(485, 320, 1, 1);
-        d = imageData.data;
-        assert_equals(d[0], 0);
-        assert_equals(d[1], 0);
-        assert_equals(d[2], 0);
-        assert_equals(d[3], 0);
-    
-    }, "Ensure correct behavior of canvas with image shadow. A square with a cut-out top-right corner should be displayed with solid shadow (top) and blur shadow (bottom).");
-}
+async_test(t => {
+        img.onload = function() {
+            t.step(drawImageToCanvasAndCheckPixels);
+            t.done();
+        }
+}, "Ensure correct behavior of canvas with image shadow. A square with a cut-out top-right corner should be displayed with solid shadow (top) and blur shadow (bottom).");
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-quadratic-same-endpoint-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-quadratic-same-endpoint-expected.txt
deleted file mode 100644
index 3625dcb7..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-quadratic-same-endpoint-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Bug 105650: Test correct rendering of quadratic and bezier curves with coincident endpoints
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS blue_value is 255
-PASS blue_value is 0
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-quadratic-same-endpoint.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-quadratic-same-endpoint.html
index a6becb96..5147b9a 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-quadratic-same-endpoint.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-quadratic-same-endpoint.html
@@ -1,44 +1,40 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
 <canvas id="canvas" width="100" height="100"></canvas>
 <script>
-description("Bug 105650: Test correct rendering of quadratic and bezier curves with coincident endpoints");
 var ctx = document.getElementById('canvas').getContext('2d');
-var data;
 
-function shouldBeYellow(x,y)
+function shouldBeYellow(x, y)
 {
-	blue_value = ctx.getImageData(x, y, 1, 1).data[2];
-	shouldBe("blue_value", "0");
+    blue_value = ctx.getImageData(x, y, 1, 1).data[2];
+    assert_equals(blue_value, 0);
 }
 
-function shouldBeBlue(x,y)
+function shouldBeBlue(x, y)
 {
-	blue_value = ctx.getImageData(x, y, 1, 1).data[2];
-	shouldBe("blue_value", "255");
+    blue_value = ctx.getImageData(x, y, 1, 1).data[2];
+    assert_equals(blue_value, 255);
 }
 
-ctx.fillStyle = '#00f';
-ctx.strokeStyle = '#ff0';
-ctx.lineWidth = 30;
-
-ctx.beginPath();
-ctx.fillRect(0,0,100,100);
-
-// quadratic with coincident endpoint
-ctx.moveTo(20,20);
-
-//Next line should be close to ctx.bezierCurveTo(81,80,80,80,20,20);
-ctx.quadraticCurveTo(110,110,20,20);
-
-shouldBeBlue(70,70);
-ctx.stroke();
-shouldBeYellow(70,70);
+test(function(t) {
+    ctx.fillStyle = '#00f';
+    ctx.strokeStyle = '#ff0';
+    ctx.lineWidth = 30;
+    
+    ctx.beginPath();
+    ctx.fillRect(0, 0, 100, 100);
+    
+    // quadratic with coincident endpoint
+    ctx.moveTo(20, 20);
+    
+    //Next line should be close to ctx.bezierCurveTo(81, 80, 80, 80, 20, 20);
+    ctx.quadraticCurveTo(110, 110, 20, 20);
+    
+    shouldBeBlue(70, 70);
+    ctx.stroke();
+    shouldBeYellow(70, 70);
+}, "Bug 105650: Test correct rendering of quadratic and bezier curves with coincident endpoints");
 
 </script>
 </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod-expected.txt
deleted file mode 100644
index c3bcf64..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Series of tests to ensure correct behaviour of spreadMethod to a radial gradient.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS imgdata[4] is 0
-PASS imgdata[5] is 128
-PASS imgdata[6] is 0
-PASS imgdata[7] is 255
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod.html
index b736225..cea3732 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod.html
@@ -1,9 +1,16 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
-<body>
-<script src="canvas-radial-gradient-spreadMethod.js"></script>
-</body>
-</html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+test(function(t) {
+    var ctx = document.createElement('canvas').getContext('2d');
+    
+    var radgrad = ctx.createRadialGradient(80, 90, 90, 80, 50, 100);
+    radgrad.addColorStop(0, 'green');
+    radgrad.addColorStop(1, 'green');
+    
+    ctx.fillStyle = radgrad;
+    ctx.fillRect(0, 0, 100, 100);
+    var imageData = ctx.getImageData(0, 0, 100, 100).data;
+    assert_array_equals(imageData.slice(4, 8), [0, 128, 0, 255]);
+}, "Verify correct behaviour of spreadMethod to a radial gradient.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod.js b/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod.js
deleted file mode 100644
index 258c9479..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-radial-gradient-spreadMethod.js
+++ /dev/null
@@ -1,15 +0,0 @@
-description("Series of tests to ensure correct behaviour of spreadMethod to a radial gradient.");
-var ctx = document.createElement('canvas').getContext('2d');
-
-var radgrad = ctx.createRadialGradient(80,90,90,80,50,100);
-radgrad.addColorStop(0, 'green');
-radgrad.addColorStop(1, 'green');
-
-ctx.fillStyle = radgrad;
-ctx.fillRect(0, 0, 100, 100);
-var imageData = ctx.getImageData(0, 0, 100, 100);
-var imgdata = imageData.data;
-shouldBe("imgdata[4]", "0");
-shouldBe("imgdata[5]", "128");
-shouldBe("imgdata[6]", "0");
-shouldBe("imgdata[7]", "255");
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-resetTransform-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-resetTransform-expected.txt
deleted file mode 100644
index 800c5b3..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-resetTransform-expected.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-This test checks resetTransform in canvas v5
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-resetTransform should reset other transforms.
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-resetTransform should not affect CTM outside of save() and restore().
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-PASS imgdata[0] is 255
-PASS imgdata[1] is 0
-PASS imgdata[2] is 0
-resetTransform should restore the path transform to identity.
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-resetTransform should resolve the non-invertible CTM state.
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-The path object should not be updated on the non-invertible CTM state.
-resetTransform should restore the path object just before CTM became non-invertible.
-PASS imgdata[0] is 255
-PASS imgdata[1] is 0
-PASS imgdata[2] is 0
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-resetTransform.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-resetTransform.html
index fe2d369d..f689b71 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-resetTransform.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-resetTransform.html
@@ -1,9 +1,97 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
-<script src="script-tests/canvas-resetTransform.js"></script>
+<script>
+test(function(t) {
+    
+    var canvas = document.createElement('canvas');
+    document.body.appendChild(canvas);
+    canvas.setAttribute('width', '100');
+    canvas.setAttribute('height', '100');
+    var ctx = canvas.getContext('2d');
+    
+    ctx.save();
+    ctx.scale(0.5, 0.5);
+    ctx.resetTransform();
+    ctx.fillStyle = 'green';
+    ctx.fillRect(0, 0, 100, 100);
+    ctx.restore();
+    
+    var imageData = ctx.getImageData(98, 98, 1, 1).data;
+    assert_array_equals(imageData.slice(0, 3), [0, 128, 0]);
+    
+    ctx.save();
+    ctx.scale(0.5, 0.5);
+    ctx.save();
+    ctx.resetTransform();
+    ctx.fillStyle = 'green';
+    ctx.fillRect(0, 0, 100, 100);
+    ctx.restore();
+    ctx.fillStyle = 'red';
+    ctx.fillRect(0, 0, 100, 100);
+    ctx.restore();
+    
+    imageData = ctx.getImageData(98, 98, 1, 1).data;
+    assert_array_equals(imageData.slice(0, 3), [0, 128, 0]);
+    
+    imageData = ctx.getImageData(48, 48, 1, 1).data;
+    assert_array_equals(imageData.slice(0, 3), [255, 0, 0]);
+    
+    /* This should draw a green rectangle on on top of a red one. The red should not be visible. */
+    ctx.save();
+    ctx.beginPath();
+    ctx.moveTo(0, 0);
+    ctx.lineTo(100, 0);
+    ctx.lineTo(100, 100);
+    ctx.lineTo(0, 100);
+    ctx.fillStyle = 'red';
+    ctx.fill();
+    ctx.translate(200, 0);
+    ctx.resetTransform();
+    ctx.fillStyle = 'green';
+    ctx.fill();
+    ctx.restore();
+    
+    imageData = ctx.getImageData(50, 50, 1, 1).data;
+    assert_array_equals(imageData.slice(0, 3), [0, 128, 0]);
+    
+    ctx.save();
+    ctx.fillStyle = 'red';
+    ctx.fillRect(0, 0, 100, 100);
+    ctx.beginPath();
+    ctx.moveTo(0, 0);
+    ctx.lineTo(100, 0);
+    ctx.lineTo(100, 100);
+    ctx.lineTo(0, 100);
+    ctx.scale(0, 0);
+    ctx.resetTransform();
+    ctx.fillStyle = 'green';
+    ctx.fill();
+    ctx.restore();
+    
+    imageData = ctx.getImageData(98, 98, 1, 1).data;
+    assert_array_equals(imageData.slice(0, 3), [0, 128, 0]);
+    
+    ctx.save();
+    ctx.fillStyle = 'red';
+    ctx.fillRect(0, 0, 100, 100);
+    ctx.beginPath();
+    ctx.moveTo(0, 0);
+    ctx.lineTo(100, 0);
+    ctx.lineTo(100, 50);
+    ctx.scale(0, 0);
+    ctx.lineTo(100, 100);
+    ctx.resetTransform();
+    ctx.lineTo(0, 100);
+    ctx.fillStyle = 'green';
+    ctx.fill();
+    ctx.restore();
+    
+    imageData = ctx.getImageData(98, 98, 1, 1).data;
+    assert_array_equals(imageData.slice(0, 3), [255, 0, 0]);
+    
+    imageData = ctx.getImageData(98, 48, 1, 1).data;
+    assert_array_equals(imageData.slice(0, 3), [0, 128, 0]);
+}, "This test checks resetTransform in canvas v5");
+</script>
 </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-expected.txt
deleted file mode 100644
index c8a11fe..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-expected.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-Test of save and restore on canvas graphics context.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS pixel() is black
-PASS pixel() is red
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is red
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is red
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is red
-PASS pixel() is black
-PASS pixel() is green
-PASS pixel() is green
-PASS pixel() is red
-PASS pixel() is green
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is black
-PASS pixel() is red
-PASS pixel() is red
-PASS pixel() is green
-PASS pixel() is red
-PASS pixel() is red
-PASS pixel() is green
-PASS pixel() is black
-PASS pixel() is black
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path-expected.txt
deleted file mode 100644
index c3c69a8..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This test ensures that paths are correctly handled over save/restore boundaries
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS getPixel(25,25) is [0,128,0,255]
-PASS getPixel(75,25) is [0,128,0,255]
-PASS getPixel(75,75) is [255,0,0,255]
-PASS getPixel(25,75) is [0,128,0,255]
-PASS getPixel(75,75) is [255,0,0,255]
-PASS getPixel(75,75) is [0,128,0,255]
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path.html
index 41589b1..ef6ddcc 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path.html
@@ -1,2 +1,57 @@
-<script src="../../resources/js-test.js"></script>
-<script src="canvas-save-restore-with-path.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+test(function(t) {
+}, "This test ensures that paths are correctly handled over save/restore boundaries");
+
+function pixelShouldBe(x, y, color) {
+    assert_array_equals(context.getImageData(x, y, 1, 1).data, color);
+}
+
+var canvas = document.createElement("canvas");
+canvas.width = 100;
+canvas.height = 100;
+
+var context = canvas.getContext("2d");
+context.fillStyle = "red";
+context.fillRect(0, 0, 100, 100);
+context.fillStyle = "green";
+
+// Test translate
+context.beginPath();
+context.save();
+context.translate(100, 100);
+context.rect(-100, -100, 50, 50);
+context.restore();
+context.fill();
+pixelShouldBe(25, 25, [0, 128, 0, 255]);
+
+// Test scale
+context.beginPath();
+context.save();
+context.scale(2, 2);
+context.rect(25, 0, 25, 25);
+context.restore();
+context.fill();
+pixelShouldBe(75, 25, [0, 128, 0, 255]);
+pixelShouldBe(75, 75, [255, 0, 0, 255]);
+
+// Test rotate
+context.beginPath();
+context.save();
+context.rotate(90/180 * Math.PI);
+context.rect(50, -50, 50, 50);
+context.restore();
+context.fill();
+pixelShouldBe(25, 75, [0, 128, 0, 255]);
+pixelShouldBe(75, 75, [255, 0, 0, 255]);
+
+// Test transform
+context.beginPath();
+context.save();
+context.transform(1, 0, 0, 1, 50, 50);
+context.rect(0, 0, 50, 50);
+context.restore();
+context.fill();
+pixelShouldBe(75, 75, [0, 128, 0, 255]);
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path.js b/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path.js
deleted file mode 100644
index 184c7e28..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore-with-path.js
+++ /dev/null
@@ -1,66 +0,0 @@
-description("This test ensures that paths are correctly handled over save/restore boundaries");
-
-function dataToArray(data) {
-    var result = new Array(data.length)
-    for (var i = 0; i < data.length; i++)
-        result[i] = data[i];
-    return result;
-}
-
-function getPixel(x, y) {
-    var data = context.getImageData(x,y,1,1);
-    if (!data) // getImageData failed, which should never happen
-        return [-1,-1,-1,-1];
-    return dataToArray(data.data);
-}
-
-function pixelShouldBe(x, y, colour) {
-    shouldBe("getPixel(" + [x, y] +")", "["+colour+"]");
-}
-
-var canvas = document.createElement("canvas");
-canvas.width = 100;
-canvas.height = 100;
-
-var context = canvas.getContext("2d");
-context.fillStyle = "red";
-context.fillRect(0,0,100,100);
-context.fillStyle = "green";
-
-// Test translate
-context.beginPath();
-context.save();
-context.translate(100, 100);
-context.rect(-100, -100, 50, 50);
-context.restore();
-context.fill();
-pixelShouldBe(25, 25, [0, 128, 0, 255]);
-
-// Test scale
-context.beginPath();
-context.save();
-context.scale(2, 2);
-context.rect(25, 0,25,25);
-context.restore();
-context.fill();
-pixelShouldBe(75, 25, [0, 128, 0, 255]);
-pixelShouldBe(75, 75, [255, 0, 0, 255]);
-
-// Test rotate
-context.beginPath();
-context.save();
-context.rotate(90/180 * Math.PI);
-context.rect(50, -50, 50, 50);
-context.restore();
-context.fill();
-pixelShouldBe(25, 75, [0, 128, 0, 255]);
-pixelShouldBe(75, 75, [255, 0, 0, 255]);
-
-// Test transform
-context.beginPath();
-context.save();
-context.transform(1, 0, 0, 1, 50, 50);
-context.rect(0, 0, 50, 50);
-context.restore();
-context.fill();
-pixelShouldBe(75, 75, [0, 128, 0, 255]);
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore.html
index 0c9be2d..64686b3 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-save-restore.html
@@ -1,9 +1,163 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
-<script src="script-tests/canvas-save-restore.js"></script>
+<script>
+var canvas = document.createElement("canvas");
+var context = canvas.getContext('2d');
+
+function hex(number)
+{
+    var hexDigits = "0123456789abcdef";
+    return hexDigits[number >> 4] + hexDigits[number & 0xF];
+}
+
+function pixel()
+{
+    var imageData = context.getImageData(0, 0, 1, 1);
+    return "#" + hex(imageData.data[0]) + hex(imageData.data[1]) + hex(imageData.data[2]);
+}
+
+var black="#000000";
+var red = "#ff0000";
+var green = "#008000";
+
+test(function(t) {
+    // (save set restore)
+    context.fillStyle = "black";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.save();
+    context.fillStyle = "red";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    // (save (save set restore) restore)
+    context.fillStyle = "black";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.save();
+    
+    context.save();
+    context.fillStyle = "red";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    // (save (save restore) set restore)
+    context.fillStyle = "black";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.save();
+    context.restore();
+    
+    context.save();
+    context.fillStyle = "red";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    // (save (save (save set restore) set (save set restore) restore) restore)
+    context.fillStyle = "black";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.save();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.save();
+    context.fillStyle = "red";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.fillStyle = "green";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), green);
+    
+    context.save();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), green);
+    
+    context.fillStyle = "red";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), green);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    // (save (save set (save (save set restore) restore) set restore) restore)
+    context.fillStyle = "black";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.save();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.save();
+    context.fillStyle = "red";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.save();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.save();
+    context.fillStyle = "green";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), green);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), red);
+    
+    context.fillStyle = "green";
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), green);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+    
+    context.restore();
+    context.fillRect(0, 0, 1, 1);
+    assert_equals(pixel(), black);
+}, "Verfiy canvas save and restore correct behavior.");
+</script>
 </body>
 </html>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-drawImage-shadow-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-drawImage-shadow-expected.txt
deleted file mode 100644
index b54ef615..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-drawImage-shadow-expected.txt
+++ /dev/null
@@ -1,89 +0,0 @@
-Ensure correct behavior of canvas with drawImage+shadow after scaling. A blue and red checkered pattern should be displayed.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-drawImage-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-drawImage-shadow.html
index f95053c..1e854e20 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-drawImage-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-drawImage-shadow.html
@@ -1,9 +1,125 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
-<script src="script-tests/canvas-scale-drawImage-shadow.js"></script>
+<script>
+async_test(t => {
+    // Create auxiliary canvas to draw to and create an image from.
+    // This is done instead of simply loading an image from the file system
+    // because that would throw a SECURITY_ERR DOM Exception.
+    var aCanvas = document.createElement('canvas');
+    aCanvas.width = aCanvas.height = 10;
+    var aCtx = aCanvas.getContext('2d');
+    aCtx.fillStyle = 'rgba(0, 0, 255, 1)';
+    aCtx.fillRect(0, 0, 50, 50);
+    
+    // Create the image object to be drawn on the master canvas.
+    var img = new Image();
+    img.onload = drawImageToCanvasAndCheckPixels;
+    img.src = aCanvas.toDataURL(); // set a data URI of the base64 encoded image as the source
+    
+    aCanvas.width = 10;
+    aCtx.fillStyle = 'rgba(0, 0, 255, 0.5)';
+    aCtx.fillRect(0, 0, 50, 50);
+    // Create the image object to be drawn on the master canvas.
+    var transparentImg = new Image();
+    transparentImg.onload = drawImageToCanvasAndCheckPixels;
+    transparentImg.src = aCanvas.toDataURL(); // set a data URI of the base64 encoded image as the source
+    
+    // Create master canvas.
+    var canvas = document.createElement('canvas');
+    document.body.appendChild(canvas);
+    canvas.width = 150;
+    canvas.height = 110;
+    var ctx = canvas.getContext('2d');
+    
+    function testPixelShadow(x, y, color)
+    {
+        assert_array_equals(ctx.getImageData(x, y, 1, 1).data, color);
+    }
+    
+    function testPixelShadowAlpha(x, y, color)
+    {
+        var data = ctx.getImageData(x, y, 1, 1).data;
+        assert_array_equals(data.slice(0,3), color.slice(0,3));
+        assert_approx_equals(data[3], color[3], 10);
+    }
+    
+    var testPixelShadowScenarios = [
+        ['Verify solid shadow 1', 40, 40, [255, 0, 0, 255]],
+        ['Verify solid shadow 2', 59, 59, [255, 0, 0, 255]],
+    ];
+    
+    var testPixelShadowAlphaScenarios = [
+        ['Verify solid alpha shadow 1', 41, 81, [255, 0, 0, 76]],
+        ['Verify solid alpha shadow 2', 59, 99, [255, 0, 0, 76]],
+    
+        ['Verify blurry shadow 1', 90, 39, [255, 0, 0, 114]],
+        ['Verify blurry shadow 2', 90, 60, [255, 0, 0, 114]],
+        ['Verify blurry shadow 3', 79, 50, [255, 0, 0, 114]],
+        ['Verify blurry shadow 4', 100, 50, [255, 0, 0, 114]],
+    
+        ['Verify blurry alpha shadow 1', 90, 79, [255, 0, 0, 34]],
+        ['Verify blurry alpha shadow 2', 90, 100, [255, 0, 0, 34]],
+        ['Verify blurry alpha shadow 3', 79, 90, [255, 0, 0, 34]],
+        ['Verify blurry alpha shadow 4', 100, 90, [255, 0, 0, 34]],
+        
+        ['Verify blurry shadow of image with alpha 1', 130, 39, [255, 0, 0, 57]],
+        ['Verify blurry shadow of image with alpha 2', 130, 60, [255, 0, 0, 57]],
+        ['Verify blurry shadow of image with alpha 3', 119, 50, [255, 0, 0, 57]],
+        ['Verify blurry shadow of image with alpha 4', 140, 50, [255, 0, 0, 57]],
+    
+        ['Verify blurry alpha shadow of image with alpha 1', 130, 79, [255, 0, 0, 17]],
+        ['Verify blurry alpha shadow of image with alpha 2', 130, 100, [255, 0, 0, 17]],
+        ['Verify blurry alpha shadow of image with alpha 3', 119, 90, [255, 0, 0, 17]],
+        ['Verify blurry alpha shadow of image with alpha 4', 140, 90, [255, 0, 0, 17]],
+    ];
+    
+    var imagesLoaded = 0;
+    function drawImageToCanvasAndCheckPixels() {
+        imagesLoaded = imagesLoaded + 1;
+        if (imagesLoaded == 2) {
+            ctx.scale(2, 2);
+            ctx.shadowOffsetX = 20;
+            ctx.shadowOffsetY = 20;
+            ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+    
+            ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+            ctx.drawImage(img, 10, 10);
+    
+            ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
+            ctx.drawImage(img, 10, 30);
+    
+            ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+            ctx.shadowBlur = 10;
+            ctx.drawImage(img, 30, 10);
+    
+            ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
+            ctx.drawImage(img, 30, 30);
+    
+            ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+            ctx.drawImage(transparentImg, 50, 10);
+    
+            ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
+            ctx.drawImage(transparentImg, 50, 30);
+            
+            t.step(runTests);
+            t.done();
+    
+        }
+    }
+    
+    function runTests() {
+        for (var i = 0; i < testPixelShadowScenarios.length; i++)
+            testPixelShadow(testPixelShadowScenarios[i][1],
+                            testPixelShadowScenarios[i][2],
+                            testPixelShadowScenarios[i][3]);
+    
+        for (var i = 0; i < testPixelShadowAlphaScenarios.length; i++)
+            testPixelShadowAlpha(testPixelShadowAlphaScenarios[i][1],
+                                 testPixelShadowAlphaScenarios[i][2],
+                                 testPixelShadowAlphaScenarios[i][3]);
+    }
+
+}, 'Ensure correct behavior of canvas with drawImage+shadow after scaling. A blue and red checkered pattern should be displayed.');
+</script>
 </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillPath-shadow-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillPath-shadow-expected.txt
deleted file mode 100644
index 5a9fb84..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillPath-shadow-expected.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-Ensure correct behavior of canvas with path fill + shadow after scaling. A blue and red checkered pattern should be displayed.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 83
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 83
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 53
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 24
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 24
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 24
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillPath-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillPath-shadow.html
index 0da6772..e1d7a5c 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillPath-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillPath-shadow.html
@@ -1,9 +1,86 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
-<script src="script-tests/canvas-scale-fillPath-shadow.js"></script>
+<script>
+// Ensure correct behavior of canvas with path fill + shadow after scaling. A blue and red checkered pattern should be displayed.
+
+var canvas = document.createElement('canvas');
+document.body.appendChild(canvas);
+canvas.setAttribute('width', '1000');
+canvas.setAttribute('height', '1000');
+var ctx = canvas.getContext('2d');
+
+ctx.scale(2, 2);
+ctx.shadowOffsetX = 100;
+ctx.shadowOffsetY = 100;
+ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+ctx.beginPath();
+ctx.moveTo(50, 50);
+ctx.lineTo(100, 50);
+ctx.lineTo(100, 100);
+ctx.lineTo(50, 100);
+ctx.fill();
+
+ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
+ctx.beginPath();
+ctx.moveTo(50, 150);
+ctx.lineTo(100, 150);
+ctx.lineTo(100, 200);
+ctx.lineTo(50, 200);
+ctx.fill();
+
+ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+ctx.shadowBlur = 10;
+ctx.beginPath();
+ctx.moveTo(150, 50);
+ctx.lineTo(200, 50);
+ctx.lineTo(200, 100);
+ctx.lineTo(150, 100);
+ctx.fill();
+
+ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
+ctx.beginPath();
+ctx.moveTo(150, 150);
+ctx.lineTo(200, 150);
+ctx.lineTo(200, 200);
+ctx.lineTo(150, 200);
+ctx.fill();
+
+function testPixelShadow(x, y, color)
+{
+    assert_array_equals(ctx.getImageData(x, y, 1, 1).data, color);
+}
+
+function testPixelShadowAlpha(x, y, color)
+{
+    var data = ctx.getImageData(x, y, 1, 1).data;
+    assert_array_equals(data.slice(0,3), color.slice(0,3));
+    assert_approx_equals(data[3], color[3], 20);
+}
+
+var testPixelShadowScenarios = [
+    ['Verify solid shadow 1', 201, 205, [255, 0, 0, 255]],
+    ['Verify solid shadow 2', 298, 295, [255, 0, 0, 255]],
+    ['Verify solid shadow 3', 201, 298, [255, 0, 0, 255]],
+];
+
+var testPixelShadowAlphaScenarios = [
+    ['Verify solid alpha shadow 1', 201, 405, [255, 0, 0, 76]],
+    ['Verify solid alpha shadow 2', 298, 405, [255, 0, 0, 76]],
+    ['Verify solid alpha shadow 3', 205, 498, [255, 0, 0, 76]],
+
+    ['Verify blurry shadow 1', 398, 205, [255, 0, 0, 83]],
+    ['Verify blurry shadow 2', 501, 205, [255, 0, 0, 83]],
+    ['Verify blurry shadow 3', 500, 300, [255, 0, 0, 53]],
+
+    ['Verify blurry alpha shadow 1', 398, 405, [255, 0, 0, 24]],
+    ['Verify blurry alpha shadow 2', 405, 501, [255, 0, 0, 24]],
+];
+
+generate_tests(testPixelShadow, testPixelShadowScenarios);
+generate_tests(testPixelShadowAlpha, testPixelShadowAlphaScenarios);
+
+</script>
 </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillRect-shadow-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillRect-shadow-expected.txt
deleted file mode 100644
index 94f0a8e2..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillRect-shadow-expected.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-Ensure correct behavior of canvas with fillRect+shadow after scaling. A blue and red checkered pattern should be displayed.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 83
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 83
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 53
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 24
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 24
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 24
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillRect-shadow.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillRect-shadow.html
index eed9534..67afaef7 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillRect-shadow.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-fillRect-shadow.html
@@ -1,9 +1,66 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
-<script src="script-tests/canvas-scale-fillRect-shadow.js"></script>
+<script>
+// Ensure correct behavior of canvas with fillRect+shadow after scaling. A blue and red checkered pattern should be displayed.
+
+var canvas = document.createElement('canvas');
+document.body.appendChild(canvas);
+canvas.setAttribute('width', '1000');
+canvas.setAttribute('height', '1000');
+var ctx = canvas.getContext('2d');
+
+ctx.scale(2, 2);
+ctx.shadowOffsetX = 100;
+ctx.shadowOffsetY = 100;
+ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+ctx.fillRect(50, 50, 50, 50);
+
+ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
+ctx.fillRect(50, 150, 50, 50);
+
+ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+ctx.shadowBlur = 10;
+ctx.fillRect(150, 50, 50, 50);
+
+ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
+ctx.fillRect(150, 150, 50, 50);
+
+function testPixelShadow(x, y, color)
+{
+    assert_array_equals(ctx.getImageData(x, y, 1, 1).data, color);
+}
+
+function testPixelShadowAlpha(x, y, color)
+{
+    var data = ctx.getImageData(x, y, 1, 1).data;
+    assert_array_equals(data.slice(0,3), color.slice(0,3));
+    assert_approx_equals(data[3], color[3], 20);
+}
+
+var testPixelShadowScenarios = [
+    ['Verify solid shadow 1', 201, 205, [255, 0, 0, 255]],
+    ['Verify solid shadow 2', 298, 298, [255, 0, 0, 255]],
+    ['Verify solid shadow 3', 201, 298, [255, 0, 0, 255]],
+];
+
+var testPixelShadowAlphaScenarios = [
+    ['Verify solid alpha shadow 1', 201, 405, [255, 0, 0, 76]],
+    ['Verify solid alpha shadow 2', 298, 405, [255, 0, 0, 76]],
+    ['Verify solid alpha shadow 3', 205, 498, [255, 0, 0, 76]],
+
+    ['Verify blurry shadow 1', 398, 205, [255, 0, 0, 83]],
+    ['Verify blurry shadow 2', 501, 205, [255, 0, 0, 83]],
+    ['Verify blurry shadow 3', 500, 300, [255, 0, 0, 53]],
+
+    ['Verify blurry alpha shadow 1', 398, 405, [255, 0, 0, 24]],
+    ['Verify blurry alpha shadow 2', 405, 501, [255, 0, 0, 24]],
+];
+
+generate_tests(testPixelShadow, testPixelShadowScenarios);
+generate_tests(testPixelShadowAlpha, testPixelShadowAlphaScenarios);
+
+</script>
 </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-shadowBlur-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-shadowBlur-expected.txt
deleted file mode 100644
index a2bb3a9..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-shadowBlur-expected.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-Ensure that canvas shadowBlur is not affected by transformations.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 255
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 126
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 255
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 126
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-shadowBlur.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-shadowBlur.html
index 7af0f50b..6dba9da 100644
--- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-shadowBlur.html
+++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-scale-shadowBlur.html
@@ -1,9 +1,82 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<script src="../../resources/js-test.js"></script>
-</head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
 <body>
-<script src="script-tests/canvas-scale-shadowBlur.js"></script>
+<script>
+// Ensure that canvas shadowBlur is not affected by transformations.
+
+var canvas = document.createElement('canvas');
+document.body.appendChild(canvas);
+canvas.setAttribute('width', '600');
+canvas.setAttribute('height', '600');
+var ctx = canvas.getContext('2d');
+
+ctx.shadowBlur = 25;
+ctx.shadowOffsetX = 100;
+ctx.shadowOffsetY = 100;
+ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+// top left
+ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+ctx.scale(4, 4);
+ctx.rotate(Math.PI/2);
+ctx.translate(25, -50);
+ctx.fillRect(0, 0, 25, 25);
+
+// bottom left
+ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
+ctx.setTransform(1, 0, 0, 1, 0, 0);
+ctx.scale(0.5, 0.5);
+ctx.fillRect(200, 600, 200, 200);
+
+// top right
+ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
+ctx.scale(2, 2);
+ctx.fillRect(300, 100, 100, 100);
+
+// bottom right
+ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
+ctx.fillRect(300, 300, 100, 100);
+
+function testPixelShadowBlur(x, y, color)
+{
+    if (color.length == 4) {
+        assert_array_equals(ctx.getImageData(x, y, 1, 1).data, color);
+    } else {    // we expect to have [r, g, b, a, alphaApprox]
+        var data = ctx.getImageData(x, y, 1, 1).data;
+        assert_array_equals(data.slice(0,3), color.slice(0,3));
+        assert_approx_equals(data[3], color[3], color[4]);
+    }
+}
+
+var testPixelShadowBlurScenarios = [
+    ['Verify top left 1', 250, 250, [255, 0, 0, 255]],
+    ['Verify top left 2', 250, 175, [0, 0, 0, 0]],
+    ['Verify top left 3', 250, 325, [0, 0, 0, 0]],
+    ['Verify top left 4', 175, 250, [0, 0, 0, 0]],
+    ['Verify top left 5', 325, 250, [0, 0, 0, 0]],
+
+    ['Verify bottom left 1', 250, 450, [255, 0, 0, 126, 20]],
+    ['Verify bottom left 2', 250, 375, [0, 0, 0, 0]],
+    ['Verify bottom left 3', 250, 525, [0, 0, 0, 0]],
+    ['Verify bottom left 4', 175, 450, [0, 0, 0, 0]],
+    ['Verify bottom left 5', 325, 450, [0, 0, 0, 0]],
+    ['Verify bottom left 6', 250, 250, [255, 0, 0, 255, 20]],
+
+    ['Verify top right 1', 450, 250, [255, 0, 0, 255, 20]],
+    ['Verify top right 2', 450, 175, [0, 0, 0, 0]],
+    ['Verify top right 3', 450, 325, [0, 0, 0, 0]],
+    ['Verify top right 4', 375, 250, [0, 0, 0, 0]],
+    ['Verify top right 5', 525, 250, [0, 0, 0, 0]],
+    
+    ['Verify bottom right 1', 450, 450, [255, 0, 0, 126, 20]],
+    ['Verify bottom right 2', 450, 375, [0, 0, 0, 0]],
+    ['Verify bottom right 3', 450, 525, [0, 0, 0, 0]],
+    ['Verify bottom right 2', 375, 450, [0, 0, 0, 0]],
+    ['Verify bottom right 2', 525, 450, [0, 0, 0, 0]],
+    
+];
+
+generate_tests(testPixelShadowBlur, testPixelShadowBlurScenarios);
+
+</script>
 </body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-resetTransform.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-resetTransform.js
deleted file mode 100644
index 05cbe575..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-resetTransform.js
+++ /dev/null
@@ -1,117 +0,0 @@
-description("This test checks resetTransform in canvas v5");
-
-var canvas = document.createElement('canvas');
-document.body.appendChild(canvas);
-canvas.setAttribute('width', '100');
-canvas.setAttribute('height', '100');
-var ctx = canvas.getContext('2d');
-
-debug("resetTransform should reset other transforms.");
-ctx.save();
-ctx.scale(0.5, 0.5);
-ctx.resetTransform();
-ctx.fillStyle = 'green';
-ctx.fillRect(0, 0, 100, 100);
-ctx.restore();
-
-var imageData = ctx.getImageData(98, 98, 1, 1);
-var imgdata = imageData.data;
-shouldBe("imgdata[0]", "0");
-shouldBe("imgdata[1]", "128");
-shouldBe("imgdata[2]", "0");
-
-debug("resetTransform should not affect CTM outside of save() and restore().");
-ctx.save();
-ctx.scale(0.5, 0.5);
-ctx.save();
-ctx.resetTransform();
-ctx.fillStyle = 'green';
-ctx.fillRect(0, 0, 100, 100);
-ctx.restore();
-ctx.fillStyle = 'red';
-ctx.fillRect(0, 0, 100, 100);
-ctx.restore();
-
-imageData = ctx.getImageData(98, 98, 1, 1);
-imgdata = imageData.data;
-shouldBe("imgdata[0]", "0");
-shouldBe("imgdata[1]", "128");
-shouldBe("imgdata[2]", "0");
-
-imageData = ctx.getImageData(48, 48, 1, 1);
-imgdata = imageData.data;
-shouldBe("imgdata[0]", "255");
-shouldBe("imgdata[1]", "0");
-shouldBe("imgdata[2]", "0");
-
-debug("resetTransform should restore the path transform to identity.");
-/* This should draw a green rectangle on on top of a red one. The red should not be visible. */
-ctx.save();
-ctx.beginPath();
-ctx.moveTo(0, 0);
-ctx.lineTo(100, 0);
-ctx.lineTo(100, 100);
-ctx.lineTo(0, 100);
-ctx.fillStyle = 'red';
-ctx.fill();
-ctx.translate(200, 0);
-ctx.resetTransform();
-ctx.fillStyle = 'green';
-ctx.fill();
-ctx.restore();
-
-imageData = ctx.getImageData(50, 50, 1, 1);
-imgdata = imageData.data;
-shouldBe("imgdata[0]", "0");
-shouldBe("imgdata[1]", "128");
-shouldBe("imgdata[2]", "0");
-
-debug("resetTransform should resolve the non-invertible CTM state.");
-ctx.save();
-ctx.fillStyle = 'red';
-ctx.fillRect(0, 0, 100, 100);
-ctx.beginPath();
-ctx.moveTo(0, 0);
-ctx.lineTo(100, 0);
-ctx.lineTo(100, 100);
-ctx.lineTo(0, 100);
-ctx.scale(0, 0);
-ctx.resetTransform();
-ctx.fillStyle = 'green';
-ctx.fill();
-ctx.restore();
-
-imageData = ctx.getImageData(98, 98, 1, 1);
-imgdata = imageData.data;
-shouldBe("imgdata[0]", "0");
-shouldBe("imgdata[1]", "128");
-shouldBe("imgdata[2]", "0");
-
-debug("The path object should not be updated on the non-invertible CTM state.");
-debug("resetTransform should restore the path object just before CTM became non-invertible.");
-ctx.save();
-ctx.fillStyle = 'red';
-ctx.fillRect(0, 0, 100, 100);
-ctx.beginPath();
-ctx.moveTo(0, 0);
-ctx.lineTo(100, 0);
-ctx.lineTo(100, 50);
-ctx.scale(0, 0);
-ctx.lineTo(100, 100);
-ctx.resetTransform();
-ctx.lineTo(0, 100);
-ctx.fillStyle = 'green';
-ctx.fill();
-ctx.restore();
-
-imageData = ctx.getImageData(98, 98, 1, 1);
-imgdata = imageData.data;
-shouldBe("imgdata[0]", "255");
-shouldBe("imgdata[1]", "0");
-shouldBe("imgdata[2]", "0");
-
-imageData = ctx.getImageData(98, 48, 1, 1);
-imgdata = imageData.data;
-shouldBe("imgdata[0]", "0");
-shouldBe("imgdata[1]", "128");
-shouldBe("imgdata[2]", "0");
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-save-restore.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-save-restore.js
deleted file mode 100644
index cd68a5a9..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-save-restore.js
+++ /dev/null
@@ -1,161 +0,0 @@
-description("Test of save and restore on canvas graphics context.");
-
-var canvas = document.createElement("canvas");
-var context = canvas.getContext('2d');
-
-function hex(number)
-{
-    var hexDigits = "0123456789abcdef";
-    return hexDigits[number >> 4] + hexDigits[number & 0xF];
-}
-
-function pixel()
-{
-    var imageData = context.getImageData(0, 0, 1, 1);
-    return "#" + hex(imageData.data[0]) + hex(imageData.data[1]) + hex(imageData.data[2]);
-}
-
-var black="#000000";
-var red = "#ff0000";
-var green = "#008000";
-
-// (save set restore)
-context.fillStyle = "black";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.save();
-context.fillStyle = "red";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-
-// (save (save set restore) restore)
-context.fillStyle = "black";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.save();
-
-context.save();
-context.fillStyle = "red";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-
-// (save (save restore) set restore)
-context.fillStyle = "black";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.save();
-context.restore();
-
-context.save();
-context.fillStyle = "red";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-
-// (save (save (save set restore) set (save set restore) restore) restore)
-context.fillStyle = "black";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.save();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.save();
-context.fillStyle = "red";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.fillStyle = "green";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "green");
-
-context.save();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "green");
-
-context.fillStyle = "red";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "green");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-
-// (save (save set (save (save set restore) restore) set restore) restore)
-context.fillStyle = "black";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.save();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.save();
-context.fillStyle = "red";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.save();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.save();
-context.fillStyle = "green";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "green");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "red");
-
-context.fillStyle = "green";
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "green");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
-context.restore();
-context.fillRect(0, 0, 1, 1);
-shouldBe("pixel()", "black");
-
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-drawImage-shadow.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-drawImage-shadow.js
deleted file mode 100644
index e713688..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-drawImage-shadow.js
+++ /dev/null
@@ -1,224 +0,0 @@
-description("Ensure correct behavior of canvas with drawImage+shadow after scaling. A blue and red checkered pattern should be displayed.");
-
-function print(message, color)
-{
-    var paragraph = document.createElement("div");
-    paragraph.appendChild(document.createTextNode(message));
-    paragraph.style.fontFamily = "monospace";
-    if (color)
-        paragraph.style.color = color;
-    document.getElementById("console").appendChild(paragraph);
-}
-
-function shouldBeAround(a, b)
-{
-    var evalA;
-    try {
-        evalA = eval(a);
-    } catch(e) {
-        evalA = e;
-    }
-
-    if (Math.abs(evalA - b) < 10)
-        print("PASS " + a + " is around " + b , "green")
-    else
-        print("FAIL " + a + " is not around " + b + " (actual: " + evalA + ")", "red");
-}
-
-// Create auxiliary canvas to draw to and create an image from.
-// This is done instead of simply loading an image from the file system
-// because that would throw a SECURITY_ERR DOM Exception.
-var aCanvas = document.createElement('canvas');
-aCanvas.width = 10;
-aCanvas.height = 10;
-aCanvas.setAttribute('height', '10');
-var aCtx = aCanvas.getContext('2d');
-aCtx.fillStyle = 'rgba(0, 0, 255, 1)';
-aCtx.fillRect(0, 0, 50, 50);
-
-// Create the image object to be drawn on the master canvas.
-var img = new Image();
-img.onload = drawImageToCanvasAndCheckPixels;
-img.src = aCanvas.toDataURL(); // set a data URI of the base64 encoded image as the source
-
-aCanvas.width = 10;
-aCtx.fillStyle = 'rgba(0, 0, 255, 0.5)';
-aCtx.fillRect(0, 0, 50, 50);
-// Create the image object to be drawn on the master canvas.
-var transparentImg = new Image();
-transparentImg.onload = drawImageToCanvasAndCheckPixels;
-transparentImg.src = aCanvas.toDataURL(); // set a data URI of the base64 encoded image as the source
-
-// Create master canvas.
-var canvas = document.createElement('canvas');
-document.body.appendChild(canvas);
-canvas.setAttribute('width', '150');
-canvas.setAttribute('height', '110');
-var ctx = canvas.getContext('2d');
-
-var imagesLoaded = 0;
-
-function drawImageToCanvasAndCheckPixels() {
-    imagesLoaded = imagesLoaded + 1;
-    if (imagesLoaded == 2) {
-        ctx.scale(2, 2);
-        ctx.shadowOffsetX = 20;
-        ctx.shadowOffsetY = 20;
-        ctx.fillStyle = 'rgba(0, 0, 255, 1)';
-
-        ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-        ctx.drawImage(img, 10, 10);
-
-        ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
-        ctx.drawImage(img, 10, 30);
-
-        ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-        ctx.shadowBlur = 10;
-        ctx.drawImage(img, 30, 10);
-
-        ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
-        ctx.drawImage(img, 30, 30);
-
-        ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-        ctx.drawImage(transparentImg, 50, 10);
-
-        ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
-        ctx.drawImage(transparentImg, 50, 30);
-
-        checkPixels();
-    }
-}
-
-var d; // imageData.data
-
-function checkPixels() {
-
-    // Verify solid shadow.
-    d = ctx.getImageData(40, 40, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBe('d[3]', '255');
-
-    d = ctx.getImageData(59, 59, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBe('d[3]', '255');
-
-    // Verify solid alpha shadow.
-    d = ctx.getImageData(41, 81, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '76');
-
-    d = ctx.getImageData(59, 99, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '76');
-
-    // Verify blurry shadow.
-    d = ctx.getImageData(90, 39, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '114');
-
-    d = ctx.getImageData(90, 60, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '114');
-
-    d = ctx.getImageData(79, 50, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '114');
-
-    d = ctx.getImageData(100, 50, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '114');
-
-    // Verify blurry alpha shadow.
-    d = ctx.getImageData(90, 79, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '34');
-
-    d = ctx.getImageData(90, 100, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '34');
-
-    d = ctx.getImageData(79, 90, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '34');
-
-    d = ctx.getImageData(100, 90, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '34');
-
-    // Verify blurry shadow of image with alpha
-    d = ctx.getImageData(130, 39, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '57');
-
-    d = ctx.getImageData(130, 60, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '57');
-
-    d = ctx.getImageData(119, 50, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '57');
-
-    d = ctx.getImageData(140, 50, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '57');
-
-    // Verify blurry alpha shadow of image with alpha.
-    d = ctx.getImageData(130, 79, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '17');
-
-    d = ctx.getImageData(130, 100, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '17');
-
-    d = ctx.getImageData(119, 90, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '17');
-
-    d = ctx.getImageData(140, 90, 1, 1).data;
-    shouldBe('d[0]', '255');
-    shouldBe('d[1]', '0');
-    shouldBe('d[2]', '0');
-    shouldBeAround('d[3]', '17');
-    finishJSTest();
-}
-
-window.jsTestIsAsync = true;
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-fillPath-shadow.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-fillPath-shadow.js
deleted file mode 100644
index 98675134..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-fillPath-shadow.js
+++ /dev/null
@@ -1,148 +0,0 @@
-description("Ensure correct behavior of canvas with path fill + shadow after scaling. A blue and red checkered pattern should be displayed.");
-
-function print(message, color)
-{
-    var paragraph = document.createElement("div");
-    paragraph.appendChild(document.createTextNode(message));
-    paragraph.style.fontFamily = "monospace";
-    if (color)
-        paragraph.style.color = color;
-    document.getElementById("console").appendChild(paragraph);
-}
-
-function shouldBeAround(a, b)
-{
-    var evalA;
-    try {
-        evalA = eval(a);
-    } catch(e) {
-        evalA = e;
-    }
-
-    if (Math.abs(evalA - b) < 20)
-        print("PASS " + a + " is around " + b , "green")
-    else
-        print("FAIL " + a + " is not around " + b + " (actual: " + evalA + ")", "red");
-}
-
-var canvas = document.createElement('canvas');
-document.body.appendChild(canvas);
-canvas.setAttribute('width', '1000');
-canvas.setAttribute('height', '1000');
-var ctx = canvas.getContext('2d');
-
-ctx.scale(2, 2);
-ctx.shadowOffsetX = 100;
-ctx.shadowOffsetY = 100;
-ctx.fillStyle = 'rgba(0, 0, 255, 1)';
-
-ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-ctx.beginPath();
-ctx.moveTo(50, 50);
-ctx.lineTo(100, 50);
-ctx.lineTo(100, 100);
-ctx.lineTo(50, 100);
-ctx.fill();
-
-ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
-ctx.beginPath();
-ctx.moveTo(50, 150);
-ctx.lineTo(100, 150);
-ctx.lineTo(100, 200);
-ctx.lineTo(50, 200);
-ctx.fill();
-
-ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-ctx.shadowBlur = 10;
-ctx.beginPath();
-ctx.moveTo(150, 50);
-ctx.lineTo(200, 50);
-ctx.lineTo(200, 100);
-ctx.lineTo(150, 100);
-ctx.fill();
-
-ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
-ctx.beginPath();
-ctx.moveTo(150, 150);
-ctx.lineTo(200, 150);
-ctx.lineTo(200, 200);
-ctx.lineTo(150, 200);
-ctx.fill();
-
-var d; // imageData.data
-
-// Verify solid shadow.
-d = ctx.getImageData(201, 205, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '255');
-
-d = ctx.getImageData(298, 295, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '255');
-
-d = ctx.getImageData(201, 298, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '255');
-
-// Verify solid alpha shadow.
-d = ctx.getImageData(201, 405, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '76');
-
-d = ctx.getImageData(298, 405, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '76');
-
-d = ctx.getImageData(205, 498, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '76');
-
-// Verify blurry shadow.
-d = ctx.getImageData(398, 205, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '83');
-
-d = ctx.getImageData(501, 205, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '83');
-
-d = ctx.getImageData(500, 300, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '53');
-
-// Verify blurry alpha shadow.
-d = ctx.getImageData(398, 405, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '24');
-
-d = ctx.getImageData(405, 501, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '24');
-
-d = ctx.getImageData(405, 501, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '24');
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-fillRect-shadow.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-fillRect-shadow.js
deleted file mode 100644
index 8fdc17ef..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-fillRect-shadow.js
+++ /dev/null
@@ -1,128 +0,0 @@
-description("Ensure correct behavior of canvas with fillRect+shadow after scaling. A blue and red checkered pattern should be displayed.");
-
-function print(message, color)
-{
-    var paragraph = document.createElement("div");
-    paragraph.appendChild(document.createTextNode(message));
-    paragraph.style.fontFamily = "monospace";
-    if (color)
-        paragraph.style.color = color;
-    document.getElementById("console").appendChild(paragraph);
-}
-
-function shouldBeAround(a, b)
-{
-    var evalA;
-    try {
-        evalA = eval(a);
-    } catch(e) {
-        evalA = e;
-    }
-
-    if (Math.abs(evalA - b) < 20)
-        print("PASS " + a + " is around " + b , "green")
-    else
-        print("FAIL " + a + " is not around " + b + " (actual: " + evalA + ")", "red");
-}
-
-var canvas = document.createElement('canvas');
-document.body.appendChild(canvas);
-canvas.setAttribute('width', '1000');
-canvas.setAttribute('height', '1000');
-var ctx = canvas.getContext('2d');
-
-ctx.scale(2, 2);
-ctx.shadowOffsetX = 100;
-ctx.shadowOffsetY = 100;
-ctx.fillStyle = 'rgba(0, 0, 255, 1)';
-
-ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-ctx.fillRect(50, 50, 50, 50);
-
-ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
-ctx.fillRect(50, 150, 50, 50);
-
-ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-ctx.shadowBlur = 10;
-ctx.fillRect(150, 50, 50, 50);
-
-ctx.shadowColor = 'rgba(255, 0, 0, 0.3)';
-ctx.fillRect(150, 150, 50, 50);
-
-var d; // imageData.data
-
-// Verify solid shadow.
-d = ctx.getImageData(201, 205, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '255');
-
-d = ctx.getImageData(298, 298, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '255');
-
-d = ctx.getImageData(201, 298, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '255');
-
-// Verify solid alpha shadow.
-d = ctx.getImageData(201, 405, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '76');
-
-d = ctx.getImageData(298, 405, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '76');
-
-d = ctx.getImageData(205, 498, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '76');
-
-// Verify blurry shadow.
-d = ctx.getImageData(398, 205, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '83');
-
-d = ctx.getImageData(501, 205, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '83');
-
-d = ctx.getImageData(500, 300, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '53');
-
-// Verify blurry alpha shadow.
-d = ctx.getImageData(398, 405, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '24');
-
-d = ctx.getImageData(405, 501, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '24');
-
-d = ctx.getImageData(405, 501, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '24');
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-shadowBlur.js b/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-shadowBlur.js
deleted file mode 100644
index 6fdb73f..0000000
--- a/third_party/WebKit/LayoutTests/fast/canvas/script-tests/canvas-scale-shadowBlur.js
+++ /dev/null
@@ -1,191 +0,0 @@
-description("Ensure that canvas shadowBlur is not affected by transformations.");
-
-function print(message, color)
-{
-    var paragraph = document.createElement("div");
-    paragraph.appendChild(document.createTextNode(message));
-    paragraph.style.fontFamily = "monospace";
-    if (color)
-        paragraph.style.color = color;
-    document.getElementById("console").appendChild(paragraph);
-}
-
-function shouldBeAround(a, b)
-{
-    var evalA;
-    try {
-        evalA = eval(a);
-    } catch(e) {
-        evalA = e;
-    }
-
-    if (Math.abs(evalA - b) < 10)
-        print("PASS " + a + " is around " + b , "green")
-    else
-        print("FAIL " + a + " is not around " + b + " (actual: " + evalA + ")", "red");
-}
-
-var canvas = document.createElement('canvas');
-document.body.appendChild(canvas);
-canvas.setAttribute('width', '600');
-canvas.setAttribute('height', '600');
-var ctx = canvas.getContext('2d');
-
-ctx.shadowBlur = 25;
-ctx.shadowOffsetX = 100;
-ctx.shadowOffsetY = 100;
-ctx.fillStyle = 'rgba(0, 0, 255, 1)';
-
-// top left
-ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-ctx.scale(4, 4);
-ctx.rotate(Math.PI/2);
-ctx.translate(25, -50);
-ctx.fillRect(0, 0, 25, 25);
-
-// bottom left
-ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
-ctx.setTransform(1, 0, 0, 1, 0, 0);
-ctx.scale(0.5, 0.5);
-ctx.fillRect(200, 600, 200, 200);
-
-// top right
-ctx.shadowColor = 'rgba(255, 0, 0, 1.0)';
-ctx.scale(2, 2);
-ctx.fillRect(300, 100, 100, 100);
-
-// bottom right
-ctx.shadowColor = 'rgba(255, 0, 0, 0.5)';
-ctx.fillRect(300, 300, 100, 100);
-
-var d;
-
-// top left
-d = ctx.getImageData(250, 250, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '255');
-
-d = ctx.getImageData(250, 175, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(250, 325, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(175, 250, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(325, 250, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-// bottom left
-d = ctx.getImageData(250, 450, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '126');
-
-d = ctx.getImageData(250, 375, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(250, 525, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(175, 450, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(325, 450, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(250, 250, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '255');
-
-// top right
-d = ctx.getImageData(450, 250, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '255');
-
-d = ctx.getImageData(450, 175, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(450, 325, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(375, 250, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(525, 250, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-// top right
-d = ctx.getImageData(450, 450, 1, 1).data;
-shouldBe('d[0]', '255');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBeAround('d[3]', '126');
-
-d = ctx.getImageData(450, 375, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(450, 525, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(375, 450, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
-
-d = ctx.getImageData(525, 450, 1, 1).data;
-shouldBe('d[0]', '0');
-shouldBe('d[1]', '0');
-shouldBe('d[2]', '0');
-shouldBe('d[3]', '0');
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-resetTransform-expected.txt b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-resetTransform-expected.txt
deleted file mode 100644
index 800c5b3..0000000
--- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-resetTransform-expected.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-This test checks resetTransform in canvas v5
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-resetTransform should reset other transforms.
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-resetTransform should not affect CTM outside of save() and restore().
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-PASS imgdata[0] is 255
-PASS imgdata[1] is 0
-PASS imgdata[2] is 0
-resetTransform should restore the path transform to identity.
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-resetTransform should resolve the non-invertible CTM state.
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-The path object should not be updated on the non-invertible CTM state.
-resetTransform should restore the path object just before CTM became non-invertible.
-PASS imgdata[0] is 255
-PASS imgdata[1] is 0
-PASS imgdata[2] is 0
-PASS imgdata[0] is 0
-PASS imgdata[1] is 128
-PASS imgdata[2] is 0
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-scale-drawImage-shadow-expected.txt b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-scale-drawImage-shadow-expected.txt
deleted file mode 100644
index b54ef615..0000000
--- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-scale-drawImage-shadow-expected.txt
+++ /dev/null
@@ -1,89 +0,0 @@
-Ensure correct behavior of canvas with drawImage+shadow after scaling. A blue and red checkered pattern should be displayed.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 76
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 114
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 34
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 57
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 17
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-scale-shadowBlur-expected.txt b/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-scale-shadowBlur-expected.txt
deleted file mode 100644
index a2bb3a9..0000000
--- a/third_party/WebKit/LayoutTests/virtual/gpu/fast/canvas/canvas-scale-shadowBlur-expected.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-Ensure that canvas shadowBlur is not affected by transformations.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 255
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 126
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 255
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 255
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 255
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is around 126
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS d[0] is 0
-PASS d[1] is 0
-PASS d[2] is 0
-PASS d[3] is 0
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index ca8983f..17b2c4a 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -306,9 +306,6 @@
   DCHECK(m_requestedToStart);
 
   {
-    // Prevent the deadlock between GC and an attempt to terminate a thread.
-    SafePointScope safePointScope(BlinkGC::HeapPointersOnStack);
-
     // Protect against this method, initializeOnWorkerThread() or
     // termination via the global scope racing each other.
     MutexLocker lock(m_threadStateMutex);
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
index 1965213..45b233b 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/optimize_png.hashes
@@ -5,9 +5,9 @@
     "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a",
     "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45",
     "smallIcons.svg": "044ba42204fd8ae030835e2ca78433bf",
-    "toolbarButtonGlyphs.svg": "fa5911823785a90273dfea76fe4ce512",
+    "toolbarButtonGlyphs.svg": "3db0c30256dd19d51b088f6855052030",
     "breakpoint.svg": "69cd92d807259c022791112809b97799",
     "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9",
     "audits_logo_bw.svg": "203dcb2ba32ef0f4595ad45bb8feffab",
     "audits_logo.svg": "647095d7981857c22a816eef12f75b91"
-}
\ No newline at end of file
+}
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
index 1965213..1eecefc 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/svg2png.hashes
@@ -5,7 +5,7 @@
     "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a",
     "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45",
     "smallIcons.svg": "044ba42204fd8ae030835e2ca78433bf",
-    "toolbarButtonGlyphs.svg": "fa5911823785a90273dfea76fe4ce512",
+    "toolbarButtonGlyphs.svg": "3db0c30256dd19d51b088f6855052030",
     "breakpoint.svg": "69cd92d807259c022791112809b97799",
     "treeoutlineTriangles.svg": "017d2f89437df0afc6b9cd5ff43735d9",
     "audits_logo_bw.svg": "203dcb2ba32ef0f4595ad45bb8feffab",
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg b/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg
index c07f8f8d..c0a3f4d 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg
+++ b/third_party/WebKit/Source/devtools/front_end/Images/src/toolbarButtonGlyphs.svg
@@ -9,23 +9,23 @@
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   height="168"
+   height="192"
    version="1.1"
    width="352"
    xml:space="preserve"
    id="svg3395"
-   inkscape:version="0.92.0 r"
+   inkscape:version="0.48.4 r9939"
    sodipodi:docname="toolbarButtonGlyphs.svg"><metadata
      id="metadata3773"><rdf:RDF><cc:Work
          rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
      showgrid="true"
      id="namedview3397"
-     inkscape:zoom="2.8284271"
-     inkscape:cx="196.27229"
-     inkscape:cy="85.656284"
-     inkscape:window-width="1278"
-     inkscape:window-height="746"
+     inkscape:zoom="11.313708"
+     inkscape:cx="83.592365"
+     inkscape:cy="12.060079"
+     inkscape:window-width="1941"
+     inkscape:window-height="1436"
      inkscape:window-x="0"
      inkscape:window-y="0"
      inkscape:window-maximized="0"
@@ -621,7 +621,7 @@
        style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
      id="g2488"><path
        transform="matrix(0.36,0,0,0.36,125.49998,127.46)"
-       d="m 53,14 a 3,3 0 1 1 -6,0 3,3 0 1 1 6,0 z"
+       d="m 53,14 c 0,1.656854 -1.343146,3 -3,3 -1.656854,0 -3,-1.343146 -3,-3 0,-1.656854 1.343146,-3 3,-3 1.656854,0 3,1.343146 3,3 z"
        sodipodi:ry="3"
        sodipodi:rx="3"
        sodipodi:cy="14"
@@ -658,11 +658,7 @@
      id="g2472"><path
        id="path3509-0"
        d="m 240.76701,127 -1.53402,0 0,4.23299 -4.23299,0 0,1.53402 4.23299,0 0,4.23299 1.53402,0 0,-4.23299 4.23299,0 0,-1.53402 -4.23299,0 0,-4.23299 z"
-       inkscape:connector-curvature="0" /></g><path
-     style="fill:none"
-     inkscape:connector-curvature="0"
-     d="m 228.56466,156.76923 h 48 v 48 h -48 z"
-     id="path3712" /><g
+       inkscape:connector-curvature="0" /></g><g
      id="g2462"><path
        id="path3714"
        d="m 310.7696,127.0439 -1.81599,-1.81636 c -0.30331,-0.30338 -0.79716,-0.30338 -1.10048,0 l -2.43038,2.43089 -1.48935,-1.49354 -1.10047,1.1007 1.10437,1.1046 L 297,135.30504 V 139 h 3.69419 l 6.9373,-6.93874 1.10048,1.1046 1.10048,-1.10072 -1.49324,-1.49353 2.43039,-2.43089 c 0.3072,-0.30338 0.3072,-0.79345 0,-1.09682 z m -10.72092,10.40033 -1.49324,-1.49354 6.27235,-6.27365 1.49323,1.49354 -6.27234,6.27365 z"
@@ -724,7 +720,7 @@
      style="fill:none" /><g
      id="g2256"><path
        transform="matrix(1.4142135,0,0,1.4142135,-86.874996,-12.771743)"
-       d="m 209.92234,31.304852 a 1.0606602,1.0606602 0 1 1 -2.12132,0 1.0606602,1.0606602 0 1 1 2.12132,0 z"
+       d="m 209.92234,31.304852 c 0,0.585786 -0.47487,1.06066 -1.06066,1.06066 -0.58579,0 -1.06066,-0.474874 -1.06066,-1.06066 0,-0.585787 0.47487,-1.060661 1.06066,-1.060661 0.58579,0 1.06066,0.474874 1.06066,1.060661 z"
        sodipodi:ry="1.0606602"
        sodipodi:rx="1.0606602"
        sodipodi:cy="31.304852"
@@ -739,10 +735,10 @@
        sodipodi:cy="31.304852"
        sodipodi:rx="1.0606602"
        sodipodi:ry="1.0606602"
-       d="m 209.92234,31.304852 a 1.0606602,1.0606602 0 1 1 -2.12132,0 1.0606602,1.0606602 0 1 1 2.12132,0 z"
+       d="m 209.92234,31.304852 c 0,0.585786 -0.47487,1.06066 -1.06066,1.06066 -0.58579,0 -1.06066,-0.474874 -1.06066,-1.06066 0,-0.585787 0.47487,-1.060661 1.06066,-1.060661 0.58579,0 1.06066,0.474874 1.06066,1.060661 z"
        transform="matrix(1.4142135,0,0,1.4142135,-86.874986,-7.771742)" /><path
        transform="matrix(1.4142135,0,0,1.4142135,-86.874986,-2.771743)"
-       d="m 209.92234,31.304852 a 1.0606602,1.0606602 0 1 1 -2.12132,0 1.0606602,1.0606602 0 1 1 2.12132,0 z"
+       d="m 209.92234,31.304852 c 0,0.585786 -0.47487,1.06066 -1.06066,1.06066 -0.58579,0 -1.06066,-0.474874 -1.06066,-1.06066 0,-0.585787 0.47487,-1.060661 1.06066,-1.060661 0.58579,0 1.06066,0.474874 1.06066,1.060661 z"
        sodipodi:ry="1.0606602"
        sodipodi:rx="1.0606602"
        sodipodi:cy="31.304852"
@@ -752,27 +748,36 @@
        sodipodi:type="arc" /></g><g
      id="g2378"><path
        id="path3288"
-       d="m 23,157 -2,0 0,2 2,0 z" /><path
+       d="m 23,157 -2,0 0,2 2,0 z"
+       inkscape:connector-curvature="0" /><path
        id="path3286"
-       d="m 23,161 -2,0 0,2 c 1,0 2,-1 2,-2 z" /><path
+       d="m 23,161 -2,0 0,2 c 1,0 2,-1 2,-2 z"
+       inkscape:connector-curvature="0" /><path
        id="path3284"
-       d="m 23,153 -2,0 0,2 2,0 z" /><path
+       d="m 23,153 -2,0 0,2 2,0 z"
+       inkscape:connector-curvature="0" /><path
        id="path3282"
-       d="m 21,149 0,2 2,0 c 0,-1 -1,-2 -2,-2 z" /><path
+       d="m 21,149 0,2 2,0 c 0,-1 -1,-2 -2,-2 z"
+       inkscape:connector-curvature="0" /><path
        sodipodi:nodetypes="scccss"
        inkscape:connector-curvature="0"
        id="path3280"
        d="m 11,163 4,0 0,-6 -6,0 0,4 c 0,1.1 0.9,2 2,2 z" /><path
        id="path3278"
-       d="m 11,153 -2,0 0,2 2,0 z" /><path
+       d="m 11,153 -2,0 0,2 2,0 z"
+       inkscape:connector-curvature="0" /><path
        id="path3276"
-       d="m 19,149 -2,0 0,2 2,0 z" /><path
+       d="m 19,149 -2,0 0,2 2,0 z"
+       inkscape:connector-curvature="0" /><path
        id="path3274"
-       d="m 19,161 -2,0 0,2 2,0 z" /><path
+       d="m 19,161 -2,0 0,2 2,0 z"
+       inkscape:connector-curvature="0" /><path
        id="path3272"
-       d="m 11,149 c -1,0 -2,1 -2,2 l 2,0 z" /><path
+       d="m 11,149 c -1,0 -2,1 -2,2 l 2,0 z"
+       inkscape:connector-curvature="0" /><path
        id="path3231"
-       d="m 15,149 -2,0 0,2 2,0 z" /></g><g
+       d="m 15,149 -2,0 0,2 2,0 z"
+       inkscape:connector-curvature="0" /></g><g
      id="g2383"><g
        id="g4042"><path
          sodipodi:type="arc"
@@ -782,7 +787,7 @@
          sodipodi:cy="155.38257"
          sodipodi:rx="4.3973203"
          sodipodi:ry="4.6182914"
-         d="m 80.87534,155.38257 a 4.3973203,4.6182914 0 1 1 -8.794641,0 4.3973203,4.6182914 0 1 1 8.794641,0 z"
+         d="m 80.87534,155.38257 c 0,2.55061 -1.968747,4.61829 -4.39732,4.61829 -2.428573,0 -4.397321,-2.06768 -4.397321,-4.61829 0,-2.55061 1.968748,-4.61829 4.397321,-4.61829 2.428573,0 4.39732,2.06768 4.39732,4.61829 z"
          transform="matrix(1.1939089,0,0,1.1367841,-44.307792,-20.636427)" /><rect
          style="fill:#000000;fill-opacity:1;stroke:none"
          id="rect4010"
@@ -792,9 +797,10 @@
          y="155"
          rx="0.38569456"
          ry="0" /></g></g><path
-     d="M0 0h24v24H0z"
-     fill="none"
-     id="path3242" /><g
+     d="M 0,0 H 24 V 24 H 0 z"
+     id="path3242"
+     inkscape:connector-curvature="0"
+     style="fill:none" /><g
      id="g2387"><path
        inkscape:connector-curvature="0"
        id="path3240"
@@ -942,7 +948,7 @@
              sketch:type="MSShapeGroup" /></g></g></g></g><polygon
      style="opacity:0.5;fill:none;stroke:none"
      id="bounds-5"
-     points="16,0 16,16 0,16 0,0 "
+     points="0,0 16,0 16,16 0,16 "
      transform="translate(232.08128,27.81372)" /><g
      id="g3185"><path
        id="path3730"
@@ -1024,12 +1030,13 @@
        id="path3294" /></g><g
      id="g2191"><path
        id="path3555-5"
-       d="M 16 6 C 12.69 6 10 8.69 10 12 C 10 15.31 12.69 18 16 18 C 19.31 18 22 15.31 22 12 L 20 12 C 20 14.209139 18.209139 16 16 16 C 13.790861 16 12 14.209139 12 12 C 12 9.7908611 13.790861 8 16 8 C 17.275627 8 18.392569 8.6012713 19.125 9.53125 L 21.46875 9.53125 C 20.526539 7.4496106 18.430781 6 16 6 z " /><path
+       d="m 16,6 c -3.31,0 -6,2.69 -6,6 0,3.31 2.69,6 6,6 3.31,0 6,-2.69 6,-6 l -2,0 c 0,2.209139 -1.790861,4 -4,4 -2.209139,0 -4,-1.790861 -4,-4 0,-2.2091389 1.790861,-4 4,-4 1.275627,0 2.392569,0.6012713 3.125,1.53125 l 2.34375,0 C 20.526539,7.4496106 18.430781,6 16,6 z"
+       inkscape:connector-curvature="0" /><path
        sodipodi:nodetypes="cccc"
        inkscape:connector-curvature="0"
        id="path3660"
        d="m 21.090773,6.879988 0,3.0918004 -3.0918,0 z"
-       style="fill:#000000;stroke:#000000;stroke-width:1.06808328999999991px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g><path
+       style="fill:#000000;stroke:#000000;stroke-width:1.06808329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /></g><path
      style="fill:none"
      inkscape:connector-curvature="0"
      d="m 169,29 h 18 v 18 h -18 z"
@@ -1067,7 +1074,7 @@
      id="path4367-6-6" /><path
      style="fill:none"
      inkscape:connector-curvature="0"
-     d="m 295.25,75.250001 h 20 v 20 h -20 z"
+     d="m 295.25,75.250001 h 20 V 95.25 h -20 z"
      id="path5182-06" /><path
      style="fill:none"
      inkscape:connector-curvature="0"
@@ -1090,7 +1097,7 @@
      id="path4367-6-8" /><path
      style="fill:none"
      inkscape:connector-curvature="0"
-     d="m 327.25,75.250001 h 20 v 20 h -20 z"
+     d="m 327.25,75.250001 h 20 V 95.25 h -20 z"
      id="path5182-7" /><path
      style="fill:none"
      inkscape:connector-curvature="0"
@@ -1118,7 +1125,7 @@
      style="fill:#ffffff;fill-opacity:0;stroke:none"
      id="bg-2"
      x="191.87378"
-     y="-0.0435686"
+     y="-0.043567657"
      width="14"
      height="14" /><g
      id="g2271"><circle
@@ -1140,7 +1147,7 @@
        style="fill:#000000;stroke:none" /></g><path
      style="fill:none"
      inkscape:connector-curvature="0"
-     d="m 292.76613,72.135146 h 24 v 24 h -24 z"
+     d="m 292.76613,72.135146 h 24 V 96.13515 h -24 z"
      id="path3652" /><path
      style="fill:none"
      inkscape:connector-curvature="0"
@@ -1148,7 +1155,7 @@
      id="path3763" /><path
      style="fill:none"
      inkscape:connector-curvature="0"
-     d="m 236.19418,70.013825 h 24 v 24 h -24 z"
+     d="m 236.19418,70.013825 h 24 V 94.01382 h -24 z"
      id="path3343" /><g
      id="g2237"><path
        id="path3345"
@@ -1233,7 +1240,7 @@
          id="rect3639-9"
          transform="scale(-1,1)" /></g></g><g
      id="g2528"><g
-       transform="rotate(-90,241.5,153.5)"
+       transform="matrix(0,-1,1,0,88,395)"
        id="g1088"><rect
          height="12"
          width="14"
@@ -1270,7 +1277,7 @@
            width="1"
            height="13" /></g></g></g><g
      id="g2442"><g
-       transform="rotate(-90,273.5,105.5)"
+       transform="matrix(0,-1,1,0,168,379)"
        id="g1243"><rect
          height="12"
          width="14"
@@ -1290,7 +1297,7 @@
          transform="scale(-1,1)" /></g></g><g
      id="g2448"><g
        id="g1248-3"
-       transform="rotate(-90,257.5,57.5)"><rect
+       transform="matrix(0,-1,1,0,200,315)"><rect
          height="12"
          width="14"
          x="-214.5"
@@ -1306,4 +1313,131 @@
          x="-211"
          y="102"
          id="rect3633-4-9"
-         transform="scale(-1,1)" /></g></g></svg>
\ No newline at end of file
+         transform="scale(-1,1)" /></g></g><g
+     id="g3829"
+     transform="translate(1,0)"><path
+       inkscape:connector-curvature="0"
+       id="path3519-7"
+       d="m 20,180 0,-7 2,0 0,7 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3521-5"
+       d="m 17,179 0,-6 2,0 0,6 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3523-3"
+       d="m 14,181 0,-8 2,0 0,8 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5"
+       d="m 11,185 0,-12 2,0 0,12 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-6"
+       d="m 8,177 0,-4 2,0 0,4 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3519-7-2"
+       d="m 20,180 0,-7 2,0 0,7 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3521-5-9"
+       d="m 17,179 0,-6 2,0 0,6 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3523-3-1"
+       d="m 14,181 0,-8 2,0 0,8 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-2"
+       d="m 11,185 0,-12 2,0 0,12 -2,0 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-6-7"
+       d="m 8,177 0,-4 2,0 0,4 -2,0 z" /></g><g
+     id="g3899"><path
+       inkscape:connector-curvature="0"
+       id="path3519-7-9"
+       d="m 48,185 -7,0 0,2 7,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3521-5-3"
+       d="m 47,182 -6,0 0,2 6,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3523-3-6"
+       d="m 49,179 -8,0 0,2 8,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-0"
+       d="m 53,176 -12,0 0,2 12,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-6-6"
+       d="m 45,173 -4,0 0,2 4,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3519-7-2-2"
+       d="m 48,185 -7,0 0,2 7,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3521-5-9-6"
+       d="m 47,182 -6,0 0,2 6,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3523-3-1-1"
+       d="m 53,179 -12,0 0,2 12,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-2-8"
+       d="m 55,176 -14,0 0,2 14,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-6-7-7"
+       d="m 45,173 -4,0 0,2 4,0 0,-2 z" /></g><g
+     id="g5005"><path
+       inkscape:connector-curvature="0"
+       id="path3519-7-9-2"
+       d="m 84,185 -8,0 0,2 8,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3523-3-6-2"
+       d="m 86,179 -7,0 0,2 7,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3521-5-9-6-9"
+       d="m 83,182 -4,0 0,2 4,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-2-8-2"
+       d="m 88,176 -12,0 0,2 12,0 0,-2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-6-7-7-8"
+       d="m 79,173 -6,0 0,2 6,0 0,-2 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9"
+       d="m 77,176 0,2 -4,0 0,-2 4,0 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9-3"
+       d="m 77,185 0,2 -4,0 0,-2 4,0 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9-3-1"
+       d="m 80,179 0,2 -4,0 0,-2 4,0 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9-3-1-7"
+       d="m 80,182 0,2 -4,0 0,-2 4,0 z" /></g><g
+     id="g5016"><path
+       inkscape:connector-curvature="0"
+       id="path3519-7-9-2-4"
+       d="m 104,175 8,0 0,-2 -8,0 0,2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3523-3-6-2-5"
+       d="m 104,181 7,0 0,-2 -7,0 0,2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3521-5-9-6-9-0"
+       d="m 104,178 4,0 0,-2 -4,0 0,2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-2-8-2-3"
+       d="m 104,184 12,0 0,-2 -12,0 0,2 z" /><path
+       inkscape:connector-curvature="0"
+       id="path3525-5-6-7-7-8-6"
+       d="m 113,187 6,0 0,-2 -6,0 0,2 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9-1"
+       d="m 115,184 0,-2 4,0 0,2 -4,0 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9-3-0"
+       d="m 112,175 0,-2 7,0 0,2 -7,0 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9-3-1-6"
+       d="m 110,181 0,-2 6,0 0,2 -6,0 z" /><path
+       style="opacity:0.4"
+       inkscape:connector-curvature="0"
+       id="path3517-7-9-3-1-7-3"
+       d="m 108,178 0,-2 8,0 0,2 -8,0 z" /></g></svg>
\ No newline at end of file
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png
index 6e29b0e9..c3d678c 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png
+++ b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs.png
Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png
index 46d3416..450877f 100644
--- a/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png
+++ b/third_party/WebKit/Source/devtools/front_end/Images/toolbarButtonGlyphs_2x.png
Binary files differ
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
index a9de61fd..295a7fd 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -118,6 +118,10 @@
       this._tabbedPane.appendTab(viewMode.BottomUp, Common.UIString('Bottom-Up'), new UI.VBox());
       this._tabbedPane.appendTab(viewMode.CallTree, Common.UIString('Call Tree'), new UI.VBox());
       this._tabbedPane.appendTab(viewMode.EventLog, Common.UIString('Event Log'), new UI.VBox());
+      this._tabbedPane.setTabIcon(viewMode.FlameChart, UI.Icon.create('largeicon-perf-flamechart'));
+      this._tabbedPane.setTabIcon(viewMode.BottomUp, UI.Icon.create('largeicon-perf-bottom-up-tree'));
+      this._tabbedPane.setTabIcon(viewMode.CallTree, UI.Icon.create('largeicon-perf-call-tree'));
+      this._tabbedPane.setTabIcon(viewMode.EventLog, UI.Icon.create('largeicon-perf-event-list'));
       this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this._onMainViewChanged.bind(this));
       this._tabbedPane.selectTab(this._viewModeSetting.get());
     } else {
@@ -139,9 +143,6 @@
     Extensions.extensionServer.addEventListener(
         Extensions.ExtensionServer.Events.TraceProviderAdded, this._appendExtensionsToToolbar, this);
     SDK.targetManager.addEventListener(SDK.TargetManager.Events.SuspendStateChanged, this._onSuspendStateChanged, this);
-
-    /** @type {!SDK.TracingModel.Event}|undefined */
-    this._selectedSearchResult;
   }
 
   /**
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
index 24ed2206..ee40700 100644
--- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -1212,6 +1212,17 @@
       contentHelper.addSection(Common.UIString('Invalidations'));
       Timeline.TimelineUIUtils._generateInvalidations(event, target, relatedNodesMap, contentHelper);
     } else if (initiator) {  // Partial invalidation tracking.
+      var delay = event.startTime - initiator.startTime;
+      contentHelper.appendTextRow(Common.UIString('Pending for'), Number.preciseMillisToString(delay, 1));
+
+      var link = createElementWithClass('span', 'devtools-link');
+      link.textContent = Common.UIString('reveal');
+      link.addEventListener('click', () => {
+        Timeline.TimelinePanel.instance().select(
+            Timeline.TimelineSelection.fromTraceEvent(/** @type {!SDK.TracingModel.Event} */ (initiator)));
+      });
+      contentHelper.appendElementRow(Common.UIString('Initiator'), link);
+
       var initiatorStackTrace = TimelineModel.TimelineData.forEvent(initiator).stackTrace;
       if (initiatorStackTrace) {
         contentHelper.appendStackTrace(
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
index 0b3c08a..4dd053c 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/Icon.js
@@ -169,6 +169,10 @@
   'largeicon-dock-to-bottom': {x: -32, y: -24, width: 28, height: 24, spritesheet: 'largeicons', isMask: true},
   'largeicon-undock': {x: 0, y: -48, width: 28, height: 24, spritesheet: 'largeicons', isMask: true},
   'largeicon-settings-gear': {x: -288, y: -72, width: 28, height: 24, spritesheet: 'largeicons', isMask: true},
+  'largeicon-perf-flamechart': {x: -4, y: -168, width: 24, height: 24, spritesheet: 'largeicons', isMask: true},
+  'largeicon-perf-event-list': {x: -36, y: -168, width: 24, height: 24, spritesheet: 'largeicons', isMask: true},
+  'largeicon-perf-call-tree': {x: -68, y: -168, width: 24, height: 24, spritesheet: 'largeicons', isMask: true},
+  'largeicon-perf-bottom-up-tree': {x: -100, y: -168, width: 24, height: 24, spritesheet: 'largeicons', isMask: true},
 
   'largeicon-show-left-sidebar': {x: -160, y: -72, width: 28, height: 24, spritesheet: 'largeicons', isMask: true},
   'largeicon-hide-left-sidebar': {x: -192, y: -72, width: 28, height: 24, spritesheet: 'largeicons', isMask: true},
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css
index 009b7db..3c8faf08 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css
+++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorCommon.css
@@ -343,12 +343,12 @@
 
 .spritesheet-largeicons:not(.icon-mask) {
     background-image: -webkit-image-set(url(Images/toolbarButtonGlyphs.png) 1x, url(Images/toolbarButtonGlyphs_2x.png) 2x);
-    background-size: 352px 168px;
+    background-size: 352px 192px;
 }
 
 .spritesheet-largeicons.icon-mask {
     -webkit-mask-image: -webkit-image-set(url(Images/toolbarButtonGlyphs.png) 1x, url(Images/toolbarButtonGlyphs_2x.png) 2x);
-    -webkit-mask-size: 352px 168px;
+    -webkit-mask-size: 352px 192px;
 }
 
 .spritesheet-resourceicons:not(.icon-mask) {
@@ -372,7 +372,7 @@
 
 .force-white-icons [is=ui-icon].spritesheet-largeicons, [is=ui-icon].force-white-icons.spritesheet-largeicons {
     -webkit-mask-image: -webkit-image-set(url(Images/toolbarButtonGlyphs.png) 1x, url(Images/toolbarButtonGlyphs_2x.png) 2x);
-    -webkit-mask-size: 352px 168px;
+    -webkit-mask-size: 352px 192px;
     background-image: unset;
     background-size: unset;
     background: unset;
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index a946de5b..300ea7d9 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -113,9 +113,6 @@
   "chrome/browser/resources/quota_internals_resources.grd": {
     "includes": [11990],
   },
-  "chrome/browser/resources/settings/settings_resources_vulcanized.grd": {
-    "includes": [12010],
-  },
   "chrome/browser/resources/settings/settings_resources.grd": {
     "structures": [12020],
   },
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 1494ddb..096ec4e 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -77860,20 +77860,24 @@
 </histogram>
 
 <histogram name="Welcome.Win10.NewPromoPageAdded" enum="BooleanShown">
+  <owner>pmonette@chromium.org</owner>
   <owner>tmartino@chromium.org</owner>
   <summary>
-    Records whether or not the revamped WebUI-based welcome page was added to
-    the startup tabs list. This means there is a good chance it was shown to the
-    user.
+    Emits a &quot;true&quot; sample when the revamped WebUI-based welcome page
+    is added to the startup tabs list. This means that barring an error on
+    startup, it was shown to the user. This histogram can only be recorded
+    during first-run flow, when the EnableWelcomeWin10 experiment is enabled.
   </summary>
 </histogram>
 
 <histogram name="Welcome.Win10.OriginalPromoPageAdded" enum="BooleanShown">
+  <owner>pmonette@chromium.org</owner>
   <owner>tmartino@chromium.org</owner>
   <summary>
-    Records whether or not the old external welcome page was added to the
-    startup tabs list. This means there is a good chance it was shown to the
-    user.
+    Emits a &quot;true&quot; sample when the old external welcome page is added
+    to the startup tabs list. This means that barring an error on startup, it
+    was shown to the user. This histogram can only be recorded during first-run
+    flow, when the EnableWelcomeWin10 experiment is disabled.
   </summary>
 </histogram>
 
diff --git a/ui/webui/resources/cr_elements/icons.html b/ui/webui/resources/cr_elements/icons.html
index 12af690f..674926d52 100644
--- a/ui/webui/resources/cr_elements/icons.html
+++ b/ui/webui/resources/cr_elements/icons.html
@@ -50,10 +50,7 @@
       <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
       <g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"></path></g>
       <g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path></g>
-      <!-- The <g> IDs are exposed as global variables in Vulcanized mode, which
-        conflicts with the "settings" namespace of MD Settings. Using an "_icon"
-        suffix prevents the naming conflict. -->
-      <g id="settings_icon"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
+      <g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
       <g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
       <g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
     </defs>