diff --git a/DEPS b/DEPS
index 45170061..13d1026 100644
--- a/DEPS
+++ b/DEPS
@@ -105,11 +105,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'a38ab3b094bae9cfda82829cc0cb2ca89449faca',
+  'skia_revision': '311739b2dda1d49b9ce8e7db7a33ecf6db66e6ec',
   # 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': '668b404640ee55f3f700640e7b6ff533e49c6af0',
+  'v8_revision': '028497d0d491393efc6ef2946acaff97a61b10c0',
   # 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.
@@ -117,7 +117,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'fcf10b62f76a6e75c8265667735b91212a303170',
+  'angle_revision': '9d0bb3d4d5c012d3b68bbf47adc910e66009bd5c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -165,7 +165,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '357c5c287bba72b99f96dec935224f5aea74deea',
+  'catapult_revision': '86bdcbf37ffcfaa2c9064a14e24f6195a56baefe',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -595,7 +595,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e4c8cd9919f63b1a23beb06cb77530a2f3ee2812',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8d7d6eca5f409d74329fb969a3065bcb491ec521',
       'condition': 'checkout_linux',
   },
 
@@ -1106,7 +1106,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6d2f3f4cb8bac1f7c4a945c73d07a33df74f22f9',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '3a3f0274edd9dd6c95cfee5471df5699aeb12113',
+    Var('webrtc_git') + '/src.git' + '@' + '5526e457e3e8ea14ecce32e2eecd6ded55c3e73c',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1137,7 +1137,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b94929a9aae30bc7e026152ea1661d8591f38442',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8c691df3b55a875e050ba7170210cd45fae4a950',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/base/metrics/bucket_ranges.cc b/base/metrics/bucket_ranges.cc
index 2723c3e..39b37932 100644
--- a/base/metrics/bucket_ranges.cc
+++ b/base/metrics/bucket_ranges.cc
@@ -74,8 +74,7 @@
 // the CRC correct for big-endian vs little-ending calculations.  All we need is
 // a nice hash, that tends to depend on all the bits of the sample, with very
 // little chance of changes in one place impacting changes in another place.
-// Temporary non-static for https://crbug.com/836238
-/*static*/ uint32_t Crc32(uint32_t sum, HistogramBase::Sample value) {
+static uint32_t Crc32(uint32_t sum, HistogramBase::Sample value) {
   union {
     HistogramBase::Sample range;
     unsigned char bytes[sizeof(HistogramBase::Sample)];
diff --git a/base/metrics/bucket_ranges.h b/base/metrics/bucket_ranges.h
index 476d2df..1b6d069 100644
--- a/base/metrics/bucket_ranges.h
+++ b/base/metrics/bucket_ranges.h
@@ -99,7 +99,6 @@
 //////////////////////////////////////////////////////////////////////////////
 // Expose only for test.
 BASE_EXPORT extern const uint32_t kCrcTable[256];
-uint32_t Crc32(uint32_t sum, HistogramBase::Sample value);
 
 }  // namespace base
 
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 094dea7..1b80abbd 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -166,99 +166,10 @@
       return DummyHistogram::GetInstance();
     // To avoid racy destruction at shutdown, the following will be leaked.
     const BucketRanges* created_ranges = CreateRanges();
-    CHECK(created_ranges->HasValidChecksum()) << name_;
-
-// Temporary check for https://crbug.com/836238
-#if defined(OS_WIN)  // Only Windows has a debugger that makes this useful.
-    if (bucket_count_ > 0 &&
-        maximum_ != created_ranges->range(bucket_count_ - 1)) {
-      // Create local copies of the parameters to be sure they'll be available
-      // in the crash dump for the debugger to see.
-      DEBUG_ALIAS_FOR_CSTR(h_name, name_.c_str(), 100);
-      HistogramType h_type = histogram_type_;
-      Sample h_min = minimum_;
-      Sample h_max = maximum_;
-      uint32_t h_count = bucket_count_;
-      debug::Alias(&h_type);
-      debug::Alias(&h_min);
-      debug::Alias(&h_max);
-      debug::Alias(&h_count);
-      uint32_t ranges_min = created_ranges->range(1);
-      uint32_t ranges_max = created_ranges->range(bucket_count_ - 1);
-      debug::Alias(&ranges_min);
-      debug::Alias(&ranges_max);
-      CHECK(false) << name_;
-    }
-#endif
-
-// Temporary check for https://crbug.com/836238
-#if defined(OS_WIN)  // Only Windows has a debugger that makes this useful.
-    std::unique_ptr<const BucketRanges> recreated_ranges(CreateRanges());
-    for (uint32_t i = 0; i < bucket_count_; ++i) {
-      uint32_t created_range = created_ranges->range(i);
-      uint32_t recreated_range = recreated_ranges->range(i);
-      debug::Alias(&created_range);
-      debug::Alias(&recreated_range);
-      if (created_range != recreated_range) {
-        // Create local copies of the parameters to be sure they'll be available
-        // in the crash dump for the debugger to see.
-        DEBUG_ALIAS_FOR_CSTR(h_name, name_.c_str(), 100);
-        HistogramType h_type = histogram_type_;
-        uint32_t b_count = bucket_count_;
-        size_t c_count = created_ranges->size() - 1;
-        size_t r_count = recreated_ranges->size() - 1;
-        bool c_valid = created_ranges->HasValidChecksum();
-        bool r_valid = recreated_ranges->HasValidChecksum();
-        CHECK(recreated_ranges->Equals(created_ranges)) << name_;
-        debug::Alias(&h_type);
-        debug::Alias(&b_count);
-        debug::Alias(&c_count);
-        debug::Alias(&r_count);
-        debug::Alias(&c_valid);
-        debug::Alias(&r_valid);
-        CHECK(false) << name_;
-      }
-    }
-    CHECK(recreated_ranges->Equals(created_ranges));
-#endif
 
     const BucketRanges* registered_ranges =
         StatisticsRecorder::RegisterOrDeleteDuplicateRanges(created_ranges);
 
-// Temporary check for https://crbug.com/836238
-#if defined(OS_WIN)  // Only Windows has a debugger that makes this useful.
-    bool using_created_ranges = (registered_ranges == created_ranges);
-    bool equal_ranges = registered_ranges->Equals(recreated_ranges.get());
-    debug::Alias(&using_created_ranges);
-    debug::Alias(&equal_ranges);
-    for (uint32_t i = 0; i < bucket_count_; ++i) {
-      uint32_t created_range = recreated_ranges->range(i);
-      uint32_t registered_range = registered_ranges->range(i);
-      debug::Alias(&created_range);
-      debug::Alias(&registered_range);
-      if (created_range != registered_range) {
-        // Create local copies of the parameters to be sure they'll be available
-        // in the crash dump for the debugger to see.
-        DEBUG_ALIAS_FOR_CSTR(h_name, name_.c_str(), 100);
-        HistogramType h_type = histogram_type_;
-        uint32_t b_count = bucket_count_;
-        size_t c_count = recreated_ranges->size() - 1;
-        size_t r_count = registered_ranges->size() - 1;
-        bool c_valid = recreated_ranges->HasValidChecksum();
-        bool r_valid = registered_ranges->HasValidChecksum();
-        CHECK(recreated_ranges->Equals(registered_ranges)) << name_;
-        debug::Alias(&h_type);
-        debug::Alias(&b_count);
-        debug::Alias(&c_count);
-        debug::Alias(&r_count);
-        debug::Alias(&c_valid);
-        debug::Alias(&r_valid);
-        CHECK(false) << name_;
-      }
-    }
-    CHECK(recreated_ranges->Equals(registered_ranges));
-#endif
-
     // In most cases, the bucket-count, minimum, and maximum values are known
     // when the code is written and so are passed in explicitly. In other
     // cases (such as with a CustomHistogram), they are calculated dynamically
@@ -427,15 +338,6 @@
   ranges->set_range(bucket_index, current);
   size_t bucket_count = ranges->bucket_count();
 
-  // Temporary for https://crbug.com/836238
-  uint32_t checksum = static_cast<uint32_t>(bucket_count + 1);
-  checksum = Crc32(checksum, 0);
-  checksum = Crc32(checksum, current);
-  debug::Alias(&minimum);
-  debug::Alias(&maximum);
-  debug::Alias(&bucket_count);
-  debug::Alias(&checksum);
-
   while (bucket_count > ++bucket_index) {
     double log_current;
     log_current = log(static_cast<double>(current));
@@ -450,12 +352,9 @@
     else
       ++current;  // Just do a narrow bucket, and keep trying.
     ranges->set_range(bucket_index, current);
-    checksum = Crc32(checksum, current);
   }
   ranges->set_range(ranges->bucket_count(), HistogramBase::kSampleType_MAX);
   ranges->ResetChecksum();
-  checksum = Crc32(checksum, HistogramBase::kSampleType_MAX);
-  CHECK_EQ(checksum, ranges->checksum());
 }
 
 // static
@@ -1086,32 +985,14 @@
   double max = maximum;
   size_t bucket_count = ranges->bucket_count();
 
-  // Temporary for https://crbug.com/836238
-  bool is_enum = (minimum == 1 &&
-                  static_cast<Sample>(bucket_count) == maximum - minimum + 2);
-  uint32_t checksum = static_cast<uint32_t>(bucket_count + 1);
-  checksum = Crc32(checksum, 0);
-  debug::Alias(&minimum);
-  debug::Alias(&maximum);
-  debug::Alias(&min);
-  debug::Alias(&max);
-  debug::Alias(&bucket_count);
-  debug::Alias(&checksum);
-  debug::Alias(&is_enum);
-
   for (size_t i = 1; i < bucket_count; ++i) {
     double linear_range =
         (min * (bucket_count - 1 - i) + max * (i - 1)) / (bucket_count - 2);
     uint32_t range = static_cast<Sample>(linear_range + 0.5);
-    if (is_enum)
-      CHECK_EQ(static_cast<uint32_t>(i), range);
     ranges->set_range(i, range);
-    checksum = Crc32(checksum, range);
   }
   ranges->set_range(ranges->bucket_count(), HistogramBase::kSampleType_MAX);
   ranges->ResetChecksum();
-  checksum = Crc32(checksum, HistogramBase::kSampleType_MAX);
-  CHECK_EQ(checksum, ranges->checksum());
 }
 
 // static
diff --git a/chrome/VERSION b/chrome/VERSION
index 1f0ebfb..3ac181d6 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=71
 MINOR=0
-BUILD=3576
+BUILD=3577
 PATCH=0
diff --git a/chrome/android/java/res/layout/autofill_assistant_sheet.xml b/chrome/android/java/res/layout/autofill_assistant_sheet.xml
index 56d8f1e8..98f7f79 100644
--- a/chrome/android/java/res/layout/autofill_assistant_sheet.xml
+++ b/chrome/android/java/res/layout/autofill_assistant_sheet.xml
@@ -17,6 +17,7 @@
         android:layout_height="match_parent"
         android:gravity="center"
         android:clickable="true"
+        android:visibility="gone"
         android:focusable="false"
         android:orientation="vertical">
 
diff --git a/chrome/android/java/res/layout/explore_sites_page_layout.xml b/chrome/android/java/res/layout/explore_sites_page_layout.xml
index e9255e4..d62f595 100644
--- a/chrome/android/java/res/layout/explore_sites_page_layout.xml
+++ b/chrome/android/java/res/layout/explore_sites_page_layout.xml
@@ -7,6 +7,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/explore_sites_category_recycler"
+    android:background="@color/modern_primary_color"
     android:scrollbars="vertical"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/chrome/android/java/res/layout/toolbar_phone.xml b/chrome/android/java/res/layout/toolbar_phone.xml
index 1751858c..f53749d 100644
--- a/chrome/android/java/res/layout/toolbar_phone.xml
+++ b/chrome/android/java/res/layout/toolbar_phone.xml
@@ -51,19 +51,14 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="top|end" >
-        <FrameLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top" >
 
-            <ViewStub
-                android:id="@+id/experimental_button_stub"
-                android:inflatedId="@+id/experimental_toolbar_button"
-                android:layout="@layout/experimental_toolbar_button"
-                style="@style/ToolbarButton"
-                android:paddingStart="8dp"
-                android:visibility="gone" />
-        </FrameLayout>
+        <ViewStub
+            android:id="@+id/experimental_button_stub"
+            android:inflatedId="@+id/experimental_toolbar_button"
+            android:layout="@layout/experimental_toolbar_button"
+            style="@style/ToolbarButton"
+            android:paddingStart="8dp"
+            android:visibility="gone" />
 
         <ImageButton android:id="@+id/tab_switcher_button"
             style="@style/ToolbarButton"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index 8417018..9ab3d55 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -195,6 +195,8 @@
             "ContextualSuggestionsAlternateCardLayout";
     public static final String CONTEXTUAL_SUGGESTIONS_BUTTON = "ContextualSuggestionsButton";
     public static final String CONTEXTUAL_SUGGESTIONS_OPT_OUT = "ContextualSuggestionsOptOut";
+    public static final String CONTEXTUAL_SUGGESTIONS_IPH_REVERSE_SCROLL =
+            "ContextualSuggestionsIPHReverseScroll";
     public static final String CUSTOM_CONTEXT_MENU = "CustomContextMenu";
     public static final String CUSTOM_FEEDBACK_UI = "CustomFeedbackUi";
     // Enables the Data Reduction Proxy menu item in the main menu rather than under Settings on
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java
index e64d730..38d42de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contacts_picker/PickerAdapter.java
@@ -64,6 +64,7 @@
      */
     public void setSearchString(String query) {
         if (query.equals("")) {
+            if (mSearchResults == null) return;
             mSearchResults.clear();
             mSearchResults = null;
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java
index 3d108b5..6a16d5c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCoordinator.java
@@ -64,7 +64,7 @@
         mBottomSheetController = bottomSheetController;
         mTabModelSelector = tabModelSelector;
         mMediator = mediator;
-        mediator.initialize(this, bottomSheetController.getBottomSheet());
+        mediator.initialize(this);
     }
 
     /** Called when the containing activity is destroyed. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
index fec1a30..70da6e9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsMediator.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.toolbar.ToolbarPhone;
 import org.chromium.chrome.browser.util.AccessibilityUtil;
-import org.chromium.chrome.browser.util.MathUtils;
 import org.chromium.chrome.browser.widget.ListMenuButton;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.StateChangeReason;
@@ -74,9 +73,9 @@
     private final Handler mHandler = new Handler();
     private final Provider<ContextualSuggestionsSource> mSuggestionSourceProvider;
     private @Nullable final OverviewModeBehavior mOverviewModeBehavior;
+    private final boolean mRequireReverseScrollForIPH;
 
     private ContextualSuggestionsCoordinator mCoordinator;
-    private View mIphParentView;
 
     private @Nullable ContextualSuggestionsSource mSuggestionsSource;
     private @Nullable FetchHelper mFetchHelper;
@@ -88,12 +87,25 @@
     private boolean mSuggestionsSetOnBottomSheet;
     private boolean mHasRecordedButtonShownForTab;
 
+    /**
+     * Whether the browser controls have fully hidden at least once since the last time
+     * #clearSuggestions() was called. This is used as a proxy for whether the user has scrolled
+     * down on the current page.
+     */
+    private boolean mHaveBrowserControlsFullyHidden;
+
     private boolean mHasPeekDelayPassed;
 
     /** Whether the content sheet is observed to be opened for the first time. */
     private boolean mHasSheetBeenOpened;
 
     /**
+     * Whether in-product help may be shown. This is set to false if the IPH system indicates that
+     * it wouldn't trigger our IPH if requested and when we attempt to show the IPH bubble.
+     */
+    private boolean mCanShowIph;
+
+    /**
      * Construct a new {@link ContextualSuggestionsMediator}.
      * @param profile The last used {@link Profile}.
      * @param tabModelSelector The {@link TabModelSelector} for the containing activity.
@@ -135,6 +147,14 @@
             @Override
             public void onControlsOffsetChanged(
                     float topOffset, float bottomOffset, boolean needsAnimate) {
+                if (!mHaveBrowserControlsFullyHidden) {
+                    mHaveBrowserControlsFullyHidden =
+                            mFullscreenManager.areBrowserControlsOffScreen();
+                } else if (mCanShowIph && mRequireReverseScrollForIPH
+                        && mFullscreenManager.areBrowserControlsFullyVisible()) {
+                    mHandler.postDelayed(() -> maybeShowHelpBubble(),
+                            ToolbarPhone.LOC_BAR_WIDTH_CHANGE_ANIMATION_DURATION_MS);
+                }
                 reportToolbarButtonShown();
             }
 
@@ -156,20 +176,18 @@
         } else {
             mOverviewModeBehavior = null;
         }
+
+        mRequireReverseScrollForIPH = ChromeFeatureList.isEnabled(
+                ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_IPH_REVERSE_SCROLL);
     }
 
     /**
-     * Sets the {@link ContextualSuggestionsCoordinator} for bidirectional communication,
-     * and the {@link View} used to anchor an in-product help bubble.
+     * Sets the {@link ContextualSuggestionsCoordinator} for bidirectional communication.
      */
-    void initialize(ContextualSuggestionsCoordinator coordinator, View iphParentView) {
+    void initialize(ContextualSuggestionsCoordinator coordinator) {
         // TODO(pshmakov): get rid of this circular dependency by establishing an observer-observable
         // relationship between Mediator and Coordinator;
         mCoordinator = coordinator;
-
-        // TODO(twellington): The mediator shouldn't need to directly access other UI components or
-        // views. Make IPH implementation better adhere to MVC model.
-        mIphParentView = iphParentView;
     }
 
     /** Destroys the mediator. */
@@ -189,14 +207,6 @@
         mEnabledStateMonitor.removeObserver(this);
     }
 
-    /**
-     * @return Whether the browser controls are currently completely hidden.
-     */
-    private boolean areBrowserControlsHidden() {
-        return MathUtils.areFloatsEqual(-mFullscreenManager.getTopControlOffset(),
-                mFullscreenManager.getTopControlsHeight());
-    }
-
     @Override
     public void onEnabledStateChanged(boolean enabled) {
         if (enabled) {
@@ -209,6 +219,13 @@
     private void enable() {
         mSuggestionsSource = mSuggestionSourceProvider.get();
         mFetchHelper = new FetchHelper(this, mTabModelSelector);
+
+        Tracker tracker = TrackerFactory.getTrackerForProfile(mProfile);
+        tracker.addOnInitializedCallback(success -> {
+            if (!success) return;
+            mCanShowIph =
+                    tracker.wouldTriggerHelpUI(FeatureConstants.CONTEXTUAL_SUGGESTIONS_FEATURE);
+        });
     }
 
     private void disable() {
@@ -304,8 +321,9 @@
     }
 
     private void reportToolbarButtonShown() {
-        if (mHasRecordedButtonShownForTab || areBrowserControlsHidden() || isOverviewModeVisible()
-                || mSuggestionsSource == null || !mModel.hasSuggestions()) {
+        if (mHasRecordedButtonShownForTab || !mFullscreenManager.areBrowserControlsFullyVisible()
+                || isOverviewModeVisible() || mSuggestionsSource == null
+                || !mModel.hasSuggestions()) {
             return;
         }
 
@@ -313,8 +331,10 @@
         reportEvent(ContextualSuggestionsEvent.UI_BUTTON_SHOWN);
         TrackerFactory.getTrackerForProfile(mProfile).notifyEvent(
                 EventConstants.CONTEXTUAL_SUGGESTIONS_BUTTON_SHOWN);
-        mHandler.postDelayed(() -> maybeShowHelpBubble(),
-                ToolbarPhone.LOC_BAR_WIDTH_CHANGE_ANIMATION_DURATION_MS);
+        if (mCanShowIph && !mRequireReverseScrollForIPH) {
+            mHandler.postDelayed(() -> maybeShowHelpBubble(),
+                    ToolbarPhone.LOC_BAR_WIDTH_CHANGE_ANIMATION_DURATION_MS);
+        }
     }
 
     @Override
@@ -391,6 +411,7 @@
         mHasSheetBeenOpened = false;
         mHandler.removeCallbacksAndMessages(null);
         mHasPeekDelayPassed = false;
+        mHaveBrowserControlsFullyHidden = false;
         mModel.setClusterList(Collections.emptyList());
         mModel.setCloseButtonOnClickListener(null);
         mModel.setMenuButtonDelegate(null);
@@ -458,13 +479,17 @@
     }
 
     private void maybeShowHelpBubble() {
-        View anchorView =
-                mIphParentView.getRootView().findViewById(R.id.experimental_toolbar_button);
-        if (mToolbarManager.isUrlBarFocused() || anchorView == null
-                || anchorView.getVisibility() != View.VISIBLE) {
+        View anchorView = mToolbarManager.getExperimentalButtonView();
+        if (!mCanShowIph || mToolbarManager.isUrlBarFocused() || anchorView == null
+                || anchorView.getVisibility() != View.VISIBLE
+                || !mFullscreenManager.areBrowserControlsFullyVisible()
+                || mSuggestionsSource == null || !mModel.hasSuggestions()) {
             return;
         }
 
+        // Either we'll fail to show or we'll successfully show. Either way, we can't show IPH
+        // after this attempt.
+        mCanShowIph = false;
         Tracker tracker = TrackerFactory.getTrackerForProfile(mProfile);
         if (!tracker.shouldTriggerHelpUI(FeatureConstants.CONTEXTUAL_SUGGESTIONS_FEATURE)) {
             return;
@@ -472,10 +497,10 @@
 
         ViewRectProvider rectProvider = new ViewRectProvider(anchorView);
         rectProvider.setInsetPx(0, 0, 0,
-                mIphParentView.getResources().getDimensionPixelOffset(
+                anchorView.getResources().getDimensionPixelOffset(
                         R.dimen.text_bubble_menu_anchor_y_inset));
 
-        mHelpBubble = new ImageTextBubble(mIphParentView.getContext(), mIphParentView,
+        mHelpBubble = new ImageTextBubble(anchorView.getContext(), anchorView,
                 R.string.contextual_suggestions_in_product_help,
                 R.string.contextual_suggestions_in_product_help_accessibility, true, rectProvider,
                 R.drawable.ic_logo_googleg_24dp);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
index 6d43da68..4afbd81 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -333,6 +333,13 @@
     }
 
     /**
+     * @return True if the browser controls are currently completely visible.
+     */
+    public boolean areBrowserControlsFullyVisible() {
+        return getBrowserControlHiddenRatio() == 0.f;
+    }
+
+    /**
      * @return Whether the browser controls should be drawn as a texture.
      */
     public boolean drawControlsAsTexture() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
index f8cd899..7250526 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -873,6 +873,13 @@
             @DrawableRes int drawableResId, @StringRes int contentDescriptionResId) {}
 
     /**
+     * @return The experimental toolbar button if it exists.
+     */
+    public @Nullable View getExperimentalButtonView() {
+        return null;
+    }
+
+    /**
      * Disable the experimental toolbar button.
      */
     public void disableExperimentalButton() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index ed6f4cf..b8b93e8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -986,6 +986,14 @@
     }
 
     /**
+     * @return The experimental toolbar button if it exists.
+     */
+    public @Nullable View getExperimentalButtonView() {
+        if (mToolbar == null) return null;
+        return mToolbar.getExperimentalButtonView();
+    }
+
+    /**
      * @return The bookmarks bridge.
      */
     public BookmarkBridge getBookmarkBridge() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
index c4e955c..ead9063 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -2731,6 +2731,11 @@
     }
 
     @Override
+    public View getExperimentalButtonView() {
+        return mExperimentalButton;
+    }
+
+    @Override
     public void disableExperimentalButton() {
         if (mExperimentalButton == null || mExperimentalButton.getVisibility() == View.GONE) {
             return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java
index b56bb4014..7bb22e2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDisclosureSnackbarController.java
@@ -55,7 +55,7 @@
                                     this, Snackbar.TYPE_PERSISTENT,
                                     Snackbar.UMA_WEBAPK_PRIVACY_DISCLOSURE)
                             .setAction(
-                                    activity.getResources().getString(R.string.ok_got_it), storage)
+                                    activity.getResources().getString(R.string.ok), storage)
                             .setSingleLine(false));
         }
     }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 735849b..269d740 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1649,11 +1649,11 @@
       <message name="IDS_SYNC_PASSPHRASE_TYPE_KEYSTORE" desc="Option to encrypt only passwords, using your Google credentials.">
         Encrypt passwords with Google credentials
       </message>
-      <message name="IDS_SYNC_PASSPHRASE_TYPE_FROZEN" desc="Option to encrypt all data, using your Google password frozen on the substituted date.">
-        Encrypt all with Google password as of <ph name="TIME">%1$s<ex>Oct 3, 2014</ex></ph>
+      <message name="IDS_SYNC_PASSPHRASE_TYPE_FROZEN" desc="Option to encrypt sync data, using your Google password frozen on the substituted date.">
+        Encrypt synced data with Google password as of <ph name="TIME">%1$s<ex>Oct 3, 2014</ex></ph>
       </message>
-      <message name="IDS_SYNC_PASSPHRASE_TYPE_CUSTOM" desc="Option to encrypt all sync data with a custom passphrase.">
-        Encrypt all synced data with your own sync passphrase
+      <message name="IDS_SYNC_PASSPHRASE_TYPE_CUSTOM" desc="Option to encrypt sync data with a custom passphrase.">
+        Encrypt synced data with your own sync passphrase
       </message>
       <message name="IDS_SYNC_PASSPHRASE_TYPE_CUSTOM_DIALOG_TITLE" desc="Dialog title for custom passphrase creation.">
         Create passphrase
@@ -1662,7 +1662,7 @@
         Google Account
       </message>
       <message name="IDS_SYNC_CUSTOM_PASSPHRASE" desc="Prompt user to create a custom sync password.">
-        Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting you'll need to reset sync. <ph name="BEGIN_LINK">&lt;learnmore&gt;</ph>Learn more<ph name="END_LINK">&lt;/learnmore&gt;</ph>
+        Passphrase encryption doesn’t include payment methods and addresses from Google Pay. Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting you'll need to reset sync. <ph name="BEGIN_LINK">&lt;learnmore&gt;</ph>Learn more<ph name="END_LINK">&lt;/learnmore&gt;</ph>
       </message>
       <message name="IDS_SYNC_ENTER_CUSTOM_PASSPHRASE_HINT" desc="Hint for the passphrase field when user is to type in a passphrase. [CHAR-LIMIT=30]">
         Passphrase
@@ -1680,7 +1680,9 @@
         Passphrases do not match
       </message>
       <message name="IDS_SYNC_PASSPHRASE_ENCRYPTION_RESET_INSTRUCTIONS" desc="Inform user how to change their encryption setting.">
-        To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<ph name="END_LINK">&lt;/resetlink&gt;</ph>
+        Passphrase encryption doesn’t include payment methods and addresses from Google Pay.
+
+To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<ph name="END_LINK">&lt;/resetlink&gt;</ph>
       </message>
       <message name="IDS_SYNC_PASSPHRASE_INCORRECT" desc="Inform the user that the passphrase they entered for sync is incorrect. [CHAR-LIMIT=40]">
         Incorrect passphrase
@@ -3549,7 +3551,7 @@
 
       <!-- WebAPK/TWA related strings -->
       <message name="IDS_APP_RUNNING_IN_CHROME_DISCLOSURE" desc="Message on the snackbar that indicates an app may use Chrome data.">
-        This app is running in Chrome.
+        This app is running in Chrome
       </message>
       <message name="IDS_TWA_RUNNING_IN_CHROME" desc="Message on a snackbar indicating that the current Activity may use Chrome data (the rest of the app may not be)." translateable="false">
         Running in Chrome
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java
index 879f8211..c3090a6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contacts_picker/ContactsPickerDialogTest.java
@@ -194,6 +194,13 @@
         Assert.assertEquals(expectedAction, mLastActionRecorded);
     }
 
+    private void clickSearchButton() throws Exception {
+        ContactsPickerToolbar toolbar =
+                (ContactsPickerToolbar) mDialog.findViewById(R.id.action_bar);
+        View search = toolbar.findViewById(R.id.search);
+        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(), search);
+    }
+
     private void dismissDialog() {
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
@@ -321,4 +328,14 @@
         clickActionButton(6, ContactsPickerAction.SELECT_ALL);
         clickActionButton(5, ContactsPickerAction.UNDO_SELECT_ALL);
     }
+
+    @Test
+    @LargeTest
+    public void testNoSearchStringNoCrash() throws Throwable {
+        createDialog(/* multiselect = */ true, Arrays.asList("image/*"));
+        Assert.assertTrue(mDialog.isShowing());
+
+        clickSearchButton();
+        dismissDialog();
+    }
 }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index c64d1c9..17dade9 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7186,15 +7186,15 @@
 
         <!-- Encryption tab of the configure sync dialog -->
         <message name="IDS_SYNC_FULL_ENCRYPTION_BODY_CUSTOM" desc="Text of the radio that when selected enables full encryption.">
-          All data is encrypted with your sync passphrase
+          Data is encrypted with your sync passphrase. This doesn't include payment methods and addresses from Google Pay.
         </message>
         <message name="IDS_SYNC_FULL_ENCRYPTION_BODY_CUSTOM_WITH_DATE" desc="Text of the radio that when selected enables full encryption.">
-          All data was encrypted with your sync passphrase on
-          <ph name="TIME">$1<ex>Sept 1, 2012</ex></ph>
+          Data was encrypted with your sync passphrase on
+          <ph name="TIME">$1<ex>Sept 1, 2012</ex></ph>. This doesn't include payment methods and addresses from Google Pay.
         </message>
         <message name="IDS_SYNC_FULL_ENCRYPTION_BODY_GOOGLE_WITH_DATE" desc="Text of the radio that when selected enables full encryption.">
-          All data was encrypted with your Google password as of
-          <ph name="TIME">$1<ex>Sept 1, 2012</ex></ph>
+          Data was encrypted with your Google password as of
+          <ph name="TIME">$1<ex>Sept 1, 2012</ex></ph>. This doesn't include payment methods and addresses from Google Pay.
         </message>
 
         <!-- Sync promo page chrome://signin -->
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 80f6af77..1a8fdc7 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1167,9 +1167,6 @@
   <message name="IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED" desc="A description for the basic tab explaining browsing history for users with history sync.">
     Clears history from all signed-in devices. Your Google Account may have other forms of browsing history at <ph name="BEGIN_LINK">&lt;a target='_blank' href='$1'&gt;</ph>myactivity.google.com<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>.
   </message>
-  <message name="IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNC_ERROR" desc="A description for the basic tab explaining browsing history for users with history sync, that have a sync error.">
-    Clears history from this device.
-  </message>
   <message name="IDS_SETTINGS_CLEAR_DOWNLOAD_HISTORY" desc="Checkbox for deleting Download History">
     Download history
   </message>
@@ -3645,7 +3642,7 @@
     Encrypt synced passwords with your Google username and password
   </message>
   <message name="IDS_SETTINGS_ENCRYPT_WITH_SYNC_PASSPHRASE_LABEL" desc="Label for the radio button which, when selected, causes synced settings to be encrypted with a user-provided password.">
-    Encrypt synced data with your own <ph name="BEGIN_LINK">&lt;a href="$1" target=&quot;_blank&quot;&gt;<ex>&lt;a href="$1" target=&quot;_blank&quot;&gt;</ex></ph>sync passphrase<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
+    Encrypt synced data with your own <ph name="BEGIN_LINK">&lt;a href="$1" target=&quot;_blank&quot;&gt;<ex>&lt;a href="$1" target=&quot;_blank&quot;&gt;</ex></ph>sync passphrase<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>. This doesn't include payment methods and addresses from Google Pay.
   </message>
   <message name="IDS_SETTINGS_PASSPHRASE_EXPLANATION_TEXT" desc="Message shown when explicit passphrase is selected.">
     Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, you'll need to <ph name="BEGIN_LINK">&lt;a href="$1" target=&quot;_blank&quot;&gt;<ex>&lt;a href="$1" target=&quot;_blank&quot;&gt;</ex></ph>reset sync<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>.
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6be44b7..ab80c9f 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1752,7 +1752,6 @@
     "//components/cookie_config",
     "//components/crx_file",
     "//components/data_reduction_proxy/content/browser",
-    "//components/data_reduction_proxy/content/common",
     "//components/data_reduction_proxy/core/browser",
     "//components/data_use_measurement/content",
     "//components/data_use_measurement/core:ascriber",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2bb33ed..5ea39e2 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2689,6 +2689,12 @@
      kOsAndroid,
      FEATURE_VALUE_TYPE(
          contextual_suggestions::kContextualSuggestionsAlternateCardLayout)},
+    {"contextual-suggestions-iph-reverse-scroll",
+     flag_descriptions::kContextualSuggestionsIPHReverseScrollName,
+     flag_descriptions::kContextualSuggestionsIPHReverseScrollDescription,
+     kOsAndroid,
+     FEATURE_VALUE_TYPE(
+         contextual_suggestions::kContextualSuggestionsIPHReverseScroll)},
     {"contextual-suggestions-opt-out",
      flag_descriptions::kContextualSuggestionsOptOutName,
      flag_descriptions::kContextualSuggestionsOptOutDescription, kOsAndroid,
@@ -2730,11 +2736,6 @@
      flag_descriptions::kEnableNtpBookmarkSuggestionsName,
      flag_descriptions::kEnableNtpBookmarkSuggestionsDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(ntp_snippets::kBookmarkSuggestionsFeature)},
-    {"enable-ntp-foreign-sessions-suggestions",
-     flag_descriptions::kEnableNtpForeignSessionsSuggestionsName,
-     flag_descriptions::kEnableNtpForeignSessionsSuggestionsDescription,
-     kOsAndroid,
-     FEATURE_VALUE_TYPE(ntp_snippets::kForeignSessionsSuggestionsFeature)},
     {"enable-ntp-suggestions-notifications",
      flag_descriptions::kEnableNtpSuggestionsNotificationsName,
      flag_descriptions::kEnableNtpSuggestionsNotificationsDescription,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 93d67a3..5ed3502 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -52,6 +52,7 @@
     &autofill::features::kAutofillScanCardholderName,
     &contextual_suggestions::kContextualSuggestionsAlternateCardLayout,
     &contextual_suggestions::kContextualSuggestionsButton,
+    &contextual_suggestions::kContextualSuggestionsIPHReverseScroll,
     &contextual_suggestions::kContextualSuggestionsOptOut,
     &features::kAppNotificationStatusMessaging,
     &features::kClearOldBrowsingData,
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 80e2c2eb..335f1f4 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -174,9 +174,6 @@
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/content_settings/core/common/content_settings_utils.h"
 #include "components/content_settings/core/common/pref_names.h"
-#include "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/dom_distiller/core/dom_distiller_switches.h"
 #include "components/dom_distiller/core/url_constants.h"
 #include "components/error_page/common/error_page_switches.h"
@@ -4320,23 +4317,14 @@
       base::FeatureList::IsEnabled(network::features::kNetworkService);
   std::vector<std::unique_ptr<content::URLLoaderThrottle>> result;
 
-  ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
-
-  if (data_reduction_proxy::params::IsEnabledWithNetworkService() && io_data) {
-    net::HttpRequestHeaders headers;
-    data_reduction_proxy::DataReductionProxyRequestOptions* request_options =
-        io_data->data_reduction_proxy_io_data()->request_options();
-    request_options->AddRequestHeader(&headers,
-                                      request_options->GeneratePageId());
-    result.push_back(std::make_unique<
-                     data_reduction_proxy::DataReductionProxyURLLoaderThrottle>(
-        headers));
-  }
-
-#if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE)
+  ProfileIOData* io_data = nullptr;
   // Null-check safe_browsing_service_ as in unit tests |resource_context| is a
   // MockResourceContext and the cast doesn't work.
-  if (io_data && safe_browsing_service_) {
+  if (safe_browsing_service_)
+    io_data = ProfileIOData::FromResourceContext(resource_context);
+
+#if defined(SAFE_BROWSING_DB_LOCAL) || defined(SAFE_BROWSING_DB_REMOTE)
+  if (io_data) {
     bool matches_enterprise_whitelist = safe_browsing::IsURLWhitelistedByPolicy(
         request.url, io_data->safe_browsing_whitelist_domains());
     if (!matches_enterprise_whitelist &&
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 892dbad..c07083c8 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1602,6 +1602,8 @@
     "power/auto_screen_brightness/modeller.h",
     "power/auto_screen_brightness/modeller_impl.cc",
     "power/auto_screen_brightness/modeller_impl.h",
+    "power/auto_screen_brightness/monotone_cubic_spline.cc",
+    "power/auto_screen_brightness/monotone_cubic_spline.h",
     "power/auto_screen_brightness/trainer.h",
     "power/auto_screen_brightness/utils.cc",
     "power/auto_screen_brightness/utils.h",
@@ -2281,6 +2283,7 @@
     "power/auto_screen_brightness/als_reader_impl_unittest.cc",
     "power/auto_screen_brightness/brightness_monitor_impl_unittest.cc",
     "power/auto_screen_brightness/modeller_impl_unittest.cc",
+    "power/auto_screen_brightness/monotone_cubic_spline_unittest.cc",
     "power/auto_screen_brightness/utils_unittest.cc",
     "power/cpu_data_collector_unittest.cc",
     "power/extension_event_observer_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc
index d80a74f..889ea5a 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include "base/bind.h"
 #include "base/location.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -54,7 +55,8 @@
     profile_ = std::make_unique<TestingProfile>();
     arc_service_manager_->set_browser_context(profile_.get());
     ArcFileSystemOperationRunner::GetFactory()->SetTestingFactoryAndUse(
-        profile_.get(), &CreateArcFileSystemOperationRunnerForTesting);
+        profile_.get(),
+        base::BindRepeating(&CreateArcFileSystemOperationRunnerForTesting));
     arc_service_manager_->arc_bridge_service()->file_system()->SetInstance(
         &fake_file_system_);
     WaitForInstanceReady(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
index 043296e..2f954bc8 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "base/bind.h"
 #include "base/location.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader.h"
@@ -81,7 +82,8 @@
     profile_ = std::make_unique<TestingProfile>();
     arc_service_manager_->set_browser_context(profile_.get());
     ArcFileSystemOperationRunner::GetFactory()->SetTestingFactoryAndUse(
-        profile_.get(), &CreateFileSystemOperationRunnerForTesting);
+        profile_.get(),
+        base::BindRepeating(&CreateFileSystemOperationRunnerForTesting));
     arc_service_manager_->arc_bridge_service()->file_system()->SetInstance(
         &fake_file_system_);
     WaitForInstanceReady(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc
index ef75678..9c215b8 100644
--- a/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc
+++ b/chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
 #include "chrome/browser/chromeos/arc/fileapi/arc_documents_provider_root.h"
@@ -126,7 +127,8 @@
     profile_ = std::make_unique<TestingProfile>();
     arc_service_manager_->set_browser_context(profile_.get());
     ArcFileSystemOperationRunner::GetFactory()->SetTestingFactoryAndUse(
-        profile_.get(), &CreateFileSystemOperationRunnerForTesting);
+        profile_.get(),
+        base::BindRepeating(&CreateFileSystemOperationRunnerForTesting));
     arc_service_manager_->arc_bridge_service()->file_system()->SetInstance(
         &fake_file_system_);
     WaitForInstanceReady(
diff --git a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc
index 55429e2..c9682dc 100644
--- a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc
+++ b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.cc
@@ -55,10 +55,7 @@
           chromeos::android_sms::GetAndroidMessagesURLWithParams(),
           web_app::LaunchContainer::kWindow, web_app::InstallSource::kInternal,
           web_app::PendingAppManager::AppInfo::kDefaultCreateShortcuts,
-          true /* override_previous_user_uninstall */,
-          // The service worker does not load in time for the installability
-          // check so we bypass it as a workaround.
-          true /* bypass_service_worker_check */),
+          true),  // override_previous_user_uninstall
       base::BindOnce(&AndroidSmsAppHelperDelegateImpl::OnAppInstalled,
                      weak_ptr_factory_.GetWeakPtr(), launch_on_install));
 }
diff --git a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc
index dea9d64..55a381e 100644
--- a/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc
+++ b/chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl_unittest.cc
@@ -83,8 +83,7 @@
       chromeos::android_sms::GetAndroidMessagesURLWithParams(),
       web_app::LaunchContainer::kWindow, web_app::InstallSource::kInternal,
       web_app::PendingAppManager::AppInfo::kDefaultCreateShortcuts,
-      true /* override_previous_user_uninstall */,
-      true /* bypass_service_worker_check */);
+      true);  // override_previous_user_uninstall
   EXPECT_EQ(expected_apps_to_install,
             test_pending_app_manager()->install_requests());
   EXPECT_EQ(ContentSetting::CONTENT_SETTING_ALLOW, GetNotificationSetting());
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.cc b/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.cc
new file mode 100644
index 0000000..80d6b80
--- /dev/null
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.cc
@@ -0,0 +1,141 @@
+// Copyright 2018 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 "chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.h"
+
+#include <cmath>
+
+#include "base/logging.h"
+#include "base/macros.h"
+
+namespace chromeos {
+namespace power {
+namespace auto_screen_brightness {
+
+namespace {
+constexpr double kTol = 1e-10;
+
+bool IsIncreasing(const std::vector<double>& data, bool is_strict) {
+  DCHECK_GT(data.size(), 1u);
+  for (size_t i = 1; i < data.size(); ++i) {
+    if (data[i] < data[i - 1] || (data[i] <= data[i - 1] && is_strict))
+      return false;
+  }
+  return true;
+}
+
+// Computes the tangents at every control point as the average of the secants,
+// while ensuring monotonicity is preserved.
+std::vector<double> ComputeTangents(const std::vector<double>& xs,
+                                    const std::vector<double>& ys,
+                                    size_t num_points) {
+  DCHECK_GT(num_points, 1u);
+  DCHECK_EQ(num_points, ys.size());
+  DCHECK(IsIncreasing(xs, true /* is_strict */));
+  DCHECK(IsIncreasing(ys, false /* is_strict */));
+
+  // Calculate the slopes of the secant lines between successive points.
+  std::vector<double> ds;
+  std::vector<double> ms;
+  for (size_t i = 0; i < num_points - 1; ++i) {
+    const double slope = (ys[i + 1] - ys[i]) / (xs[i + 1] - xs[i]);
+    DCHECK_GE(slope, 0);
+    ds.push_back(slope);
+  }
+
+  // Initialize the tangents at every point as the average of the secants, and
+  // use one-sided differences for endpoints.
+  ms.push_back(ds[0]);
+  for (size_t i = 1; i < num_points - 1; ++i) {
+    ms.push_back(0.5 * (ds[i - 1] + ds[i]));
+  }
+  ms.push_back(ds[num_points - 2]);
+
+  // Refine tangents to ensure spline monotonicity.
+  for (size_t i = 0; i < num_points - 1; ++i) {
+    if (ds[i] < kTol) {
+      // Successive points are equal, spline needs to be flat.
+      ms[i] = 0;
+      ms[i + 1] = 0;
+    } else {
+      const double a = ms[i] / ds[i];
+      const double b = ms[i + 1] / ds[i];
+      DCHECK_GE(a, 0.0);
+      DCHECK_GE(b, 0.0);
+
+      const double r = std::hypot(a, b);
+      if (r > 3.0) {
+        const double t = 3.0 / r;
+        ms[i] *= t;
+        ms[i + 1] *= t;
+      }
+    }
+  }
+
+  return ms;
+}
+
+}  // namespace
+
+MonotoneCubicSpline::MonotoneCubicSpline(const std::vector<double>& xs,
+                                         const std::vector<double>& ys)
+    : xs_(xs),
+      ys_(ys),
+      num_points_(xs.size()),
+      ms_(ComputeTangents(xs, ys, num_points_)) {}
+
+MonotoneCubicSpline::MonotoneCubicSpline(const MonotoneCubicSpline& spline) =
+    default;
+
+MonotoneCubicSpline::~MonotoneCubicSpline() = default;
+
+double MonotoneCubicSpline::Interpolate(double x) const {
+  DCHECK_GT(num_points_, 1u);
+
+  if (x <= xs_[0])
+    return ys_[0];
+
+  if (x >= xs_.back())
+    return ys_.back();
+
+  // Get |x_lower| and |x_upper| so that |x_lower| <= |x| <= |x_upper|.
+  // Size of |xs_| is small, so linear search for upper & lower
+  // bounds will be ok.
+  size_t i = 1;
+  while (i < num_points_) {
+    const double curr = xs_[i];
+    if (curr == x) {
+      // Return exact value if |x| is a control point.
+      return ys_[i];
+    }
+    if (curr > x) {
+      break;
+    }
+    ++i;
+  }
+
+  DCHECK_LT(i, num_points_);
+  const double x_upper = xs_[i];
+  const double x_lower = xs_[i - 1];
+  DCHECK_GE(x, x_lower);
+  DCHECK_LE(x, x_upper);
+
+  const double h = x_upper - x_lower;
+  const double t = (x - x_lower) / h;
+
+  return (ys_[i - 1] * (2 * t + 1) + h * ms_[i - 1] * t) * (t - 1) * (t - 1) +
+         (ys_[i] * (-2 * t + 3) + h * ms_[i] * (t - 1)) * t * t;
+}
+
+std::vector<double> MonotoneCubicSpline::GetControlPointsX() const {
+  return xs_;
+}
+
+std::vector<double> MonotoneCubicSpline::GetControlPointsY() const {
+  return ys_;
+}
+
+}  // namespace auto_screen_brightness
+}  // namespace power
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.h b/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.h
new file mode 100644
index 0000000..b2c4a8d
--- /dev/null
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.h
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_POWER_AUTO_SCREEN_BRIGHTNESS_MONOTONE_CUBIC_SPLINE_H_
+#define CHROME_BROWSER_CHROMEOS_POWER_AUTO_SCREEN_BRIGHTNESS_MONOTONE_CUBIC_SPLINE_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/optional.h"
+
+namespace chromeos {
+namespace power {
+namespace auto_screen_brightness {
+
+// This class implements monotone cubic spline from Fritsch-Carlson (1980), see
+// https://en.wikipedia.org/wiki/Monotone_cubic_interpolation
+// This class only supports non-decreasing sequence of control points.
+class MonotoneCubicSpline {
+ public:
+  // |xs| and |ys| must have the same size with at least 2 elements. |xs| must
+  // be strictly increasing and |ys| must be monotone (non-decreasing).
+  MonotoneCubicSpline(const std::vector<double>& xs,
+                      const std::vector<double>& ys);
+
+  MonotoneCubicSpline(const MonotoneCubicSpline& spline);
+
+  ~MonotoneCubicSpline();
+
+  // Returns interpolated value for |x|. If |x| is smaller|greater than
+  // smallest|largest value in |xs_|, then smallest|largest value in |ys_| will
+  // be returned.
+  double Interpolate(double x) const;
+
+  std::vector<double> GetControlPointsX() const;
+
+  std::vector<double> GetControlPointsY() const;
+
+ private:
+  const std::vector<double> xs_;
+  const std::vector<double> ys_;
+
+  const size_t num_points_;
+
+  // Tangents of control points.
+  const std::vector<double> ms_;
+};
+
+}  // namespace auto_screen_brightness
+}  // namespace power
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_POWER_AUTO_SCREEN_BRIGHTNESS_MONOTONE_CUBIC_SPLINE_H_
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline_unittest.cc
new file mode 100644
index 0000000..08505ec
--- /dev/null
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline_unittest.cc
@@ -0,0 +1,82 @@
+// Copyright 2018 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 "chrome/browser/chromeos/power/auto_screen_brightness/monotone_cubic_spline.h"
+
+#include <algorithm>
+#include <random>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace power {
+namespace auto_screen_brightness {
+
+TEST(MonotoneCubicSpline, Interpolation) {
+  const std::vector<double> xs = {0,   10,  20,   40,   60,  80,
+                                  100, 500, 1000, 2000, 3000};
+  const std::vector<double> ys = {0, 5, 10, 15, 20, 25, 30, 40, 60, 80, 1000};
+
+  MonotoneCubicSpline spline(xs, ys);
+  EXPECT_EQ(spline.GetControlPointsY().size(), xs.size());
+
+  // Spline's control points get their exact values.
+  for (size_t i = 0; i < xs.size(); ++i) {
+    EXPECT_DOUBLE_EQ(spline.Interpolate(xs[i]), ys[i]);
+  }
+
+  // Data points falling out of the range get boundary values.
+  EXPECT_DOUBLE_EQ(spline.Interpolate(-0.1), ys[0]);
+  EXPECT_DOUBLE_EQ(spline.Interpolate(4000), ys.back());
+
+  // Check interpolation results on non-control points. Results are compared
+  // with java implementation of Spline for Android.
+  const std::vector<double> ts = {2.2, 4.8, 12.3, 46.4, 70.1, 90.5, 95.8};
+  const std::vector<double> expected = {
+      1.1,    2.3999999999999995, 6.200916250000001, 16.599999999999998,
+      22.525, 28.08849264366124,  29.413985177197368};
+  for (size_t i = 0; i < ts.size(); ++i) {
+    EXPECT_DOUBLE_EQ(spline.Interpolate(ts[i]), expected[i]);
+  }
+}
+
+TEST(MonotoneCubicSpline, Monotonicity) {
+  const unsigned seed = 1;
+  std::default_random_engine generator(seed);
+  std::uniform_real_distribution<double> distribution(0.0, 200);
+
+  std::vector<double> xs;
+  std::vector<double> ys;
+  for (size_t i = 0; i < 10; ++i) {
+    xs.push_back(distribution(generator));
+    ys.push_back(distribution(generator));
+  }
+
+  // Sort xs and ensure they are strictly increasing.
+  std::sort(xs.begin(), xs.end());
+  for (size_t i = 1; i < xs.size(); ++i) {
+    if (xs[i] <= xs[i - 1]) {
+      xs[i] = xs[i - 1] + 1;
+    }
+  }
+
+  std::sort(ys.begin(), ys.end());
+
+  MonotoneCubicSpline spline(xs, ys);
+
+  std::vector<double> test_points;
+  for (size_t i = 0; i < 1000; ++i) {
+    test_points.push_back(distribution(generator));
+  }
+  std::sort(test_points.begin(), test_points.end());
+
+  for (size_t i = 1; i < test_points.size(); ++i) {
+    EXPECT_LE(spline.Interpolate(test_points[i - 1]),
+              spline.Interpolate(test_points[i]));
+  }
+}
+
+}  // namespace auto_screen_brightness
+}  // namespace power
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/usb_printer_util.cc b/chrome/browser/chromeos/printing/usb_printer_util.cc
index eabfe49..a644deb 100644
--- a/chrome/browser/chromeos/printing/usb_printer_util.cc
+++ b/chrome/browser/chromeos/printing/usb_printer_util.cc
@@ -17,7 +17,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/grit/generated_resources.h"
 #include "chromeos/printing/printer_configuration.h"
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
 #include "device/usb/usb_device.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc
index b5db0cb..b7c870f 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.cc
+++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -8,6 +8,7 @@
 #include "base/files/file_path.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/task/post_task.h"
+#include "chrome/browser/chromeos/file_system_provider/mount_path_util.h"
 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/smb_client/discovery/mdns_host_locator.h"
@@ -19,6 +20,7 @@
 #include "chrome/browser/chromeos/smb_client/smb_service_factory.h"
 #include "chrome/browser/chromeos/smb_client/smb_service_helper.h"
 #include "chrome/browser/chromeos/smb_client/smb_url.h"
+#include "chrome/browser/platform_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -187,6 +189,10 @@
   base::File::Error result =
       GetProviderService()->MountFileSystem(provider_id_, mount_options);
 
+  if (result == base::File::FILE_OK) {
+    OpenFileManager(mount_options.file_system_id);
+  }
+
   FireMountCallback(std::move(callback), TranslateErrorToMountResult(result));
 
   // Record Mount count after callback to include the new mount.
@@ -374,6 +380,13 @@
   share_finder_->RegisterHostLocator(std::move(netbios_host_locator));
 }
 
+void SmbService::OpenFileManager(const std::string& file_system_id) {
+  base::FilePath mount_path = file_system_provider::util::GetMountPath(
+      profile_, provider_id_, file_system_id);
+
+  platform_util::ShowItemInFolder(profile_, mount_path);
+}
+
 bool SmbService::IsAllowedByPolicy() const {
   return profile_->GetPrefs()->GetBoolean(prefs::kNetworkFileSharesAllowed);
 }
diff --git a/chrome/browser/chromeos/smb_client/smb_service.h b/chrome/browser/chromeos/smb_client/smb_service.h
index 4afc8dcb..04e0a7732 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.h
+++ b/chrome/browser/chromeos/smb_client/smb_service.h
@@ -137,6 +137,10 @@
   // Set up NetBios host locator.
   void SetUpNetBiosHostLocator();
 
+  // Opens |file_system_id| in the File Manager. Must only be called on a
+  // mounted share.
+  void OpenFileManager(const std::string& file_system_id);
+
   // Whether Network File Shares are allowed to be used. Controlled via policy.
   bool IsAllowedByPolicy() const;
 
diff --git a/chrome/browser/engagement/important_sites_usage_counter.cc b/chrome/browser/engagement/important_sites_usage_counter.cc
index 1d8b1c4b..b4abf678 100644
--- a/chrome/browser/engagement/important_sites_usage_counter.cc
+++ b/chrome/browser/engagement/important_sites_usage_counter.cc
@@ -63,16 +63,16 @@
 }
 
 void ImportantSitesUsageCounter::ReceiveQuotaUsageOnIOThread(
-    const std::vector<storage::UsageInfo>& usage_infos) {
+    std::vector<storage::UsageInfo> usage_infos) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&ImportantSitesUsageCounter::ReceiveQuotaUsage,
-                     base::Unretained(this), usage_infos));
+                     base::Unretained(this), std::move(usage_infos)));
 }
 
 void ImportantSitesUsageCounter::ReceiveQuotaUsage(
-    const std::vector<storage::UsageInfo>& usage_infos) {
+    std::vector<storage::UsageInfo> usage_infos) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   for (const storage::UsageInfo& info : usage_infos) {
     IncrementUsage(
diff --git a/chrome/browser/engagement/important_sites_usage_counter.h b/chrome/browser/engagement/important_sites_usage_counter.h
index 51d33630..57cc709 100644
--- a/chrome/browser/engagement/important_sites_usage_counter.h
+++ b/chrome/browser/engagement/important_sites_usage_counter.h
@@ -56,10 +56,9 @@
 
   void GetQuotaUsageOnIOThread();
 
-  void ReceiveQuotaUsageOnIOThread(
-      const std::vector<storage::UsageInfo>& usage_infos);
+  void ReceiveQuotaUsageOnIOThread(std::vector<storage::UsageInfo> usage_infos);
 
-  void ReceiveQuotaUsage(const std::vector<storage::UsageInfo>& usage_infos);
+  void ReceiveQuotaUsage(std::vector<storage::UsageInfo> usage_infos);
 
   void ReceiveLocalStorageUsage(
       const std::vector<content::LocalStorageUsageInfo>& storage_infos);
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc
index c658439..eaac524 100644
--- a/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -248,7 +248,8 @@
 }
 
 #if defined(OS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopActions) {
+// TODO(https://crbug.com/894016): flaky.
+IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopActions) {
   AutomationManagerAura::GetInstance()->Enable();
   // Trigger the shelf subtree to be computed.
   ash::Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index 73f82fe..f2e042c 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -69,7 +69,6 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_function_dispatcher.h"
@@ -999,10 +998,6 @@
             &error_))
     return false;
 
-  content::StoragePartition* storage_partition =
-      BrowserContext::GetStoragePartition(
-          render_frame_host()->GetProcess()->GetBrowserContext(),
-          render_frame_host()->GetSiteInstance());
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("downloads_api_run_async", R"(
         semantics {
@@ -1036,8 +1031,7 @@
       new download::DownloadUrlParameters(
           download_url, render_frame_host()->GetProcess()->GetID(),
           render_frame_host()->GetRenderViewHost()->GetRoutingID(),
-          render_frame_host()->GetRoutingID(),
-          storage_partition->GetURLRequestContext(), traffic_annotation));
+          render_frame_host()->GetRoutingID(), traffic_annotation));
 
   base::FilePath creator_suggested_filename;
   if (options.filename.get()) {
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc
index 0a04b25..e99fc46 100644
--- a/chrome/browser/extensions/bookmark_app_helper.cc
+++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -370,7 +370,7 @@
       params.valid_primary_icon = true;
       params.valid_manifest = true;
       // Do not wait for a service worker if it doesn't exist.
-      params.has_worker = !bypass_service_worker_check_;
+      params.has_worker = true;
       installable_manager_->GetData(
           params, base::Bind(&BookmarkAppHelper::OnDidPerformInstallableCheck,
                              weak_factory_.GetWeakPtr()));
diff --git a/chrome/browser/extensions/bookmark_app_helper.h b/chrome/browser/extensions/bookmark_app_helper.h
index 41ef9ad..493c069 100644
--- a/chrome/browser/extensions/bookmark_app_helper.h
+++ b/chrome/browser/extensions/bookmark_app_helper.h
@@ -106,12 +106,6 @@
 
   bool create_shortcuts() const { return create_shortcuts_; }
 
-  // If called, the installability check won't test for a service worker.
-  void set_bypass_service_worker_check() {
-    DCHECK(is_default_app());
-    bypass_service_worker_check_ = true;
-  }
-
   // If called, the installed app will launch in |launch_type|. User might still
   // be able to change the launch type depending on the type of app.
   void set_forced_launch_type(LaunchType launch_type) {
@@ -189,8 +183,6 @@
 
   bool create_shortcuts_ = true;
 
-  bool bypass_service_worker_check_ = false;
-
   // The mechanism via which the app creation was triggered.
   WebappInstallSource install_source_;
 
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index c1f220b9..f62fd7d 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -54,7 +54,6 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_registry.h"
@@ -659,9 +658,6 @@
       contents->GetRenderViewHost()->GetRoutingID();
 
   content::RenderFrameHost* render_frame_host = contents->GetMainFrame();
-  content::StoragePartition* storage_partition =
-      BrowserContext::GetStoragePartition(profile_,
-                                          render_frame_host->GetSiteInstance());
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("webstore_installer", R"(
         semantics {
@@ -694,8 +690,7 @@
         })");
   std::unique_ptr<DownloadUrlParameters> params(new DownloadUrlParameters(
       download_url_, render_process_host_id, render_view_host_routing_id,
-      render_frame_host->GetRoutingID(),
-      storage_partition->GetURLRequestContext(), traffic_annotation));
+      render_frame_host->GetRoutingID(), traffic_annotation));
   params->set_file_path(file);
   if (controller.GetVisibleEntry()) {
     content::Referrer referrer = content::Referrer::SanitizeForRequest(
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 3db50c6..64a77ff 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -241,6 +241,12 @@
 const char kContextualSuggestionsButtonDescription[] =
     "If enabled, shows a button to trigger contextual suggestions.";
 
+const char kContextualSuggestionsIPHReverseScrollName[] =
+    "Contextual Suggestions IPH Reverse Scroll";
+const char kContextualSuggestionsIPHReverseScrollDescription[] =
+    "Require a reverse scroll before showing in-product help for contextual "
+    "suggestions.";
+
 const char kContextualSuggestionsOptOutName[] =
     "Contextual Suggestions Opt-out";
 const char kContextualSuggestionsOptOutDescription[] =
@@ -2387,12 +2393,6 @@
     "If enabled, the list of content suggestions on the New Tab page will "
     "contain recently visited bookmarks.";
 
-const char kEnableNtpForeignSessionsSuggestionsName[] =
-    "Show recent foreign tabs on the New Tab page";
-const char kEnableNtpForeignSessionsSuggestionsDescription[] =
-    "If enabled, the list of content suggestions on the New Tab page will "
-    "contain recent foreign tabs.";
-
 const char kEnableNtpOfflinePageDownloadSuggestionsName[] =
     "Show offline page downloads on the New Tab page";
 const char kEnableNtpOfflinePageDownloadSuggestionsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 6d1dc9e0..d93c4c2c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -172,6 +172,9 @@
 extern const char kContextualSuggestionsButtonName[];
 extern const char kContextualSuggestionsButtonDescription[];
 
+extern const char kContextualSuggestionsIPHReverseScrollName[];
+extern const char kContextualSuggestionsIPHReverseScrollDescription[];
+
 extern const char kContextualSuggestionsOptOutName[];
 extern const char kContextualSuggestionsOptOutDescription[];
 
@@ -1447,9 +1450,6 @@
 extern const char kEnableNtpBookmarkSuggestionsName[];
 extern const char kEnableNtpBookmarkSuggestionsDescription[];
 
-extern const char kEnableNtpForeignSessionsSuggestionsName[];
-extern const char kEnableNtpForeignSessionsSuggestionsDescription[];
-
 extern const char kEnableNtpOfflinePageDownloadSuggestionsName[];
 extern const char kEnableNtpOfflinePageDownloadSuggestionsDescription[];
 
diff --git a/chrome/browser/media/webrtc/webrtc_audio_quality_browsertest.cc b/chrome/browser/media/webrtc/webrtc_audio_quality_browsertest.cc
deleted file mode 100644
index d3b2f72..0000000
--- a/chrome/browser/media/webrtc/webrtc_audio_quality_browsertest.cc
+++ /dev/null
@@ -1,876 +0,0 @@
-// Copyright 2013 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 <stddef.h>
-
-#include <ctime>
-
-#include "base/command_line.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/format_macros.h"
-#include "base/macros.h"
-#include "base/process/launch.h"
-#include "base/process/process.h"
-#include "base/scoped_native_library.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_restrictions.h"
-#include "build/build_config.h"
-#include "chrome/browser/media/webrtc/webrtc_browsertest_audio.h"
-#include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
-#include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/browser_test_utils.h"
-#include "media/base/audio_parameters.h"
-#include "media/base/media_switches.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "testing/perf/perf_test.h"
-
-namespace {
-
-// This is a test-only flag that tells the test where to dump its recordings.
-static const char kWebRtcSaveAudioRecordingsIn[] =
-    "webrtc_save_audio_recordings_in";
-
-static const base::FilePath::CharType kReferenceFile[] =
-    FILE_PATH_LITERAL("speech_44kHz_16bit_stereo.wav");
-
-// The javascript will load the reference file relative to its location,
-// which is in /webrtc on the web server. The files we are looking for are in
-// webrtc/resources in the chrome/test/data folder.
-static const char kReferenceFileRelativeUrl[] =
-    "resources/speech_44kHz_16bit_stereo.wav";
-
-static const char kWebRtcAudioTestHtmlPage[] =
-    "/webrtc/webrtc_audio_quality_test.html";
-
-// For the AGC test, there are 6 speech segments split on silence. If one
-// segment is significantly different in length compared to the same segment in
-// the reference file, there's something fishy going on.
-const int kMaxAgcSegmentDiffMs =
-#if defined(OS_MACOSX)
-  // Something is different on Mac; http://crbug.com/477653.
-  600;
-#else
-  200;
-#endif
-
-
-}  // namespace
-
-// Test we can set up a WebRTC call and play audio through it.
-//
-// If you're not a googler and want to run this test, you need to provide a
-// pesq binary for your platform (and sox.exe on windows). Read more on how
-// resources are managed in chrome/test/data/webrtc/resources/README.
-//
-// This test will only work on machines that have been configured to record
-// their own input.
-//
-// On Linux:
-// 1. # sudo apt-get install pavucontrol sox
-// 2. For the user who will run the test: # pavucontrol
-// 3. In a separate terminal, # arecord dummy
-// 4. In pavucontrol, go to the recording tab.
-// 5. For the ALSA plugin [aplay]: ALSA Capture from, change from <x> to
-//    <Monitor of x>, where x is whatever your primary sound device is called.
-// 6. Try launching chrome as the target user on the target machine, try
-//    playing, say, a YouTube video, and record with # arecord -f dat tmp.dat.
-//    Verify the recording with aplay (should have recorded what you played
-//    from chrome).
-//
-// Note: the volume for ALL your input devices will be forced to 100% by
-//       running this test on Linux.
-//
-// On Mac:
-// TODO(phoglund): download sox from gs instead.
-// 1. Get SoundFlower: http://rogueamoeba.com/freebies/soundflower/download.php
-// 2. Install it + reboot.
-// 3. Install MacPorts (http://www.macports.org/).
-// 4. Install sox: sudo port install sox.
-// 5. (For Chrome bots) Ensure sox and rec are reachable from the env the test
-//    executes in (sox and rec tends to install in /opt/, which generally isn't
-//    in the Chrome bots' env). For instance, run
-//    sudo ln -s /opt/local/bin/rec /usr/local/bin/rec
-//    sudo ln -s /opt/local/bin/sox /usr/local/bin/sox
-// 6. In Sound Preferences, set both input and output to Soundflower (2ch).
-//    Note: You will no longer hear audio on this machine, and it will no
-//    longer use any built-in mics.
-// 7. Try launching chrome as the target user on the target machine, try
-//    playing, say, a YouTube video, and record with 'rec test.wav trim 0 5'.
-//    Stop the video in chrome and try playing back the file; you should hear
-//    a recording of the video (note; if you play back on the target machine
-//    you must revert the changes in step 3 first).
-//
-// On Windows 7:
-// 1. Control panel > Sound > Manage audio devices.
-// 2. In the recording tab, right-click in an empty space in the pane with the
-//    devices. Tick 'show disabled devices'.
-// 3. You should see a 'stereo mix' device - this is what your speakers output.
-//    If you don't have one, your driver doesn't support stereo mix devices.
-//    Some drivers use different names for the mix device though (like "Wave").
-//    Right click > Properties.
-// 4. Ensure "listen to this device" is unchecked, otherwise you get echo.
-// 5. Ensure the mix device is the default recording device.
-// 6. Launch chrome and try playing a video with sound. You should see
-//    in the volume meter for the mix device. Configure the mix device to have
-//    50 / 100 in level. Also go into the playback tab, right-click Speakers,
-//    and set that level to 50 / 100. Otherwise you will get distortion in
-//    the recording.
-class WebRtcAudioQualityBrowserTest : public WebRtcTestBase {
- public:
-  WebRtcAudioQualityBrowserTest() {}
-  void SetUpInProcessBrowserTestFixture() override {
-    DetectErrorsInJavaScript();  // Look for errors in our rather complex js.
-  }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    EXPECT_FALSE(command_line->HasSwitch(
-        switches::kUseFakeUIForMediaStream));
-
-    wav_dump_path_ =
-        command_line->GetSwitchValuePath(kWebRtcSaveAudioRecordingsIn);
-    if (wav_dump_path_.empty()) {
-      EXPECT_TRUE(base::GetTempDir(&wav_dump_path_));
-    }
-
-    LOG(INFO) << "Dumping recordings in " << wav_dump_path_;
-
-    // The WebAudio-based tests don't care what devices are available to
-    // getUserMedia, and the getUserMedia-based tests will play back a file
-    // through the fake device using using --use-file-for-fake-audio-capture.
-    command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
-
-    // Add loopback interface such that there is always connectivity.
-    command_line->AppendSwitch(switches::kAllowLoopbackInPeerConnection);
-
-    reference_file_ = test::GetReferenceFilesDir().Append(kReferenceFile);
-    ConfigureFakeDeviceToPlayFile(reference_file_);
-  }
-
-  void ConfigureFakeDeviceToPlayFile(const base::FilePath& wav_file_path) {
-    base::CommandLine::ForCurrentProcess()->AppendSwitchNative(
-        switches::kUseFileForFakeAudioCapture,
-        wav_file_path.value() + FILE_PATH_LITERAL("%noloop"));
-  }
-
-  void AddAudioFileToWebAudio(const std::string& input_file_relative_url,
-                              content::WebContents* tab_contents) {
-    // This calls into webaudio.js.
-    EXPECT_EQ("ok-added", ExecuteJavascript(
-        "addAudioFile('" + input_file_relative_url + "')", tab_contents));
-  }
-
-  void PlayAudioFileThroughWebAudio(content::WebContents* tab_contents) {
-    EXPECT_EQ("ok-playing", ExecuteJavascript("playAudioFile()", tab_contents));
-  }
-
-  content::WebContents* OpenPageWithoutGetUserMedia(const char* url) {
-    chrome::AddTabAt(browser(), GURL(), -1, true);
-    ui_test_utils::NavigateToURL(
-        browser(), embedded_test_server()->GetURL(url));
-    content::WebContents* tab =
-        browser()->tab_strip_model()->GetActiveWebContents();
-
-    // Prepare the peer connections manually in this test since we don't add
-    // getUserMedia-derived media streams in this test like the other tests.
-    EXPECT_EQ("ok-peerconnection-created",
-              ExecuteJavascript("preparePeerConnection()", tab));
-    return tab;
-  }
-
-  void MuteMediaElement(const std::string& element_id,
-                        content::WebContents* tab_contents) {
-    EXPECT_EQ("ok-muted", ExecuteJavascript(
-        "setMediaElementMuted('" + element_id + "', true)", tab_contents));
-  }
-
-  base::FilePath CreateTemporaryWaveFile() {
-    base::FilePath filename;
-    EXPECT_TRUE(base::CreateTemporaryFileInDir(wav_dump_path_, &filename));
-
-    base::FilePath wav_filename =
-        filename.AddExtension(FILE_PATH_LITERAL(".wav"));
-    EXPECT_TRUE(base::Move(filename, wav_filename));
-    return wav_filename;
-  }
-
-  void DeleteFileUnlessTestFailed(const base::FilePath& path, bool recursive) {
-    if (::testing::Test::HasFailure())
-      printf("Test failed; keeping recording(s) at\n\t%" PRFilePath ".\n",
-             path.value().c_str());
-    else
-      EXPECT_TRUE(base::DeleteFile(path, recursive));
-  }
-
-  std::vector<base::FilePath> ListWavFilesInDir(const base::FilePath& dir) {
-    base::FileEnumerator files(dir, false, base::FileEnumerator::FILES,
-                               FILE_PATH_LITERAL("*.wav"));
-
-    std::vector<base::FilePath> result;
-    for (base::FilePath name = files.Next(); !name.empty(); name = files.Next())
-      result.push_back(name);
-    return result;
-  }
-
-  // Sox is the "Swiss army knife" of audio processing. We mainly use it for
-  // silence trimming. See http://sox.sourceforge.net.
-  base::CommandLine MakeSoxCommandLine() {
-#if defined(OS_WIN)
-    base::FilePath sox_path = test::GetToolForPlatform("sox");
-    if (!base::PathExists(sox_path)) {
-      LOG(ERROR) << "Missing sox.exe binary in " << sox_path.value()
-                 << "; you may have to provide this binary yourself.";
-      return base::CommandLine(base::CommandLine::NO_PROGRAM);
-    }
-    base::CommandLine command_line(sox_path);
-#else
-    // TODO(phoglund): call checked-in sox rather than system sox on mac/linux.
-    // Same for rec invocations on Mac, above.
-    base::CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("sox")));
-#endif
-    return command_line;
-  }
-
-  // Looks for 0.2 second audio segments surrounded by silences under 0.3% audio
-  // power and splits the input file on those silences. Output files are written
-  // according to the output file template (e.g. /tmp/out.wav writes
-  // /tmp/out001.wav, /tmp/out002.wav, etc if there are two silence-padded
-  // regions in the file). The silences between speech segments must be at
-  // least 500 ms for this to be reliable.
-  bool SplitFileOnSilence(const base::FilePath& input_file,
-                          const base::FilePath& output_file_template) {
-    base::CommandLine command_line = MakeSoxCommandLine();
-    if (command_line.GetProgram().empty())
-      return false;
-
-    // These are experimentally determined and work on the files we use.
-    const char* kAbovePeriods = "1";
-    const char* kUnderPeriods = "1";
-    const char* kDuration = "0.2";
-    const char* kTreshold = "0.5%";
-    command_line.AppendArgPath(input_file);
-    command_line.AppendArgPath(output_file_template);
-    command_line.AppendArg("silence");
-    command_line.AppendArg(kAbovePeriods);
-    command_line.AppendArg(kDuration);
-    command_line.AppendArg(kTreshold);
-    command_line.AppendArg(kUnderPeriods);
-    command_line.AppendArg(kDuration);
-    command_line.AppendArg(kTreshold);
-    command_line.AppendArg(":");
-    command_line.AppendArg("newfile");
-    command_line.AppendArg(":");
-    command_line.AppendArg("restart");
-
-    DVLOG(0) << "Running " << command_line.GetCommandLineString();
-    std::string result;
-    bool ok = base::GetAppOutput(command_line, &result);
-    DVLOG(0) << "Output was:\n\n" << result;
-    return ok;
-  }
-
-  // Removes silence from beginning and end of the |input_audio_file| and writes
-  // the result to the |output_audio_file|. Returns true on success.
-  bool RemoveSilence(const base::FilePath& input_file,
-                     const base::FilePath& output_file) {
-    // SOX documentation for silence command:
-    // http://sox.sourceforge.net/sox.html To remove the silence from both
-    // beginning and end of the audio file, we call sox silence command twice:
-    // once on normal file and again on its reverse, then we reverse the final
-    // output. Silence parameters are (in sequence): ABOVE_PERIODS: The period
-    // for which silence occurs. Value 1 is used for
-    //                 silence at beginning of audio.
-    // DURATION: the amount of time in seconds that non-silence must be detected
-    //           before sox stops trimming audio.
-    // THRESHOLD: value used to indicate what sample value is treats as silence.
-    const char* kAbovePeriods = "1";
-    const char* kDuration = "2";
-    const char* kTreshold = "1.5%";
-
-    base::CommandLine command_line = MakeSoxCommandLine();
-    if (command_line.GetProgram().empty())
-      return false;
-    command_line.AppendArgPath(input_file);
-    command_line.AppendArgPath(output_file);
-    command_line.AppendArg("silence");
-    command_line.AppendArg(kAbovePeriods);
-    command_line.AppendArg(kDuration);
-    command_line.AppendArg(kTreshold);
-    command_line.AppendArg("reverse");
-    command_line.AppendArg("silence");
-    command_line.AppendArg(kAbovePeriods);
-    command_line.AppendArg(kDuration);
-    command_line.AppendArg(kTreshold);
-    command_line.AppendArg("reverse");
-
-    DVLOG(0) << "Running " << command_line.GetCommandLineString();
-    std::string result;
-    bool ok = base::GetAppOutput(command_line, &result);
-    DVLOG(0) << "Output was:\n\n" << result;
-    return ok;
-  }
-
-  // Splits |to_split| into sub-files based on silence. The file you use must
-  // have at least 500 ms periods of silence between speech segments for this to
-  // be reliable.
-  void SplitFileOnSilenceIntoDir(const base::FilePath& to_split,
-                                 const base::FilePath& workdir) {
-    // First trim beginning and end since they are tricky for the splitter.
-    base::FilePath trimmed_audio = CreateTemporaryWaveFile();
-
-    ASSERT_TRUE(RemoveSilence(to_split, trimmed_audio));
-    DVLOG(0) << "Trimmed silence: " << trimmed_audio.value() << std::endl;
-
-    ASSERT_TRUE(SplitFileOnSilence(
-        trimmed_audio, workdir.Append(FILE_PATH_LITERAL("output.wav"))));
-    DeleteFileUnlessTestFailed(trimmed_audio, false);
-  }
-
-  void AnalyzeSegmentsAndPrintResult(
-      const std::vector<base::FilePath>& ref_segments,
-      const std::vector<base::FilePath>& actual_segments,
-      const base::FilePath& reference_file,
-      const std::string& perf_modifier) {
-    ASSERT_GT(ref_segments.size(), 0u)
-        << "Failed to split reference file on silence; sox is likely broken.";
-    ASSERT_EQ(ref_segments.size(), actual_segments.size())
-        << "The recording did not result in the same number of audio segments "
-        << "after on splitting on silence; WebRTC must have deformed the audio "
-        << "too much.";
-
-    for (size_t i = 0; i < ref_segments.size(); i++) {
-      float difference_in_decibel =
-          AnalyzeOneSegment(ref_segments[i], actual_segments[i], i);
-      std::string trace_name = MakeTraceName(reference_file, i);
-      perf_test::PrintResult("agc_energy_diff", perf_modifier, trace_name,
-                             difference_in_decibel, "dB", false);
-    }
-  }
-
-  // Computes the difference between the actual and reference segment. A
-  // positive number x means the actual file is x dB stronger than the
-  // reference.
-  float AnalyzeOneSegment(const base::FilePath& ref_segment,
-                          const base::FilePath& actual_segment,
-                          int segment_number) {
-    media::AudioParameters ref_parameters;
-    media::AudioParameters actual_parameters;
-    float ref_energy =
-        test::ComputeAudioEnergyForWavFile(ref_segment, &ref_parameters);
-    float actual_energy =
-        test::ComputeAudioEnergyForWavFile(actual_segment, &actual_parameters);
-
-    base::TimeDelta difference_in_length =
-        ref_parameters.GetBufferDuration() -
-        actual_parameters.GetBufferDuration();
-
-    EXPECT_LE(difference_in_length,
-              base::TimeDelta::FromMilliseconds(kMaxAgcSegmentDiffMs))
-        << "Segments differ " << difference_in_length.InMilliseconds() << " ms "
-        << "in length for segment " << segment_number << "; we're likely "
-        << "comparing unrelated segments or silence splitting is busted.";
-
-    return actual_energy - ref_energy;
-  }
-
-  void ComputeAndPrintPesqResults(const base::FilePath& reference_file,
-                                  const base::FilePath& recording,
-                                  const std::string& perf_modifier) {
-    base::FilePath trimmed_reference = CreateTemporaryWaveFile();
-    base::FilePath trimmed_recording = CreateTemporaryWaveFile();
-
-    ASSERT_TRUE(RemoveSilence(reference_file, trimmed_reference));
-    ASSERT_TRUE(RemoveSilence(recording, trimmed_recording));
-
-    std::string raw_mos;
-    std::string mos_lqo;
-    bool succeeded = RunPesq(trimmed_reference, trimmed_recording, 16000,
-                             &raw_mos, &mos_lqo);
-    EXPECT_TRUE(succeeded) << "Failed to run PESQ.";
-    if (succeeded) {
-      perf_test::PrintResult("audio_pesq", perf_modifier, "raw_mos", raw_mos,
-                             "score", true);
-      perf_test::PrintResult("audio_pesq", perf_modifier, "mos_lqo", mos_lqo,
-                             "score", true);
-    }
-
-    if (CanParseAsFloat(mos_lqo) && atof(mos_lqo.c_str()) < 3.0f) {
-      // If we keep the recordings, it's possible for the WebRTC bot recipes to
-      // upload them and make them available on the build.
-      printf("Suspiciously low MOS-LQO score: keeping recordings...\n");
-      return;
-    } else {
-      DeleteFileUnlessTestFailed(trimmed_reference, false);
-      DeleteFileUnlessTestFailed(trimmed_recording, false);
-    }
-  }
-
-  bool CanParseAsFloat(const std::string& value) {
-    return atof(value.c_str()) != 0 || value == "0";
-  }
-
-  // Runs PESQ to compare |reference_file| to a |actual_file|. The |sample_rate|
-  // can be either 16000 or 8000.
-  //
-  // PESQ is only mono-aware, so the files should preferably be recorded in
-  // mono. Furthermore it expects the file to be 16 rather than 32 bits, even
-  // though 32 bits might work. The audio bandwidth of the two files should be
-  // the same e.g. don't compare a 32 kHz file to a 8 kHz file.
-  //
-  // The raw score in MOS is written to |raw_mos|, whereas the MOS-LQO score is
-  // written to mos_lqo. The scores are returned as floats in string form (e.g.
-  // "3.145", etc). Returns true on success.
-  bool RunPesq(const base::FilePath& reference_file,
-               const base::FilePath& actual_file,
-               int sample_rate,
-               std::string* raw_mos,
-               std::string* mos_lqo) {
-    // PESQ will break if the paths are too long (!).
-    EXPECT_LT(reference_file.value().length(), 128u);
-    EXPECT_LT(actual_file.value().length(), 128u);
-
-    base::FilePath pesq_path = test::GetToolForPlatform("pesq");
-    if (!base::PathExists(pesq_path)) {
-      LOG(ERROR) << "Missing PESQ binary in " << pesq_path.value()
-                 << "; you may have to provide this binary yourself.";
-      return false;
-    }
-
-    base::CommandLine command_line(pesq_path);
-    command_line.AppendArg(base::StringPrintf("+%d", sample_rate));
-    command_line.AppendArgPath(reference_file);
-    command_line.AppendArgPath(actual_file);
-
-    DVLOG(0) << "Running " << command_line.GetCommandLineString();
-    std::string result;
-    if (!base::GetAppOutput(command_line, &result)) {
-      LOG(ERROR) << "Failed to run PESQ.";
-      return false;
-    }
-    DVLOG(0) << "Output was:\n\n" << result;
-
-    const std::string result_anchor = "Prediction (Raw MOS, MOS-LQO):  = ";
-    std::size_t anchor_pos = result.find(result_anchor);
-    if (anchor_pos == std::string::npos) {
-      LOG(ERROR)
-          << "PESQ was not able to compute a score; we probably recorded "
-          << "only silence.";
-      return false;
-    }
-
-    // There are two tab-separated numbers on the format x.xxx, e.g. 5 chars
-    // each.
-    std::size_t first_number_pos = anchor_pos + result_anchor.length();
-    *raw_mos = result.substr(first_number_pos, 5);
-    EXPECT_TRUE(CanParseAsFloat(*raw_mos)) << "Failed to parse raw MOS number.";
-    *mos_lqo = result.substr(first_number_pos + 5 + 1, 5);
-    EXPECT_TRUE(CanParseAsFloat(*mos_lqo)) << "Failed to parse MOS LQO number.";
-
-    return true;
-  }
-
-  std::string MakeTraceName(const base::FilePath& ref_filename,
-                            size_t segment_number) {
-    std::string ascii_filename;
-#if defined(OS_WIN)
-    ascii_filename = base::WideToUTF8(ref_filename.BaseName().value());
-#else
-    ascii_filename = ref_filename.BaseName().value();
-#endif
-    return base::StringPrintf("%s_segment_%" PRIuS, ascii_filename.c_str(),
-                              segment_number);
-  }
-
- protected:
-  void TestAutoGainControl(const std::string& constraints,
-                           const std::string& perf_modifier);
-  void SetupAndRecordAudioCall(const base::FilePath& recording,
-                               const std::string& constraints,
-                               const base::TimeDelta recording_time);
-  void TestWithFakeDeviceGetUserMedia(const std::string& constraints,
-                                      const std::string& perf_modifier);
-
-  const base::FilePath& reference_file() { return reference_file_; }
-
- private:
-  base::FilePath reference_file_;
-  base::FilePath wav_dump_path_;
-};
-
-namespace {
-
-class AudioRecorder {
- public:
-  AudioRecorder() {}
-  ~AudioRecorder() {}
-
-  // Starts the recording program for the specified duration. Returns true
-  // on success. We record in 16-bit 44.1 kHz Stereo (mostly because that's
-  // what SoundRecorder.exe will give us and we can't change that).
-  bool StartRecording(base::TimeDelta recording_time,
-                      const base::FilePath& output_file) {
-    EXPECT_FALSE(recording_application_.IsValid())
-        << "Tried to record, but is already recording.";
-
-    int duration_sec = static_cast<int>(recording_time.InSeconds());
-    base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-
-#if defined(OS_WIN)
-    // This disable is required to run SoundRecorder.exe on 64-bit Windows
-    // from a 32-bit binary. We need to load the wow64 disable function from
-    // the DLL since it doesn't exist on Windows XP.
-    base::ScopedNativeLibrary kernel32_lib(base::FilePath(L"kernel32"));
-    if (kernel32_lib.is_valid()) {
-      typedef BOOL (WINAPI* Wow64DisableWow64FSRedirection)(PVOID*);
-      Wow64DisableWow64FSRedirection wow_64_disable_wow_64_fs_redirection;
-      wow_64_disable_wow_64_fs_redirection =
-          reinterpret_cast<Wow64DisableWow64FSRedirection>(
-              kernel32_lib.GetFunctionPointer(
-                  "Wow64DisableWow64FsRedirection"));
-      if (wow_64_disable_wow_64_fs_redirection != NULL) {
-        PVOID* ignored = NULL;
-        wow_64_disable_wow_64_fs_redirection(ignored);
-      }
-    }
-
-    char duration_in_hms[128] = {0};
-    struct tm duration_tm = {0};
-    duration_tm.tm_sec = duration_sec;
-    EXPECT_NE(0u, strftime(duration_in_hms, arraysize(duration_in_hms),
-                           "%H:%M:%S", &duration_tm));
-
-    command_line.SetProgram(
-        base::FilePath(FILE_PATH_LITERAL("SoundRecorder.exe")));
-    command_line.AppendArg("/FILE");
-    command_line.AppendArgPath(output_file);
-    command_line.AppendArg("/DURATION");
-    command_line.AppendArg(duration_in_hms);
-#elif defined(OS_MACOSX)
-    command_line.SetProgram(base::FilePath("rec"));
-    command_line.AppendArg("-b");
-    command_line.AppendArg("16");
-    command_line.AppendArg("-q");
-    command_line.AppendArgPath(output_file);
-    command_line.AppendArg("trim");
-    command_line.AppendArg("0");
-    command_line.AppendArg(base::IntToString(duration_sec));
-#else
-    command_line.SetProgram(base::FilePath("arecord"));
-    command_line.AppendArg("-d");
-    command_line.AppendArg(base::IntToString(duration_sec));
-    command_line.AppendArg("-f");
-    command_line.AppendArg("cd");
-    command_line.AppendArg("-c");
-    command_line.AppendArg("2");
-    command_line.AppendArgPath(output_file);
-#endif
-
-    DVLOG(0) << "Running " << command_line.GetCommandLineString();
-    recording_application_ =
-        base::LaunchProcess(command_line, base::LaunchOptions());
-    return recording_application_.IsValid();
-  }
-
-  // Joins the recording program. Returns true on success.
-  bool WaitForRecordingToEnd() {
-    int exit_code = -1;
-    recording_application_.WaitForExit(&exit_code);
-    return exit_code == 0;
-  }
-
- private:
-  base::Process recording_application_;
-};
-
-bool ForceMicrophoneVolumeTo100Percent() {
-#if defined(OS_WIN)
-  // Note: the force binary isn't in tools since it's one of our own.
-  base::CommandLine command_line(test::GetReferenceFilesDir().Append(
-      FILE_PATH_LITERAL("force_mic_volume_max.exe")));
-  DVLOG(0) << "Running " << command_line.GetCommandLineString();
-  std::string result;
-  if (!base::GetAppOutput(command_line, &result)) {
-    LOG(ERROR) << "Failed to set source volume: output was " << result;
-    return false;
-  }
-#elif defined(OS_MACOSX)
-  base::CommandLine command_line(
-      base::FilePath(FILE_PATH_LITERAL("osascript")));
-  command_line.AppendArg("-e");
-  command_line.AppendArg("set volume input volume 100");
-  command_line.AppendArg("-e");
-  command_line.AppendArg("set volume output volume 85");
-
-  std::string result;
-  if (!base::GetAppOutput(command_line, &result)) {
-    LOG(ERROR) << "Failed to set source volume: output was " << result;
-    return false;
-  }
-#else
-  // Just force the volume of, say the first 5 devices. A machine will rarely
-  // have more input sources than that. This is way easier than finding the
-  // input device we happen to be using.
-  for (int device_index = 0; device_index < 5; ++device_index) {
-    std::string result;
-    const std::string kHundredPercentVolume = "65536";
-    base::CommandLine command_line(base::FilePath(FILE_PATH_LITERAL("pacmd")));
-    command_line.AppendArg("set-source-volume");
-    command_line.AppendArg(base::IntToString(device_index));
-    command_line.AppendArg(kHundredPercentVolume);
-    DVLOG(0) << "Running " << command_line.GetCommandLineString();
-    if (!base::GetAppOutput(command_line, &result)) {
-      LOG(ERROR) << "Failed to set source volume: output was " << result;
-      return false;
-    }
-  }
-#endif
-  return true;
-}
-
-}  // namespace
-
-// Sets up a two-way WebRTC call and records its output to |recording|, using
-// getUserMedia.
-//
-// |reference_file| should have at least five seconds of silence in the
-// beginning: otherwise all the reference audio will not be picked up by the
-// recording. Note that the reference file will start playing as soon as the
-// audio device is up following the getUserMedia call in the left tab. The time
-// it takes to negotiate a call isn't deterministic, but five seconds should be
-// plenty of time. Similarly, the recording time should be enough to catch the
-// whole reference file. If you then silence-trim the reference file and actual
-// file, you should end up with two time-synchronized files.
-void WebRtcAudioQualityBrowserTest::SetupAndRecordAudioCall(
-    const base::FilePath& recording,
-    const std::string& constraints,
-    const base::TimeDelta recording_time) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  ASSERT_TRUE(test::HasReferenceFilesInCheckout());
-  ASSERT_TRUE(ForceMicrophoneVolumeTo100Percent());
-
-  // Create a two-way call. Mute one of the receivers though; that way it will
-  // be receiving audio bytes, but we will not be playing out of both elements.
-  GURL test_page = embedded_test_server()->GetURL(kWebRtcAudioTestHtmlPage);
-  content::WebContents* left_tab =
-      OpenPageAndGetUserMediaInNewTabWithConstraints(test_page, constraints);
-  SetupPeerconnectionWithLocalStream(left_tab);
-  MuteMediaElement("remote-view", left_tab);
-
-  content::WebContents* right_tab =
-      OpenPageAndGetUserMediaInNewTabWithConstraints(test_page, constraints);
-  SetupPeerconnectionWithLocalStream(right_tab);
-
-  AudioRecorder recorder;
-  ASSERT_TRUE(recorder.StartRecording(recording_time, recording));
-
-  NegotiateCall(left_tab, right_tab);
-
-  ASSERT_TRUE(recorder.WaitForRecordingToEnd());
-  DVLOG(0) << "Done recording to " << recording.value() << std::endl;
-
-  HangUp(left_tab);
-}
-
-void WebRtcAudioQualityBrowserTest::TestWithFakeDeviceGetUserMedia(
-    const std::string& constraints,
-    const std::string& perf_modifier) {
-  if (OnWin8OrHigher()) {
-    // http://crbug.com/379798.
-    LOG(ERROR) << "This test is not implemented for Win8 or higher.";
-    return;
-  }
-
-  base::FilePath recording = CreateTemporaryWaveFile();
-
-  ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall(
-      recording, constraints, base::TimeDelta::FromSeconds(30)));
-
-  ComputeAndPrintPesqResults(reference_file(), recording, perf_modifier);
-  DeleteFileUnlessTestFailed(recording, false);
-}
-
-#if defined(OS_LINUX) || defined(OS_WIN)
-#define MAYBE_MANUAL_TestCallQualityWithAudioFromFakeDevice \
-  MANUAL_TestCallQualityWithAudioFromFakeDevice
-#else
-// Not implemented on Android, ChromeOS etc.
-#define MAYBE_MANUAL_TestCallQualityWithAudioFromFakeDevice \
-  DISABLED_MANUAL_TestCallQualityWithAudioFromFakeDevice
-#endif
-IN_PROC_BROWSER_TEST_F(WebRtcAudioQualityBrowserTest,
-                       MAYBE_MANUAL_TestCallQualityWithAudioFromFakeDevice) {
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  TestWithFakeDeviceGetUserMedia(kAudioOnlyCallConstraints, "_getusermedia");
-}
-
-#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
-#define MAYBE_MANUAL_TestCallQualityWithAudioFromWebAudio \
-  MANUAL_TestCallQualityWithAudioFromWebAudio
-#else
-// Not implemented on Android, ChromeOS etc. Temporary disabled on Mac
-// (https://crbug.com/882780).
-#define MAYBE_MANUAL_TestCallQualityWithAudioFromWebAudio \
-  DISABLED_MANUAL_TestCallQualityWithAudioFromWebAudio
-#endif
-IN_PROC_BROWSER_TEST_F(WebRtcAudioQualityBrowserTest,
-                       MAYBE_MANUAL_TestCallQualityWithAudioFromWebAudio) {
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  if (OnWin8OrHigher()) {
-    // http://crbug.com/379798.
-    LOG(ERROR) << "This test is not implemented for Win8 or higher.";
-    return;
-  }
-  ASSERT_TRUE(test::HasReferenceFilesInCheckout());
-  ASSERT_TRUE(embedded_test_server()->Start());
-
-  ASSERT_TRUE(ForceMicrophoneVolumeTo100Percent());
-
-  content::WebContents* left_tab =
-      OpenPageWithoutGetUserMedia(kWebRtcAudioTestHtmlPage);
-  content::WebContents* right_tab =
-      OpenPageWithoutGetUserMedia(kWebRtcAudioTestHtmlPage);
-
-  AddAudioFileToWebAudio(kReferenceFileRelativeUrl, left_tab);
-
-  NegotiateCall(left_tab, right_tab);
-
-  base::FilePath recording = CreateTemporaryWaveFile();
-
-  // Note: the sound clip is 21.6 seconds: record for 25 seconds to get some
-  // safety margins on each side.
-  AudioRecorder recorder;
-  ASSERT_TRUE(recorder.StartRecording(base::TimeDelta::FromSeconds(25),
-                                      recording));
-
-  PlayAudioFileThroughWebAudio(left_tab);
-
-  ASSERT_TRUE(recorder.WaitForRecordingToEnd());
-  DVLOG(0) << "Done recording to " << recording.value() << std::endl;
-
-  HangUp(left_tab);
-
-  // Compare with the reference file on disk (this is the same file we played
-  // through WebAudio earlier).
-  ComputeAndPrintPesqResults(reference_file(), recording, "_webaudio");
-
-  DeleteFileUnlessTestFailed(recording, false);
-}
-
-/**
- * The auto gain control test plays a file into the fake microphone. Then it
- * sets up a one-way WebRTC call with audio only and records Chrome's output on
- * the receiving side using the audio loopback provided by the quality test
- * (see the class comments for more details).
- *
- * Then both the recording and reference file are split on silence. This creates
- * a number of segments with speech in them. The reason for this is to provide
- * a kind of synchronization mechanism so the start of each speech segment is
- * compared to the start of the corresponding speech segment. This is because we
- * will experience inevitable clock drift between the system clock (which runs
- * the fake microphone) and the sound card (which runs play-out). Effectively
- * re-synchronizing on each segment mitigates this.
- *
- * The silence splitting is inherently sensitive to the sound file we run on.
- * Therefore the reference file must have at least 500 ms of pure silence
- * between speech segments; the test will fail if the output produces more
- * segments than the reference.
- *
- * The test reports the difference in decibel between the reference and output
- * file per 10 ms interval in each speech segment. A value of 6 means the
- * output was 6 dB louder than the reference, presumably because the AGC applied
- * gain to the signal.
- *
- * The test only exercises digital AGC for now.
- *
- * We record in CD format here (44.1 kHz) because that's what the fake input
- * device currently supports, and we want to be able to compare directly. See
- * http://crbug.com/421054.
- */
-void WebRtcAudioQualityBrowserTest::TestAutoGainControl(
-    const std::string& constraints,
-    const std::string& perf_modifier) {
-  if (OnWin8OrHigher()) {
-    // http://crbug.com/379798.
-    LOG(ERROR) << "This test is not implemented for Win8 or higher.";
-    return;
-  }
-  base::FilePath recording = CreateTemporaryWaveFile();
-
-  ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall(
-      recording, constraints, base::TimeDelta::FromSeconds(30)));
-
-  base::ScopedTempDir split_ref_files;
-  ASSERT_TRUE(split_ref_files.CreateUniqueTempDirUnderPath(wav_dump_path_));
-  ASSERT_NO_FATAL_FAILURE(
-      SplitFileOnSilenceIntoDir(reference_file(), split_ref_files.GetPath()));
-  std::vector<base::FilePath> ref_segments =
-      ListWavFilesInDir(split_ref_files.GetPath());
-
-  base::ScopedTempDir split_actual_files;
-  ASSERT_TRUE(split_actual_files.CreateUniqueTempDirUnderPath(wav_dump_path_));
-  ASSERT_NO_FATAL_FAILURE(
-      SplitFileOnSilenceIntoDir(recording, split_actual_files.GetPath()));
-
-  // Keep the recording and split files in case the analysis fails.
-  base::FilePath actual_files_dir = split_actual_files.Take();
-  std::vector<base::FilePath> actual_segments =
-      ListWavFilesInDir(actual_files_dir);
-
-  AnalyzeSegmentsAndPrintResult(ref_segments, actual_segments, reference_file(),
-                                perf_modifier);
-
-  DeleteFileUnlessTestFailed(recording, false);
-  DeleteFileUnlessTestFailed(actual_files_dir, true);
-}
-
-#if defined(OS_LINUX)
-#define MAYBE_MANUAL_TestAutoGainControlOnLowAudio \
-  MANUAL_TestAutoGainControlOnLowAudio
-#else
-// Not implemented on Android, ChromeOS etc. Temporary disabled on Windows
-// (https://crbug.com/850936) and on Mac (https://crbug.com/882780).
-#define MAYBE_MANUAL_TestAutoGainControlOnLowAudio \
-  DISABLED_MANUAL_TestAutoGainControlOnLowAudio
-#endif
-// The AGC should apply non-zero gain here.
-IN_PROC_BROWSER_TEST_F(WebRtcAudioQualityBrowserTest,
-                       MAYBE_MANUAL_TestAutoGainControlOnLowAudio) {
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  // Disables AEC, but leaves AGC on.
-  const char* kAudioCallWithoutEchoCancellation =
-      "{audio: { mandatory: { googEchoCancellation: false } } }";
-  ASSERT_NO_FATAL_FAILURE(
-      TestAutoGainControl(kAudioCallWithoutEchoCancellation, "_with_agc"));
-}
-
-#if defined(OS_LINUX)
-#define MAYBE_MANUAL_TestAutoGainIsOffWithAudioProcessingOff \
-  MANUAL_TestAutoGainIsOffWithAudioProcessingOff
-#else
-// Not implemented on Android, ChromeOS etc. Temporary disabled on Windows
-// (https://crbug.com/850936) and on Mac (https://crbug.com/882780).
-#define MAYBE_MANUAL_TestAutoGainIsOffWithAudioProcessingOff \
-  DISABLED_MANUAL_TestAutoGainIsOffWithAudioProcessingOff
-#endif
-// Since the AGC is off here there should be no gain at all.
-IN_PROC_BROWSER_TEST_F(WebRtcAudioQualityBrowserTest,
-                       MAYBE_MANUAL_TestAutoGainIsOffWithAudioProcessingOff) {
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  const char* kAudioCallWithoutAudioProcessing =
-      "{audio: { mandatory: { echoCancellation: false } } }";
-  ASSERT_NO_FATAL_FAILURE(
-      TestAutoGainControl(kAudioCallWithoutAudioProcessing, "_no_agc"));
-}
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_audio.cc b/chrome/browser/media/webrtc/webrtc_browsertest_audio.cc
deleted file mode 100644
index 500fbec..0000000
--- a/chrome/browser/media/webrtc/webrtc_browsertest_audio.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media/webrtc/webrtc_browsertest_audio.h"
-
-#include <stddef.h>
-
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "media/audio/audio_power_monitor.h"
-#include "media/audio/sounds/wav_audio_handler.h"
-#include "media/base/audio_bus.h"
-#include "media/base/audio_parameters.h"
-
-namespace {
-// Opens |wav_filename|, reads it and loads it as a wav file. This function will
-// bluntly trigger CHECKs if we can't read the file or if it's malformed. The
-// caller takes ownership of the returned data. The size of the data is stored
-// in |read_length|.
-std::unique_ptr<char[]> ReadWavFile(const base::FilePath& wav_filename,
-                                    size_t* file_length) {
-  base::File wav_file(
-      wav_filename, base::File::FLAG_OPEN | base::File::FLAG_READ);
-  if (!wav_file.IsValid()) {
-    CHECK(false) << "Failed to read " << wav_filename.value();
-    return nullptr;
-  }
-
-  int64_t wav_file_length64 = wav_file.GetLength();
-  if (wav_file_length64 < 0) {
-    PLOG(ERROR) << "GetLength " << wav_file.GetPlatformFile();
-    return nullptr;
-  }
-  if (wav_file_length64 > std::numeric_limits<int>::max()) {
-    LOG(ERROR) << "File is too big: " << wav_filename.value();
-    return nullptr;
-  }
-  int wav_file_length = static_cast<int>(wav_file_length64);
-  if (!wav_file_length) {
-    LOG(ERROR) << "Input file is empty: " << wav_filename.value();
-    return nullptr;
-  }
-
-  std::unique_ptr<char[]> data(new char[wav_file_length]);
-  int read_bytes = wav_file.Read(0, data.get(), wav_file_length);
-  if (read_bytes != wav_file_length) {
-    LOG(ERROR) << "Failed to read all bytes of " << wav_filename.value();
-    return nullptr;
-  }
-  *file_length = wav_file_length;
-  return data;
-}
-}  // namespace
-
-namespace test {
-
-float ComputeAudioEnergyForWavFile(const base::FilePath& wav_filename,
-                                   media::AudioParameters* file_parameters) {
-  // Read the file, and put its data in a scoped_ptr so it gets deleted later.
-  size_t file_length = 0;
-  std::unique_ptr<char[]> wav_file_data =
-      ReadWavFile(wav_filename, &file_length);
-  auto wav_audio_handler = media::WavAudioHandler::Create(
-      base::StringPiece(wav_file_data.get(), file_length));
-
-  std::unique_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(
-      wav_audio_handler->num_channels(), wav_audio_handler->total_frames());
-  base::TimeDelta file_duration = wav_audio_handler->GetDuration();
-
-  size_t bytes_written;
-  wav_audio_handler->CopyTo(audio_bus.get(), 0, &bytes_written);
-  CHECK_EQ(bytes_written, wav_audio_handler->data().size())
-      << "Expected to write entire file into bus.";
-
-  // Set the filter coefficient to the whole file's duration; this will make the
-  // power monitor take the entire file into account.
-  media::AudioPowerMonitor power_monitor(wav_audio_handler->sample_rate(),
-                                         file_duration);
-  power_monitor.Scan(*audio_bus, audio_bus->frames());
-
-  file_parameters->Reset(
-      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
-      media::GuessChannelLayout(wav_audio_handler->num_channels()),
-      wav_audio_handler->sample_rate(), wav_audio_handler->total_frames());
-  file_parameters->set_channels_for_discrete(wav_audio_handler->num_channels());
-
-  return power_monitor.ReadCurrentPowerAndClip().first;
-}
-
-}  // namespace test
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_audio.h b/chrome/browser/media/webrtc/webrtc_browsertest_audio.h
deleted file mode 100644
index 2e232b28..0000000
--- a/chrome/browser/media/webrtc/webrtc_browsertest_audio.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_BROWSERTEST_AUDIO_H_
-#define CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_BROWSERTEST_AUDIO_H_
-
-#include <vector>
-
-namespace base {
-class FilePath;
-}
-
-namespace media {
-class AudioParameters;
-}
-
-namespace test {
-
-// Computes the average power of the audio signal seen over the entire file.
-//
-// The |file_parameters| pointer is filled with a copy of the audio file's
-// parameters as deduced by wav_audio_handler.h (i.e. what's in the header).
-//
-// Returns a audio dBFS (decibels relative to full-scale) value.
-// See media/audio/audio_power_monitor.h for more details.
-float ComputeAudioEnergyForWavFile(const base::FilePath& wav_file_path,
-                                   media::AudioParameters* file_parameters);
-
-}  // namespace test
-
-#endif  // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_BROWSERTEST_AUDIO_H_
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 2bc9e70..1f0ca2a 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -992,10 +992,7 @@
 }
 
 // Run UKM browser test suite with Unified Consent enabled and disabled.
-//
-// Tests with Unified Consent enabled were temporarely disabled.
-// (see http://crbug.com/891777).
-INSTANTIATE_TEST_CASE_P(, UkmBrowserTest, ::testing::Values(false));
+INSTANTIATE_TEST_CASE_P(, UkmBrowserTest, testing::Bool());
 
 IN_PROC_BROWSER_TEST_P(UkmConsentParamBrowserTest, GroupPolicyConsentCheck) {
   // Note we are not using the synthetic MetricsConsentOverride since we are
@@ -1020,11 +1017,8 @@
 }
 
 // Verify UKM is enabled/disabled for both potential settings of group policy.
-//
-// Tests with Unified Consent enabled were temporarely disabled.
-// (see http://crbug.com/891777).
 INSTANTIATE_TEST_CASE_P(UkmConsentParamBrowserTests,
                         UkmConsentParamBrowserTest,
-                        ::testing::Values(false));
+                        testing::Bool());
 
 }  // namespace metrics
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc
index 109cf2899..aca8d59 100644
--- a/chrome/browser/net/profile_network_context_service.cc
+++ b/chrome/browser/net/profile_network_context_service.cc
@@ -14,8 +14,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/net/chrome_accept_language_settings.h"
-#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
-#include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
 #include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_constants.h"
@@ -25,7 +23,6 @@
 #include "components/certificate_transparency/pref_names.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/common/pref_names.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
@@ -388,17 +385,6 @@
   network_context_params->enable_certificate_reporting = true;
   network_context_params->enable_expect_ct_reporting = true;
 
-  if (data_reduction_proxy::params::IsEnabledWithNetworkService()) {
-    auto* drp_settings =
-        DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile_);
-    if (drp_settings) {
-      network::mojom::CustomProxyConfigClientPtrInfo config_client_info;
-      network_context_params->custom_proxy_config_client_request =
-          mojo::MakeRequest(&config_client_info);
-      drp_settings->SetCustomProxyConfigClient(std::move(config_client_info));
-    }
-  }
-
   return network_context_params;
 }
 
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc
index 848162b..3865f87 100644
--- a/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc
+++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_browsertest.cc
@@ -61,17 +61,15 @@
   }
 
   void SetUp() override {
-    scoped_feature_list_.InitAndEnableFeature(
-        features::kDataReductionProxyEnabledWithNetworkService);
-    param_feature_list_.InitAndEnableFeatureWithParameters(
-        features::kDataReductionProxyRobustConnection,
-        {{params::GetMissingViaBypassParamName(), "true"},
-         {params::GetWarmupCallbackParamName(), "true"}});
     ASSERT_TRUE(embedded_test_server()->Start());
     InProcessBrowserTest::SetUp();
   }
 
   void SetUpOnMainThread() override {
+    scoped_feature_list_.InitAndEnableFeatureWithParameters(
+        features::kDataReductionProxyRobustConnection,
+        {{params::GetMissingViaBypassParamName(), "true"},
+         {params::GetWarmupCallbackParamName(), "true"}});
     host_resolver()->AddRule(kMockHost, "127.0.0.1");
     EnableDataSaver(true);
   }
@@ -104,7 +102,6 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-  base::test::ScopedFeatureList param_feature_list_;
 };
 
 IN_PROC_BROWSER_TEST_F(DataReductionProxyBrowsertest, ChromeProxyHeaderSet) {
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index 5906cf3..c7b386c 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -25,12 +25,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search/suggestions/image_decoder_impl.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "components/bookmarks/browser/bookmark_model.h"
-#include "components/browser_sync/profile_sync_service.h"
 #include "components/gcm_driver/gcm_profile_service.h"
 #include "components/gcm_driver/instance_id/instance_id_profile_service.h"
 #include "components/image_fetcher/core/image_decoder.h"
@@ -52,8 +50,6 @@
 #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
 #include "components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h"
 #include "components/ntp_snippets/remote/remote_suggestions_status_service_impl.h"
-#include "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h"
-#include "components/ntp_snippets/sessions/tab_delegate_sync_adapter.h"
 #include "components/ntp_snippets/user_classifier.h"
 #include "components/offline_pages/buildflags/buildflags.h"
 #include "components/prefs/pref_service.h"
@@ -102,11 +98,9 @@
 using ntp_snippets::BreakingNewsListener;
 using ntp_snippets::CategoryRanker;
 using ntp_snippets::ContentSuggestionsService;
-using ntp_snippets::ForeignSessionsSuggestionsProvider;
 using ntp_snippets::GetFetchEndpoint;
 using ntp_snippets::IsBookmarkProviderEnabled;
 using ntp_snippets::IsDownloadsProviderEnabled;
-using ntp_snippets::IsForeignSessionsProviderEnabled;
 using ntp_snippets::PersistentScheduler;
 using ntp_snippets::PrefetchedPagesTracker;
 using ntp_snippets::RemoteSuggestionsDatabase;
@@ -114,10 +108,8 @@
 using ntp_snippets::RemoteSuggestionsProviderImpl;
 using ntp_snippets::RemoteSuggestionsSchedulerImpl;
 using ntp_snippets::RemoteSuggestionsStatusServiceImpl;
-using ntp_snippets::TabDelegateSyncAdapter;
 using ntp_snippets::UserClassifier;
 using suggestions::ImageDecoderImpl;
-using syncer::SyncService;
 
 #if defined(OS_ANDROID)
 using content::DownloadManager;
@@ -346,22 +338,6 @@
   service->RegisterProvider(std::move(provider));
 }
 
-void RegisterForeignSessionsProviderIfEnabled(
-    ContentSuggestionsService* service,
-    Profile* profile) {
-  if (!IsForeignSessionsProviderEnabled()) {
-    return;
-  }
-
-  SyncService* sync_service =
-      ProfileSyncServiceFactory::GetSyncServiceForBrowserContext(profile);
-  std::unique_ptr<TabDelegateSyncAdapter> sync_adapter =
-      std::make_unique<TabDelegateSyncAdapter>(sync_service);
-  auto provider = std::make_unique<ForeignSessionsSuggestionsProvider>(
-      service, std::move(sync_adapter), profile->GetPrefs());
-  service->RegisterProvider(std::move(provider));
-}
-
 }  // namespace
 
 #endif  // CONTENT_SUGGESTIONS_ENABLED
@@ -398,7 +374,6 @@
   DependsOn(OfflinePageModelFactory::GetInstance());
   DependsOn(offline_pages::PrefetchServiceFactory::GetInstance());
 #endif  // BUILDFLAG(ENABLE_OFFLINE_PAGES)
-  DependsOn(ProfileSyncServiceFactory::GetInstance());
 #if defined(OS_ANDROID)
   DependsOn(gcm::GCMProfileServiceFactory::GetInstance());
   DependsOn(instance_id::InstanceIDProfileServiceFactory::GetInstance());
@@ -460,7 +435,6 @@
   RegisterArticleProviderIfEnabled(service, profile, user_classifier_raw,
                                    offline_page_model, raw_debug_logger);
   RegisterBookmarkProviderIfEnabled(service, profile);
-  RegisterForeignSessionsProviderIfEnabled(service, profile);
 
 #if defined(OS_ANDROID)
   RegisterDownloadsProviderIfEnabled(service, profile, offline_page_model);
diff --git a/chrome/browser/ntp_snippets/dependent_features.cc b/chrome/browser/ntp_snippets/dependent_features.cc
index 74503cc1..6bac474a 100644
--- a/chrome/browser/ntp_snippets/dependent_features.cc
+++ b/chrome/browser/ntp_snippets/dependent_features.cc
@@ -46,10 +46,4 @@
              ntp_snippets::kBookmarkSuggestionsFeature);
 }
 
-bool IsForeignSessionsProviderEnabled() {
-  return !IsSimplifiedNtpEnabled() &&
-         base::FeatureList::IsEnabled(
-             ntp_snippets::kForeignSessionsSuggestionsFeature);
-}
-
 }  // namespace ntp_snippets
diff --git a/chrome/browser/ntp_snippets/dependent_features.h b/chrome/browser/ntp_snippets/dependent_features.h
index 9c83962..110de2b 100644
--- a/chrome/browser/ntp_snippets/dependent_features.h
+++ b/chrome/browser/ntp_snippets/dependent_features.h
@@ -19,8 +19,6 @@
 
 bool IsPhysicalWebPageProviderEnabled();
 
-bool IsForeignSessionsProviderEnabled();
-
 }  // namespace ntp_snippets
 
 #endif  // CHROME_BROWSER_NTP_SNIPPETS_DEPENDENT_FEATURES_H_
diff --git a/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc b/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc
index 982ba5e..e4d79d6 100644
--- a/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc
+++ b/chrome/browser/plugins/pdf_plugin_placeholder_observer.cc
@@ -16,7 +16,6 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "ppapi/buildflags/buildflags.h"
 
@@ -63,10 +62,6 @@
                              blink::kWebReferrerPolicyDefault));
 
 #if BUILDFLAG(ENABLE_PLUGINS)
-  content::StoragePartition* storage_partition =
-      content::BrowserContext::GetStoragePartition(
-          web_contents()->GetBrowserContext(),
-          render_frame_host->GetSiteInstance());
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("pdf_plugin_placeholder", R"(
         semantics {
@@ -96,8 +91,7 @@
       std::make_unique<download::DownloadUrlParameters>(
           url, render_frame_host->GetRenderViewHost()->GetProcess()->GetID(),
           render_frame_host->GetRenderViewHost()->GetRoutingID(),
-          render_frame_host->GetRoutingID(),
-          storage_partition->GetURLRequestContext(), traffic_annotation);
+          render_frame_host->GetRoutingID(), traffic_annotation);
   params->set_referrer(referrer.url);
   params->set_referrer_policy(
       content::Referrer::ReferrerPolicyForUrlRequest(referrer.policy));
diff --git a/chrome/browser/policy/test/policy_testserver.py b/chrome/browser/policy/test/policy_testserver.py
index c78440b..d1716c9 100644
--- a/chrome/browser/policy/test/policy_testserver.py
+++ b/chrome/browser/policy/test/policy_testserver.py
@@ -1356,9 +1356,6 @@
       dm.DeviceRegisterRequest.ANDROID_BROWSER: [
           'google/android/user'
       ],
-      dm.DeviceRegisterRequest.IOS_BROWSER: [
-          'google/ios/user'
-      ],
       dm.DeviceRegisterRequest.TT: ['google/chromeos/user',
                                     'google/chrome/user'],
     }
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index c000b17..77f4bb2 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -94,7 +94,6 @@
 #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
 #include "components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h"
 #include "components/ntp_snippets/remote/request_throttler.h"
-#include "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h"
 #include "components/ntp_snippets/user_classifier.h"
 #include "components/ntp_tiles/most_visited_sites.h"
 #include "components/offline_pages/buildflags/buildflags.h"
@@ -567,8 +566,6 @@
   NavigationCorrectionTabObserver::RegisterProfilePrefs(registry);
   NotifierStateTracker::RegisterProfilePrefs(registry);
   ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
-  ntp_snippets::ForeignSessionsSuggestionsProvider::RegisterProfilePrefs(
-      registry);
   ntp_snippets::RemoteSuggestionsProviderImpl::RegisterProfilePrefs(registry);
   ntp_snippets::RemoteSuggestionsSchedulerImpl::RegisterProfilePrefs(registry);
   ntp_snippets::RequestThrottler::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 85b09610..f115804 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -112,7 +112,6 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/ssl_status.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/menu_item.h"
 #include "content/public/common/url_utils.h"
@@ -2428,10 +2427,6 @@
   RecordDownloadSource(DOWNLOAD_INITIATED_BY_CONTEXT_MENU);
 
   const GURL& url = params_.link_url;
-  content::StoragePartition* storage_partition =
-      BrowserContext::GetStoragePartition(
-          source_web_contents_->GetBrowserContext(),
-          render_frame_host->GetSiteInstance());
 
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("render_view_context_menu", R"(
@@ -2456,8 +2451,7 @@
   auto dl_params = std::make_unique<DownloadUrlParameters>(
       url, render_frame_host->GetProcess()->GetID(),
       render_frame_host->GetRenderViewHost()->GetRoutingID(),
-      render_frame_host->GetRoutingID(),
-      storage_partition->GetURLRequestContext(), traffic_annotation);
+      render_frame_host->GetRoutingID(), traffic_annotation);
   content::Referrer referrer = CreateReferrer(url, params_);
   dl_params->set_referrer(referrer.url);
   dl_params->set_referrer_policy(
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
index 135eedb..14645e46 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -29,12 +29,15 @@
 #include "chrome/browser/resource_coordinator/usage_clock.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h"
+#include "chrome/browser/usb/usb_chooser_context.h"
+#include "chrome/browser/usb/usb_chooser_context_factory.h"
 #include "chrome/browser/usb/usb_tab_helper.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/referrer.h"
 #include "content/public/test/web_contents_tester.h"
-#include "device/base/mock_device_client.h"
+#include "device/usb/public/cpp/fake_usb_device_manager.h"
+#include "device/usb/public/mojom/device_manager.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace resource_coordinator {
@@ -477,8 +480,13 @@
   test_clock_.Advance(kBackgroundUrgentProtectionTime);
   ExpectCanDiscardTrueAllReasons(&tab_lifecycle_unit);
 
-  // Make sure there is a DeviceClient instance.
-  device::MockDeviceClient device_client;
+  // Connect with the FakeUsbDeviceManager.
+  device::FakeUsbDeviceManager device_manager;
+  device::mojom::UsbDeviceManagerPtr device_manager_ptr;
+  device_manager.AddBinding(mojo::MakeRequest(&device_manager_ptr));
+  UsbChooserContextFactory::GetForProfile(profile())
+      ->SetDeviceManagerForTesting(std::move(device_manager_ptr));
+
   UsbTabHelper* usb_tab_helper =
       UsbTabHelper::GetOrCreateForWebContents(web_contents_);
   usb_tab_helper->CreateWebUsbService(
diff --git a/chrome/browser/signin/signin_tracker_unittest.cc b/chrome/browser/signin/signin_tracker_unittest.cc
deleted file mode 100644
index 0563336..0000000
--- a/chrome/browser/signin/signin_tracker_unittest.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 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.
-
-#include "components/signin/core/browser/signin_tracker.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
-#include "build/build_config.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/account_tracker_service_factory.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
-#include "chrome/browser/signin/fake_signin_manager_builder.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/signin/signin_tracker_factory.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/browser_sync/profile_sync_service_mock.h"
-#include "components/signin/core/browser/account_tracker_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
-#include "components/signin/core/browser/profile_oauth2_token_service.h"
-#include "components/signin/core/browser/signin_manager.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::Mock;
-using ::testing::Return;
-using ::testing::ReturnRef;
-
-namespace {
-
-class MockObserver : public SigninTracker::Observer {
- public:
-  MockObserver() {}
-  ~MockObserver() {}
-
-  MOCK_METHOD1(SigninFailed, void(const GoogleServiceAuthError&));
-  MOCK_METHOD0(SigninSuccess, void(void));
-  MOCK_METHOD1(AccountAddedToCookie, void(const GoogleServiceAuthError&));
-};
-
-}  // namespace
-
-class SigninTrackerTest : public testing::Test {
- public:
-  SigninTrackerTest() {}
-  void SetUp() override {
-    TestingProfile::Builder builder;
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        base::BindRepeating(&BuildFakeProfileOAuth2TokenService));
-    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
-                              base::BindRepeating(&BuildFakeSigninManagerBase));
-    profile_ = builder.Build();
-
-    fake_oauth2_token_service_ =
-        static_cast<FakeProfileOAuth2TokenService*>(
-            ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()));
-
-    fake_signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
-        SigninManagerFactory::GetForProfile(profile_.get()));
-
-    tracker_ =
-        SigninTrackerFactory::CreateForProfile(profile_.get(), &observer_);
-  }
-
-  void TearDown() override {
-    tracker_.reset();
-    profile_.reset();
-  }
-
-  // Seed the account tracker with information from logged in user.  Normally
-  // this is done by UI code before calling SigninManager.  Returns the string
-  // to use as the account_id.
-  std::string AddToAccountTracker(const std::string& gaia_id,
-                                  const std::string& email) {
-    AccountTrackerService* service =
-        AccountTrackerServiceFactory::GetForProfile(profile_.get());
-    return service->SeedAccountInfo(gaia_id, email);
-  }
-
-  content::TestBrowserThreadBundle thread_bundle_;
-  std::unique_ptr<SigninTracker> tracker_;
-  std::unique_ptr<TestingProfile> profile_;
-  FakeSigninManagerForTesting* fake_signin_manager_;
-  FakeProfileOAuth2TokenService* fake_oauth2_token_service_;
-  MockObserver observer_;
-};
-
-#if !defined(OS_CHROMEOS)
-TEST_F(SigninTrackerTest, SignInFails) {
-  const GoogleServiceAuthError error(
-      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-
-  // Signin failure should result in a SigninFailed callback.
-  EXPECT_CALL(observer_, SigninSuccess()).Times(0);
-  EXPECT_CALL(observer_, SigninFailed(error));
-
-  fake_signin_manager_->FailSignin(error);
-}
-#endif  // !defined(OS_CHROMEOS)
-
-TEST_F(SigninTrackerTest, SignInSucceeds) {
-  EXPECT_CALL(observer_, SigninSuccess());
-  EXPECT_CALL(observer_, SigninFailed(_)).Times(0);
-
-  AccountTrackerService* service =
-    AccountTrackerServiceFactory::GetForProfile(profile_.get());
-  std::string gaia_id = "gaia_id";
-  std::string email = "user@gmail.com";
-  std::string account_id = service->SeedAccountInfo(gaia_id, email);
-
-  fake_signin_manager_->SetAuthenticatedAccountInfo(gaia_id, email);
-  fake_oauth2_token_service_->UpdateCredentials(account_id, "refresh_token");
-}
-
-#if !defined(OS_CHROMEOS)
-TEST_F(SigninTrackerTest, SignInSucceedsWithExistingAccount) {
-  EXPECT_CALL(observer_, SigninSuccess());
-  EXPECT_CALL(observer_, SigninFailed(_)).Times(0);
-
-  AccountTrackerService* service =
-      AccountTrackerServiceFactory::GetForProfile(profile_.get());
-  std::string gaia_id = "gaia_id";
-  std::string email = "user@gmail.com";
-  std::string account_id = service->SeedAccountInfo(gaia_id, email);
-  fake_oauth2_token_service_->UpdateCredentials(account_id, "refresh_token");
-  fake_signin_manager_->SignIn(gaia_id, email, std::string());
-}
-#endif
diff --git a/chrome/browser/storage/storage_info_fetcher.cc b/chrome/browser/storage/storage_info_fetcher.cc
index 3b907c8..313827a9 100644
--- a/chrome/browser/storage/storage_info_fetcher.cc
+++ b/chrome/browser/storage/storage_info_fetcher.cc
@@ -20,8 +20,7 @@
       profile)->GetQuotaManager();
 }
 
-StorageInfoFetcher::~StorageInfoFetcher() {
-}
+StorageInfoFetcher::~StorageInfoFetcher() = default;
 
 void StorageInfoFetcher::FetchStorageInfo(const FetchCallback& fetch_callback) {
   // Balanced in OnFetchCompleted.
@@ -33,9 +32,9 @@
   // called on the UI thread.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(
+      base::BindOnce(
           &StorageInfoFetcher::GetUsageInfo, this,
-          base::Bind(&StorageInfoFetcher::OnGetUsageInfoInternal, this)));
+          base::BindOnce(&StorageInfoFetcher::OnGetUsageInfoInternal, this)));
 }
 
 void StorageInfoFetcher::ClearStorage(const std::string& host,
@@ -49,10 +48,10 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(
+      base::BindOnce(
           &storage::QuotaManager::DeleteHostData, quota_manager_, host, type,
           storage::QuotaClient::kAllClientsMask,
-          base::Bind(&StorageInfoFetcher::OnUsageClearedInternal, this)));
+          base::BindOnce(&StorageInfoFetcher::OnUsageClearedInternal, this)));
 }
 
 void StorageInfoFetcher::GetUsageInfo(storage::GetUsageInfoCallback callback) {
@@ -61,13 +60,14 @@
 }
 
 void StorageInfoFetcher::OnGetUsageInfoInternal(
-    const storage::UsageInfoEntries& entries) {
+    storage::UsageInfoEntries entries) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  entries_.insert(entries_.begin(), entries.begin(), entries.end());
+  entries_ = std::move(entries);
+
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&StorageInfoFetcher::OnFetchCompleted, this));
+      base::BindOnce(&StorageInfoFetcher::OnFetchCompleted, this));
 }
 
 void StorageInfoFetcher::OnFetchCompleted() {
@@ -86,7 +86,7 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&StorageInfoFetcher::OnClearCompleted, this, code));
+      base::BindOnce(&StorageInfoFetcher::OnClearCompleted, this, code));
 }
 
 void StorageInfoFetcher::OnClearCompleted(blink::mojom::QuotaStatusCode code) {
diff --git a/chrome/browser/storage/storage_info_fetcher.h b/chrome/browser/storage/storage_info_fetcher.h
index a03ae9d..b07b440 100644
--- a/chrome/browser/storage/storage_info_fetcher.h
+++ b/chrome/browser/storage/storage_info_fetcher.h
@@ -43,7 +43,7 @@
   void GetUsageInfo(storage::GetUsageInfoCallback callback);
 
   // Called when usage information is available.
-  void OnGetUsageInfoInternal(const storage::UsageInfoEntries& entries);
+  void OnGetUsageInfoInternal(storage::UsageInfoEntries entries);
 
   // Reports back to all observers that information is available.
   void OnFetchCompleted();
diff --git a/chrome/browser/ui/page_info/page_info_unittest.cc b/chrome/browser/ui/page_info/page_info_unittest.cc
index f5c3e02..264d3fa 100644
--- a/chrome/browser/ui/page_info/page_info_unittest.cc
+++ b/chrome/browser/ui/page_info/page_info_unittest.cc
@@ -31,10 +31,7 @@
 #include "content/public/browser/ssl_host_state_delegate.h"
 #include "content/public/browser/ssl_status.h"
 #include "content/public/common/content_switches.h"
-#include "device/base/mock_device_client.h"
-#include "device/usb/mock_usb_device.h"
-#include "device/usb/mock_usb_service.h"
-#include "device/usb/mojo/type_converters.h"
+#include "device/usb/public/cpp/fake_usb_device_manager.h"
 #include "device/usb/public/mojom/device.mojom.h"
 #include "net/cert/cert_status_flags.h"
 #include "net/cert/x509_certificate.h"
@@ -205,14 +202,9 @@
     return page_info_.get();
   }
 
-  device::MockUsbService& usb_service() {
-    return *device_client_.usb_service();
-  }
-
   security_state::SecurityInfo security_info_;
 
  private:
-  device::MockDeviceClient device_client_;
   std::unique_ptr<PageInfo> page_info_;
   std::unique_ptr<MockPageInfoUI> mock_ui_;
   scoped_refptr<net::X509Certificate> cert_;
@@ -393,12 +385,15 @@
 }
 
 TEST_F(PageInfoTest, OnChosenObjectDeleted) {
-  scoped_refptr<device::UsbDevice> device =
-      new device::MockUsbDevice(0, 0, "Google", "Gizmo", "1234567890");
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
-  usb_service().AddDevice(device);
+  // Connect the UsbChooserContext with FakeUsbDeviceManager.
+  device::FakeUsbDeviceManager usb_device_manager;
+  device::mojom::UsbDeviceManagerPtr device_manager_ptr;
+  usb_device_manager.AddBinding(mojo::MakeRequest(&device_manager_ptr));
   UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile());
+  store->SetDeviceManagerForTesting(std::move(device_manager_ptr));
+
+  auto device_info = usb_device_manager.CreateAndAddDevice(
+      0, 0, "Google", "Gizmo", "1234567890");
   store->GrantDevicePermission(url(), url(), *device_info);
 
   EXPECT_CALL(*mock_ui(), SetIdentityInfo(_));
@@ -414,7 +409,7 @@
   const PageInfoUI::ChosenObjectInfo* info = last_chosen_object_info()[0].get();
   page_info()->OnSiteChosenObjectDeleted(info->ui_info, *info->object);
 
-  EXPECT_FALSE(store->HasDevicePermission(url(), url(), device));
+  EXPECT_FALSE(store->HasDevicePermission(url(), url(), *device_info));
   EXPECT_EQ(0u, last_chosen_object_info().size());
 }
 
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.cc b/chrome/browser/ui/passwords/password_manager_presenter.cc
index e8247325..e16e3c3 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter.cc
@@ -30,6 +30,7 @@
 #include "chrome/common/url_constants.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/browser_sync/profile_sync_service.h"
+#include "components/password_manager/core/browser/password_list_sorter.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_sync_util.h"
 #include "components/password_manager/core/browser/password_ui_utils.h"
@@ -47,28 +48,38 @@
 
 namespace {
 
-// Finds duplicates of |form| in |duplicates|, removes them from |store| and
-// from |duplicates|.
-void RemoveDuplicates(const autofill::PasswordForm& form,
-                      password_manager::DuplicatesMap* duplicates,
-                      PasswordStore* store) {
-  std::string key = password_manager::CreateSortKey(form);
-  std::pair<password_manager::DuplicatesMap::iterator,
-            password_manager::DuplicatesMap::iterator>
-      dups = duplicates->equal_range(key);
-  for (auto it = dups.first; it != dups.second; ++it)
-    store->RemoveLogin(*it->second);
-  duplicates->erase(key);
-}
+// Convenience typedef for the commonly used vector of PasswordForm pointers.
+using FormVector = std::vector<std::unique_ptr<autofill::PasswordForm>>;
 
 const autofill::PasswordForm* TryGetPasswordForm(
-    const std::vector<std::unique_ptr<autofill::PasswordForm>>& forms,
+    const std::map<std::string, FormVector>& map,
     size_t index) {
   // |index| out of bounds might come from a compromised renderer
   // (http://crbug.com/362054), or the user removed a password while a request
   // to the store is in progress (i.e. |forms| is empty). Don't let it crash
   // the browser.
-  return index < forms.size() ? forms[index].get() : nullptr;
+  if (map.size() <= index)
+    return nullptr;
+
+  // Android tries to obtain a PasswordForm corresponding to a specific index,
+  // and does not know about sort keys. In order to efficiently obtain the n'th
+  // element in the map we make use of std::next() here.
+  const auto& forms = std::next(map.begin(), index)->second;
+  DCHECK(!forms.empty());
+  return forms[0].get();
+}
+
+// Processes |map| and returns a FormVector where each equivalence class in
+// |map| is represented by exactly one entry in the result.
+FormVector GetEntryList(const std::map<std::string, FormVector>& map) {
+  FormVector result;
+  result.reserve(map.size());
+  for (const auto& pair : map) {
+    DCHECK(!pair.second.empty());
+    result.push_back(std::make_unique<autofill::PasswordForm>(*pair.second[0]));
+  }
+
+  return result;
 }
 
 class RemovePasswordOperation : public UndoOperation {
@@ -166,16 +177,14 @@
 
 void PasswordManagerPresenter::OnLoginsChanged(
     const password_manager::PasswordStoreChangeList& changes) {
-  // Entire list is updated for convenience.
+  // Entire maps are updated for convenience.
   UpdatePasswordLists();
 }
 
 void PasswordManagerPresenter::UpdatePasswordLists() {
-  // Reset the current lists.
-  password_list_.clear();
-  password_duplicates_.clear();
-  password_exception_list_.clear();
-  password_exception_duplicates_.clear();
+  // Reset the current maps.
+  password_map_.clear();
+  exception_map_.clear();
 
   PasswordStore* store = GetPasswordStore();
   if (!store)
@@ -187,15 +196,15 @@
 
 const autofill::PasswordForm* PasswordManagerPresenter::GetPassword(
     size_t index) {
-  return TryGetPasswordForm(password_list_, index);
+  return TryGetPasswordForm(password_map_, index);
 }
 
-std::vector<std::unique_ptr<autofill::PasswordForm>>
-PasswordManagerPresenter::GetAllPasswords() {
-  std::vector<std::unique_ptr<autofill::PasswordForm>> ret_val;
-
-  for (const auto& form : password_list_) {
-    ret_val.push_back(std::make_unique<autofill::PasswordForm>(*form));
+FormVector PasswordManagerPresenter::GetAllPasswords() {
+  FormVector ret_val;
+  for (const auto& pair : password_map_) {
+    for (const auto& form : pair.second) {
+      ret_val.push_back(std::make_unique<autofill::PasswordForm>(*form));
+    }
   }
 
   return ret_val;
@@ -203,7 +212,7 @@
 
 const autofill::PasswordForm* PasswordManagerPresenter::GetPasswordException(
     size_t index) {
-  return TryGetPasswordForm(password_exception_list_, index);
+  return TryGetPasswordForm(exception_map_, index);
 }
 
 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) {
@@ -226,7 +235,7 @@
 
 void PasswordManagerPresenter::RequestShowPassword(size_t index) {
 #if !defined(OS_ANDROID)  // This is never called on Android.
-  const auto* form = TryGetPasswordForm(password_list_, index);
+  const auto* form = TryGetPasswordForm(password_map_, index);
   if (!form)
     return;
 
@@ -274,51 +283,53 @@
 
 bool PasswordManagerPresenter::TryRemovePasswordEntry(EntryKind entry_kind,
                                                       size_t index) {
-  const auto& entries = entry_kind == EntryKind::kPassword
-                            ? password_list_
-                            : password_exception_list_;
-
-  const auto* form = TryGetPasswordForm(entries, index);
-  if (!form)
-    return false;
-
-  auto& duplicates = entry_kind == EntryKind::kPassword
-                         ? password_duplicates_
-                         : password_exception_duplicates_;
-
   PasswordStore* store = GetPasswordStore();
   if (!store)
     return false;
 
-  RemoveDuplicates(*form, &duplicates, store);
-  RemoveLogin(*form);
+  PasswordFormMap& map =
+      entry_kind == EntryKind::kPassword ? password_map_ : exception_map_;
+  if (map.size() <= index)
+    return false;
+
+  // Android tries to obtain a PasswordForm corresponding to a specific index,
+  // and does not know about sort keys. In order to efficiently obtain the n'th
+  // element in the map we make use of std::next() here.
+  auto forms_iter = std::next(map.cbegin(), index);
+  const FormVector& forms = forms_iter->second;
+  DCHECK(!forms.empty());
+
+  undo_manager_.AddUndoOperation(
+      std::make_unique<RemovePasswordOperation>(this, *forms[0]));
+  for (const auto& form : forms)
+    store->RemoveLogin(*form);
+
+  map.erase(forms_iter);
   return true;
 }
 
-void PasswordManagerPresenter::OnGetPasswordStoreResults(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
-  std::partition_copy(std::make_move_iterator(results.begin()),
-                      std::make_move_iterator(results.end()),
-                      std::back_inserter(password_exception_list_),
-                      std::back_inserter(password_list_), [](const auto& form) {
-                        return form->blacklisted_by_user;
-                      });
-
-  password_manager::SortEntriesAndHideDuplicates(&password_list_,
-                                                 &password_duplicates_);
-  password_manager::SortEntriesAndHideDuplicates(
-      &password_exception_list_, &password_exception_duplicates_);
+void PasswordManagerPresenter::OnGetPasswordStoreResults(FormVector results) {
+  for (auto& form : results) {
+    auto& form_map = form->blacklisted_by_user ? exception_map_ : password_map_;
+    form_map[password_manager::CreateSortKey(*form)].push_back(std::move(form));
+  }
 
   SetPasswordList();
   SetPasswordExceptionList();
 }
 
 void PasswordManagerPresenter::SetPasswordList() {
-  password_view_->SetPasswordList(password_list_);
+  // TODO(https://crbug.com/892260): Creating a copy of the elements is
+  // wasteful. Consider updating PasswordUIView to take a PasswordFormMap
+  // instead.
+  password_view_->SetPasswordList(GetEntryList(password_map_));
 }
 
 void PasswordManagerPresenter::SetPasswordExceptionList() {
-  password_view_->SetPasswordExceptionList(password_exception_list_);
+  // TODO(https://crbug.com/892260): Creating a copy of the elements is
+  // wasteful. Consider updating PasswordUIView to take a PasswordFormMap
+  // instead.
+  password_view_->SetPasswordExceptionList(GetEntryList(exception_map_));
 }
 
 PasswordStore* PasswordManagerPresenter::GetPasswordStore() {
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.h b/chrome/browser/ui/passwords/password_manager_presenter.h
index b1e3bcb9..2239962 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.h
+++ b/chrome/browser/ui/passwords/password_manager_presenter.h
@@ -13,7 +13,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "components/password_manager/core/browser/password_list_sorter.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 #include "components/password_manager/core/browser/ui/credential_provider_interface.h"
@@ -49,6 +48,7 @@
   void UpdatePasswordLists();
 
   // Gets the password entry at |index|.
+  // TODO(https://crbug.com/892260): Take a SortKey as argument instead.
   const autofill::PasswordForm* GetPassword(size_t index);
 
   // password::manager::CredentialProviderInterface:
@@ -56,14 +56,17 @@
       override;
 
   // Gets the password exception entry at |index|.
+  // TODO(https://crbug.com/892260): Take a SortKey as argument instead.
   const autofill::PasswordForm* GetPasswordException(size_t index);
 
   // Removes the saved password entry at |index|.
   // |index| the entry index to be removed.
+  // TODO(https://crbug.com/892260): Take a SortKey as argument instead.
   void RemoveSavedPassword(size_t index);
 
   // Removes the saved password exception entry at |index|.
   // |index| the entry index to be removed.
+  // TODO(https://crbug.com/892260): Take a SortKey as argument instead.
   void RemovePasswordException(size_t index);
 
   // Undoes the last saved password or exception removal.
@@ -71,6 +74,7 @@
 
   // Requests the plain text password for entry at |index| to be revealed.
   // |index| The index of the entry.
+  // TODO(https://crbug.com/892260): Take a SortKey as argument instead.
   void RequestShowPassword(size_t index);
 
   // Wrapper around |PasswordStore::AddLogin| that adds the corresponding undo
@@ -82,16 +86,23 @@
   void RemoveLogin(const autofill::PasswordForm& form);
 
  private:
-  friend class PasswordManagerPresenterTest;
+  // Convenience typedef for a map containing PasswordForms grouped into
+  // equivalence classes. Each equivalence class corresponds to one entry shown
+  // in the UI, and deleting an UI entry will delete all PasswordForms that are
+  // a member of the corresponding equivalence class. The keys of the map are
+  // sort keys, obtained by password_manager::CreateSortKey(). Each value of the
+  // map contains forms with the same sort key.
+  using PasswordFormMap =
+      std::map<std::string,
+               std::vector<std::unique_ptr<autofill::PasswordForm>>>;
 
   // Simple two state enum to indicate whether we should operate on saved
   // passwords or saved exceptions.
   enum class EntryKind { kPassword, kException };
 
-  // Attempts to remove the entry corresponding to |index| from the list
-  // corresponding to |entry_kind|. This will also remove the corresponding
-  // entry from the duplicate maps. Returns whether removing the entry
-  // succeeded.
+  // Attempts to remove the entry corresponding to |index| from the map
+  // corresponding to |entry_kind|. This will also add a corresponding undo
+  // operation to |undo_manager_|. Returns whether removing the entry succeeded.
   bool TryRemovePasswordEntry(EntryKind entry_kind, size_t index);
 
   // PasswordStoreConsumer:
@@ -105,10 +116,8 @@
   // Returns the password store associated with the currently active profile.
   password_manager::PasswordStore* GetPasswordStore();
 
-  std::vector<std::unique_ptr<autofill::PasswordForm>> password_list_;
-  std::vector<std::unique_ptr<autofill::PasswordForm>> password_exception_list_;
-  password_manager::DuplicatesMap password_duplicates_;
-  password_manager::DuplicatesMap password_exception_duplicates_;
+  PasswordFormMap password_map_;
+  PasswordFormMap exception_map_;
 
   UndoManager undo_manager_;
 
diff --git a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
index fafe6e5..3734188 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
@@ -9,14 +9,16 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
 #include "build/build_config.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/ui/passwords/password_ui_view.h"
 #include "chrome/browser/ui/passwords/password_ui_view_mock.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/password_manager/core/browser/mock_password_store.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/test_password_store.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -37,103 +39,107 @@
 
 class PasswordManagerPresenterTest : public testing::Test {
  protected:
-  PasswordManagerPresenterTest() {}
-
-  ~PasswordManagerPresenterTest() override {}
-  void SetUp() override {
-    PasswordStoreFactory::GetInstance()->SetTestingFactory(
-        &profile_,
-        base::BindRepeating(
-            &password_manager::BuildPasswordStore<
-                content::BrowserContext, password_manager::MockPasswordStore>));
-    mock_controller_.reset(new MockPasswordUIView(&profile_));
+  PasswordManagerPresenterTest() {
+    store_ = base::WrapRefCounted(static_cast<password_manager::PasswordStore*>(
+        PasswordStoreFactory::GetInstance()
+            ->SetTestingFactoryAndUse(
+                &profile_,
+                base::BindRepeating(&password_manager::BuildPasswordStore<
+                                    content::BrowserContext,
+                                    password_manager::TestPasswordStore>))
+            .get()));
   }
+
+  ~PasswordManagerPresenterTest() override {
+    store_->ShutdownOnUIThread();
+    scoped_task_environment_.RunUntilIdle();
+  }
+
   void AddPasswordEntry(const GURL& origin,
                         const std::string& user_name,
-                        const std::string& password);
-  void AddPasswordException(const GURL& origin);
-  void UpdateLists();
-  MockPasswordUIView* GetUIController() { return mock_controller_.get(); }
+                        const std::string& password) {
+    autofill::PasswordForm form;
+    form.origin = origin;
+    form.username_element = base::ASCIIToUTF16("Email");
+    form.username_value = base::ASCIIToUTF16(user_name);
+    form.password_element = base::ASCIIToUTF16("Passwd");
+    form.password_value = base::ASCIIToUTF16(password);
+    store_->AddLogin(form);
+  }
+
+  void AddPasswordException(const GURL& origin) {
+    autofill::PasswordForm form;
+    form.origin = origin;
+    form.blacklisted_by_user = true;
+    store_->AddLogin(form);
+  }
+
+  void UpdatePasswordLists() {
+    mock_controller_.GetPasswordManagerPresenter()->UpdatePasswordLists();
+    scoped_task_environment_.RunUntilIdle();
+  }
+
+  MockPasswordUIView& GetUIController() { return mock_controller_; }
 
  private:
-  content::TestBrowserThreadBundle thread_bundle_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  content::TestBrowserThreadBundle thread_bundle_{
+      content::TestBrowserThreadBundle::PLAIN_MAINLOOP};
   TestingProfile profile_;
-  std::unique_ptr<MockPasswordUIView> mock_controller_;
+  MockPasswordUIView mock_controller_{&profile_};
+  scoped_refptr<password_manager::PasswordStore> store_;
 
   DISALLOW_COPY_AND_ASSIGN(PasswordManagerPresenterTest);
 };
 
-void PasswordManagerPresenterTest::AddPasswordEntry(
-    const GURL& origin,
-    const std::string& user_name,
-    const std::string& password) {
-  std::unique_ptr<autofill::PasswordForm> form(new autofill::PasswordForm());
-  form->origin = origin;
-  form->username_element = base::ASCIIToUTF16("Email");
-  form->username_value = base::ASCIIToUTF16(user_name);
-  form->password_element = base::ASCIIToUTF16("Passwd");
-  form->password_value = base::ASCIIToUTF16(password);
-  mock_controller_->GetPasswordManagerPresenter()->password_list_.push_back(
-      std::move(form));
-}
-
-void PasswordManagerPresenterTest::AddPasswordException(const GURL& origin) {
-  std::unique_ptr<autofill::PasswordForm> form(new autofill::PasswordForm());
-  form->origin = origin;
-  mock_controller_->GetPasswordManagerPresenter()
-      ->password_exception_list_.push_back(std::move(form));
-}
-
-void PasswordManagerPresenterTest::UpdateLists() {
-  mock_controller_->GetPasswordManagerPresenter()->SetPasswordList();
-  mock_controller_->GetPasswordManagerPresenter()->SetPasswordExceptionList();
-}
-
 namespace {
 
 TEST_F(PasswordManagerPresenterTest, UIControllerIsCalled) {
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(0u))));
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordExceptionList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(0u))));
-  UpdateLists();
+  UpdatePasswordLists();
+
   GURL pass_origin("http://abc1.com");
   AddPasswordEntry(pass_origin, "test@gmail.com", "test");
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordExceptionList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(0u))));
-  UpdateLists();
+  UpdatePasswordLists();
+
   GURL except_origin("http://abc2.com");
   AddPasswordException(except_origin);
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordExceptionList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  UpdateLists();
+  UpdatePasswordLists();
+
   GURL pass_origin2("http://example.com");
   AddPasswordEntry(pass_origin2, "test@gmail.com", "test");
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(2u))));
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordExceptionList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  UpdateLists();
+  UpdatePasswordLists();
 }
 
 // Check that only stored passwords, not blacklisted entries, are provided for
@@ -141,18 +147,18 @@
 TEST_F(PasswordManagerPresenterTest, BlacklistedPasswordsNotExported) {
   AddPasswordEntry(GURL("http://abc1.com"), "test@gmail.com", "test");
   AddPasswordException(GURL("http://abc2.com"));
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordExceptionList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  UpdateLists();
+  UpdatePasswordLists();
 
   std::vector<std::unique_ptr<autofill::PasswordForm>> passwords_for_export =
-      GetUIController()->GetPasswordManagerPresenter()->GetAllPasswords();
+      GetUIController().GetPasswordManagerPresenter()->GetAllPasswords();
   EXPECT_EQ(1u, passwords_for_export.size());
   EXPECT_THAT(passwords_for_export, Each(IsNotBlacklisted()));
 }
@@ -164,18 +170,18 @@
   const GURL kSameOrigin("https://abc.com");
   AddPasswordEntry(kSameOrigin, "test@gmail.com", "test");
   AddPasswordException(kSameOrigin);
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  EXPECT_CALL(*GetUIController(),
+  EXPECT_CALL(GetUIController(),
               SetPasswordExceptionList(Property(
                   &std::vector<std::unique_ptr<autofill::PasswordForm>>::size,
                   Eq(1u))));
-  UpdateLists();
+  UpdatePasswordLists();
 
   std::vector<std::unique_ptr<autofill::PasswordForm>> passwords_for_export =
-      GetUIController()->GetPasswordManagerPresenter()->GetAllPasswords();
+      GetUIController().GetPasswordManagerPresenter()->GetAllPasswords();
   ASSERT_EQ(1u, passwords_for_export.size());
   EXPECT_EQ(kSameOrigin, passwords_for_export[0]->origin);
 }
diff --git a/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc b/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc
index 3bf3aa2..9eea1a5 100644
--- a/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc
@@ -214,7 +214,7 @@
 
   void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
     LogoServiceFactory::GetInstance()->SetTestingFactory(
-        context, &LocalNTPDoodleTest::CreateLogoService);
+        context, base::BindRepeating(&LocalNTPDoodleTest::CreateLogoService));
   }
 
   base::test::ScopedFeatureList feature_list_;
diff --git a/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc b/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc
index 072f031d..2cab77df 100644
--- a/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_one_google_bar_browsertest.cc
@@ -83,7 +83,9 @@
 
   void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
     OneGoogleBarServiceFactory::GetInstance()->SetTestingFactory(
-        context, &LocalNTPOneGoogleBarSmokeTest::CreateOneGoogleBarService);
+        context,
+        base::BindRepeating(
+            &LocalNTPOneGoogleBarSmokeTest::CreateOneGoogleBarService));
   }
 
   base::test::ScopedFeatureList feature_list_;
diff --git a/chrome/browser/ui/search/search_ipc_router_unittest.cc b/chrome/browser/ui/search/search_ipc_router_unittest.cc
index 0023cad..2def16df 100644
--- a/chrome/browser/ui/search/search_ipc_router_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_unittest.cc
@@ -10,6 +10,7 @@
 #include <tuple>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/field_trial.h"
@@ -138,7 +139,7 @@
 
     TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
         profile(),
-        &TemplateURLServiceFactory::BuildInstanceFor);
+        base::BindRepeating(&TemplateURLServiceFactory::BuildInstanceFor));
     TemplateURLService* template_url_service =
         TemplateURLServiceFactory::GetForProfile(profile());
     search_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index 7788e19..3d7079d0 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -11,6 +11,7 @@
 #include <tuple>
 #include <utility>
 
+#include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/signin/fake_signin_manager_builder.h"
@@ -117,9 +118,10 @@
   content::BrowserContext* CreateBrowserContext() override {
     TestingProfile::Builder builder;
     builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
-                              BuildFakeSigninManagerBase);
-    builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(),
-                              BuildMockProfileSyncService);
+                              base::BindRepeating(&BuildFakeSigninManagerBase));
+    builder.AddTestingFactory(
+        ProfileSyncServiceFactory::GetInstance(),
+        base::BindRepeating(&BuildMockProfileSyncService));
     return builder.Build().release();
   }
 
diff --git a/chrome/browser/ui/views/autofill/migratable_card_view.cc b/chrome/browser/ui/views/autofill/migratable_card_view.cc
index 338af4ea..465d4572 100644
--- a/chrome/browser/ui/views/autofill/migratable_card_view.cc
+++ b/chrome/browser/ui/views/autofill/migratable_card_view.cc
@@ -127,10 +127,10 @@
   card_network_and_last_four_digits->AddChildView(card_description.release());
 
   std::unique_ptr<views::Label> card_expiration =
-      std::make_unique<views::Label>(migratable_credit_card.credit_card()
-                                         .AbbreviatedExpirationDateForDisplay(),
-                                     views::style::CONTEXT_LABEL,
-                                     ChromeTextStyle::STYLE_SECONDARY);
+      std::make_unique<views::Label>(
+          migratable_credit_card.credit_card()
+              .AbbreviatedExpirationDateForDisplay(/*with_prefix=*/true),
+          views::style::CONTEXT_LABEL, ChromeTextStyle::STYLE_SECONDARY);
   AddChildView(card_expiration.release());
 
   delete_card_from_local_button_ = views::CreateVectorImageButton(listener);
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
index 54005152..ddf9c3c0f 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views.cc
@@ -17,6 +17,7 @@
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/legal_message_line.h"
 #include "components/autofill/core/browser/ui/save_card_bubble_controller.h"
+#include "components/autofill/core/common/autofill_features.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -199,8 +200,9 @@
   box_layout->SetFlexForView(spacer, /*flex=*/1);
 
   description_view->AddChildView(new views::Label(
-      card.AbbreviatedExpirationDateForDisplay(), CONTEXT_BODY_TEXT_LARGE,
-      ChromeTextStyle::STYLE_SECONDARY));
+      card.AbbreviatedExpirationDateForDisplay(
+          !features::IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled()),
+      CONTEXT_BODY_TEXT_LARGE, ChromeTextStyle::STYLE_SECONDARY));
 
   return view;
 }
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index c4025a0..01a27d3 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -714,6 +714,12 @@
   }
 
   if (ShowCustomTitle()) {
+    if (!ShowCustomIcon()) {
+      // This matches native Windows 10 UWP apps that don't have window icons.
+      constexpr int kMinimumTitleLeftBorderMargin = 11;
+      DCHECK_LE(next_leading_x, kMinimumTitleLeftBorderMargin);
+      next_leading_x = kMinimumTitleLeftBorderMargin;
+    }
     window_title_->SetText(browser_view()->GetWindowTitle());
     const int max_text_width = std::max(0, next_trailing_x - next_leading_x);
     window_title_->SetBounds(next_leading_x, window_icon_bounds.y(),
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
index 5dc7740..011a9eb 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -479,7 +479,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest,
-                       TestScrollingPageAndSwitchingToNTP) {
+                       DISABLED_TestScrollingPageAndSwitchingToNTP) {
   ToggleTabletMode();
   ASSERT_TRUE(GetTabletModeEnabled());
   EXPECT_TRUE(top_controls_slide_controller()->IsEnabled());
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
index d30f53b..caac5642 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_unittest.cc
@@ -21,10 +21,7 @@
 #include "content/public/browser/ssl_status.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_web_contents_factory.h"
-#include "device/base/mock_device_client.h"
-#include "device/usb/mock_usb_device.h"
-#include "device/usb/mock_usb_service.h"
-#include "device/usb/mojo/type_converters.h"
+#include "device/usb/public/cpp/fake_usb_device_manager.h"
 #include "device/usb/public/mojom/device.mojom.h"
 #include "ppapi/buildflags/buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -188,7 +185,6 @@
   void TearDown() override { parent_window_->CloseNow(); }
 
  protected:
-  device::MockDeviceClient device_client_;
   ScopedWebContentsTestHelper web_contents_helper_;
   views::ScopedViewsTestHelper views_helper_;
 
@@ -303,13 +299,17 @@
   EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count());
 
   const GURL origin = GURL(kUrl).GetOrigin();
-  scoped_refptr<device::UsbDevice> device =
-      new device::MockUsbDevice(0, 0, "Google", "Gizmo", "1234567890");
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
-  device_client_.usb_service()->AddDevice(device);
+
+  // Connect the UsbChooserContext with FakeUsbDeviceManager.
+  device::FakeUsbDeviceManager usb_device_manager;
+  device::mojom::UsbDeviceManagerPtr device_manager_ptr;
+  usb_device_manager.AddBinding(mojo::MakeRequest(&device_manager_ptr));
   UsbChooserContext* store =
       UsbChooserContextFactory::GetForProfile(web_contents_helper_.profile());
+  store->SetDeviceManagerForTesting(std::move(device_manager_ptr));
+
+  auto device_info = usb_device_manager.CreateAndAddDevice(
+      0, 0, "Google", "Gizmo", "1234567890");
   store->GrantDevicePermission(origin, origin, *device_info);
 
   PermissionInfoList list;
@@ -336,7 +336,7 @@
   button_listener->ButtonPressed(button, event);
   api_->SetPermissionInfo(list);
   EXPECT_EQ(kExpectedChildren, api_->permissions_view()->child_count());
-  EXPECT_FALSE(store->HasDevicePermission(origin, origin, device));
+  EXPECT_FALSE(store->HasDevicePermission(origin, origin, *device_info));
 }
 
 TEST_F(PageInfoBubbleViewTest, SetPermissionInfoForUsbGuard) {
diff --git a/chrome/browser/ui/webui/OWNERS b/chrome/browser/ui/webui/OWNERS
index 211ccfc8..3d2141d 100644
--- a/chrome/browser/ui/webui/OWNERS
+++ b/chrome/browser/ui/webui/OWNERS
@@ -22,4 +22,6 @@
 
 per-file sync_internals*=file://components/sync/OWNERS
 
+per-file invalidations_message_handler.*=file://components/invalidation/OWNERS
+
 # COMPONENT: UI>Browser>WebUI
diff --git a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
index 78b914f..a231a3f9 100644
--- a/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
+++ b/chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc
@@ -40,7 +40,6 @@
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/url_data_source.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -461,11 +460,6 @@
   content::RenderFrameHost* render_frame_host = web_contents->GetMainFrame();
   const GURL url = file->GetURL();
 
-  content::StoragePartition* storage_partition =
-      content::BrowserContext::GetStoragePartition(
-          web_contents->GetBrowserContext(),
-          render_frame_host->GetSiteInstance());
-
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("md_downloads_dom_handler", R"(
         semantics {
@@ -489,8 +483,7 @@
   auto dl_params = std::make_unique<download::DownloadUrlParameters>(
       url, render_frame_host->GetProcess()->GetID(),
       render_frame_host->GetRenderViewHost()->GetRoutingID(),
-      render_frame_host->GetRoutingID(),
-      storage_partition->GetURLRequestContext(), traffic_annotation);
+      render_frame_host->GetRoutingID(), traffic_annotation);
   dl_params->set_content_initiated(true);
   dl_params->set_initiator(url::Origin::Create(GURL("chrome://downloads")));
   dl_params->set_download_source(download::DownloadSource::FROM_RENDERER);
diff --git a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
index 4188e82..4e6b381 100644
--- a/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
+++ b/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
@@ -66,8 +66,7 @@
       base::Bind(&QuotaInternalsProxy::DidDumpOriginInfoTable,
                  weak_factory_.GetWeakPtr()));
 
-  std::map<std::string, std::string> stats;
-  quota_manager_->GetStatistics(&stats);
+  std::map<std::string, std::string> stats = quota_manager_->GetStatistics();
   ReportStatistics(stats);
 }
 
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index ff58eb41..5f7c247 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -537,8 +537,6 @@
       {"clearBrowsingHistory", IDS_SETTINGS_CLEAR_BROWSING_HISTORY},
       {"clearBrowsingHistorySummary",
        IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY},
-      {"clearBrowsingHistorySummarySignedIn",
-       IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNC_ERROR},
       {"clearDownloadHistory", IDS_SETTINGS_CLEAR_DOWNLOAD_HISTORY},
       {"clearCache", IDS_SETTINGS_CLEAR_CACHE},
       {"clearCookies", IDS_SETTINGS_CLEAR_COOKIES},
@@ -564,6 +562,11 @@
   };
 
   html_source->AddString(
+      "clearBrowsingHistorySummarySignedIn",
+      l10n_util::GetStringFUTF16(
+          IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SIGNED_IN,
+          base::ASCIIToUTF16(chrome::kMyActivityUrlInClearBrowsingData)));
+  html_source->AddString(
       "clearBrowsingHistorySummarySynced",
       l10n_util::GetStringFUTF16(
           IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED,
diff --git a/chrome/browser/usb/usb_blocklist.cc b/chrome/browser/usb/usb_blocklist.cc
index ef1b8c67..2e0953bf 100644
--- a/chrome/browser/usb/usb_blocklist.cc
+++ b/chrome/browser/usb/usb_blocklist.cc
@@ -11,7 +11,6 @@
 #include "base/strings/string_split.h"
 #include "components/variations/variations_associated_data.h"
 #include "device/usb/public/mojom/device.mojom.h"
-#include "device/usb/usb_device.h"
 
 namespace {
 
@@ -127,12 +126,6 @@
 }
 
 bool UsbBlocklist::IsExcluded(
-    const scoped_refptr<const device::UsbDevice>& device) const {
-  return IsExcluded(Entry(device->vendor_id(), device->product_id(),
-                          device->device_version()));
-}
-
-bool UsbBlocklist::IsExcluded(
     const device::mojom::UsbDeviceInfo& device_info) const {
   uint16_t device_version = device_info.device_version_major << 8 |
                             device_info.device_version_minor << 4 |
diff --git a/chrome/browser/usb/usb_blocklist.h b/chrome/browser/usb/usb_blocklist.h
index b277180b..4587d41 100644
--- a/chrome/browser/usb/usb_blocklist.h
+++ b/chrome/browser/usb/usb_blocklist.h
@@ -14,8 +14,6 @@
 #include "base/memory/ref_counted.h"
 
 namespace device {
-class UsbDevice;
-
 namespace mojom {
 class UsbDeviceInfo;
 }
@@ -46,7 +44,6 @@
 
   // Returns if a device is excluded from access.
   bool IsExcluded(const Entry& entry) const;
-  bool IsExcluded(const scoped_refptr<const device::UsbDevice>& device) const;
   bool IsExcluded(const device::mojom::UsbDeviceInfo& device_info) const;
 
   // Size of the blocklist.
diff --git a/chrome/browser/usb/usb_browsertest.cc b/chrome/browser/usb/usb_browsertest.cc
index f09f46d..c6b089c8 100644
--- a/chrome/browser/usb/usb_browsertest.cc
+++ b/chrome/browser/usb/usb_browsertest.cc
@@ -23,9 +23,8 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
-#include "device/base/mock_device_client.h"
-#include "device/usb/mock_usb_device.h"
-#include "device/usb/mock_usb_service.h"
+#include "device/usb/public/cpp/fake_usb_device_manager.h"
+#include "device/usb/public/mojom/device.mojom.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 
@@ -36,8 +35,9 @@
 }  // namespace blink
 
 using content::RenderFrameHost;
-using device::MockDeviceClient;
-using device::MockUsbDevice;
+using device::FakeUsbDeviceManager;
+using device::mojom::UsbDeviceManagerPtr;
+using device::mojom::UsbDeviceInfoPtr;
 
 namespace {
 
@@ -127,13 +127,13 @@
   void SetUpOnMainThread() override {
     embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
     ASSERT_TRUE(embedded_test_server()->Start());
-    device_client_.reset(new MockDeviceClient());
-    AddMockDevice("123456");
+    AddFakeDevice("123456");
 
-    // Force the UsbChooserContext to be created before the test begins. This
-    // ensures that it is created before any instances of DeviceManagerImpl and
-    // thus may expose ordering bugs not normally encountered.
-    UsbChooserContextFactory::GetForProfile(browser()->profile());
+    // Connect with the FakeUsbDeviceManager.
+    UsbDeviceManagerPtr device_manager_ptr;
+    device_manager_.AddBinding(mojo::MakeRequest(&device_manager_ptr));
+    UsbChooserContextFactory::GetForProfile(browser()->profile())
+        ->SetDeviceManagerForTesting(std::move(device_manager_ptr));
 
     original_content_browser_client_ =
         content::SetBrowserClientForTesting(&test_content_browser_client_);
@@ -151,17 +151,16 @@
     content::SetBrowserClientForTesting(original_content_browser_client_);
   }
 
-  void AddMockDevice(const std::string& serial_number) {
-    DCHECK(!mock_device_);
-    mock_device_ = base::MakeRefCounted<MockUsbDevice>(
+  void AddFakeDevice(const std::string& serial_number) {
+    DCHECK(!fake_device_info_);
+    fake_device_info_ = device_manager_.CreateAndAddDevice(
         0, 0, "Test Manufacturer", "Test Device", serial_number);
-    device_client_->usb_service()->AddDevice(mock_device_);
   }
 
-  void RemoveMockDevice() {
-    DCHECK(mock_device_);
-    device_client_->usb_service()->RemoveDevice(mock_device_);
-    mock_device_ = nullptr;
+  void RemoveFakeDevice() {
+    DCHECK(fake_device_info_);
+    device_manager_.RemoveDevice(fake_device_info_->guid);
+    fake_device_info_ = nullptr;
   }
 
   const GURL& origin() { return origin_; }
@@ -169,8 +168,8 @@
   void UseRealChooser() { test_content_browser_client_.UseRealChooser(); }
 
  private:
-  std::unique_ptr<MockDeviceClient> device_client_;
-  scoped_refptr<MockUsbDevice> mock_device_;
+  FakeUsbDeviceManager device_manager_;
+  UsbDeviceInfoPtr fake_device_info_;
   TestContentBrowserClient test_content_browser_client_;
   content::ContentBrowserClient* original_content_browser_client_;
   GURL origin_;
@@ -257,7 +256,7 @@
       &result));
   EXPECT_EQ("123456", result);
 
-  RemoveMockDevice();
+  RemoveFakeDevice();
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
@@ -270,7 +269,7 @@
       &result));
   EXPECT_EQ("123456", result);
 
-  AddMockDevice("123456");
+  AddFakeDevice("123456");
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
@@ -289,8 +288,8 @@
       browser()->tab_strip_model()->GetActiveWebContents();
 
   // Replace the default mock device with one that has no serial number.
-  RemoveMockDevice();
-  AddMockDevice("");
+  RemoveFakeDevice();
+  AddFakeDevice("");
   base::RunLoop().RunUntilIdle();
 
   std::string result;
@@ -308,7 +307,7 @@
       &result));
   EXPECT_EQ("", result);
 
-  RemoveMockDevice();
+  RemoveFakeDevice();
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc
index bc2d076..b195b4b 100644
--- a/chrome/browser/usb/usb_chooser_context.cc
+++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -13,12 +13,11 @@
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/usb/usb_blocklist.h"
-#include "device/base/device_client.h"
-#include "device/usb/mojo/type_converters.h"
+#include "content/public/common/service_manager_connection.h"
+#include "device/usb/mojo/device_manager_impl.h"
 #include "device/usb/public/mojom/device.mojom.h"
-#include "device/usb/usb_device.h"
-
-using device::UsbDevice;
+#include "services/device/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
 
 namespace {
 
@@ -96,10 +95,16 @@
   if (device_manager_)
     return;
 
-  // TODO(donna.wu@intel.com): Request UsbDeviceManagerPtr from DeviceService
-  // after moving //device/usb to //services/device.
-  device_manager_instance_ = std::make_unique<device::usb::DeviceManagerImpl>();
-  device_manager_instance_->AddBinding(mojo::MakeRequest(&device_manager_));
+  // Request UsbDeviceManagerPtr from DeviceService.
+  content::ServiceManagerConnection::GetForProcess()
+      ->GetConnector()
+      ->BindInterface(device::mojom::kServiceName,
+                      mojo::MakeRequest(&device_manager_));
+  SetUpDeviceManagerConnection();
+}
+
+void UsbChooserContext::SetUpDeviceManagerConnection() {
+  DCHECK(device_manager_);
   device_manager_.set_connection_error_handler(
       base::BindOnce(&UsbChooserContext::OnDeviceManagerConnectionError,
                      base::Unretained(this)));
@@ -245,20 +250,6 @@
   return false;
 }
 
-bool UsbChooserContext::HasDevicePermission(
-    const GURL& requesting_origin,
-    const GURL& embedding_origin,
-    scoped_refptr<const device::UsbDevice> device) {
-  if (!device)
-    return false;
-
-  device::mojom::UsbDeviceInfoPtr device_info =
-      device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
-
-  return HasDevicePermission(requesting_origin, embedding_origin, *device_info);
-}
-
 void UsbChooserContext::GetDevices(
     device::mojom::UsbDeviceManager::GetDevicesCallback callback) {
   EnsureConnectionWithDeviceManager();
@@ -337,6 +328,10 @@
   ephemeral_dicts_.clear();
 }
 
-void UsbChooserContext::DestroyDeviceManagerForTesting() {
-  device_manager_instance_.reset();
+void UsbChooserContext::SetDeviceManagerForTesting(
+    device::mojom::UsbDeviceManagerPtr fake_device_manager) {
+  DCHECK(!device_manager_);
+  DCHECK(fake_device_manager);
+  device_manager_ = std::move(fake_device_manager);
+  SetUpDeviceManagerConnection();
 }
diff --git a/chrome/browser/usb/usb_chooser_context.h b/chrome/browser/usb/usb_chooser_context.h
index 47629d4..0fb6a84 100644
--- a/chrome/browser/usb/usb_chooser_context.h
+++ b/chrome/browser/usb/usb_chooser_context.h
@@ -56,10 +56,6 @@
                            const GURL& embedding_origin,
                            const device::mojom::UsbDeviceInfo& device_info);
 
-  bool HasDevicePermission(const GURL& requesting_origin,
-                           const GURL& embedding_origin,
-                           scoped_refptr<const device::UsbDevice> device);
-
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
@@ -71,7 +67,8 @@
 
   base::WeakPtr<UsbChooserContext> AsWeakPtr();
 
-  void DestroyDeviceManagerForTesting();
+  void SetDeviceManagerForTesting(
+      device::mojom::UsbDeviceManagerPtr fake_device_manager);
 
  private:
   // ChooserContextBase implementation.
@@ -84,6 +81,7 @@
 
   void OnDeviceManagerConnectionError();
   void EnsureConnectionWithDeviceManager();
+  void SetUpDeviceManagerConnection();
 
   bool is_incognito_;
   std::map<std::pair<GURL, GURL>, std::set<std::string>> ephemeral_devices_;
@@ -91,10 +89,6 @@
 
   std::unique_ptr<UsbPolicyAllowedDevices> usb_policy_allowed_devices_;
 
-  // TODO(donna.wu@intel.com): Have the Device Service own this instance in the
-  // near future.
-  std::unique_ptr<device::usb::DeviceManagerImpl> device_manager_instance_;
-
   // Connection to |device_manager_instance_|.
   device::mojom::UsbDeviceManagerPtr device_manager_;
   mojo::AssociatedBinding<device::mojom::UsbDeviceManagerClient>
diff --git a/chrome/browser/usb/usb_chooser_context_unittest.cc b/chrome/browser/usb/usb_chooser_context_unittest.cc
index 094d7302..43f5e4b 100644
--- a/chrome/browser/usb/usb_chooser_context_unittest.cc
+++ b/chrome/browser/usb/usb_chooser_context_unittest.cc
@@ -14,14 +14,12 @@
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "device/base/mock_device_client.h"
-#include "device/usb/mock_usb_device.h"
-#include "device/usb/mock_usb_service.h"
-#include "device/usb/mojo/type_converters.h"
+#include "device/usb/public/cpp/fake_usb_device_manager.h"
 #include "device/usb/public/mojom/device.mojom.h"
+#include "device/usb/public/mojom/device_manager.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
-using device::MockUsbDevice;
-using device::UsbDevice;
+using device::mojom::UsbDeviceInfoPtr;
 
 namespace {
 
@@ -33,7 +31,15 @@
  protected:
   Profile* profile() { return &profile_; }
 
-  device::MockDeviceClient device_client_;
+  UsbChooserContext* GetChooserContext(Profile* profile) {
+    auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile);
+    device::mojom::UsbDeviceManagerPtr device_manager_ptr;
+    device_manager_.AddBinding(mojo::MakeRequest(&device_manager_ptr));
+    chooser_context->SetDeviceManagerForTesting(std::move(device_manager_ptr));
+    return chooser_context;
+  }
+
+  device::FakeUsbDeviceManager device_manager_;
 
  private:
   content::TestBrowserThreadBundle thread_bundle_;
@@ -56,12 +62,9 @@
 
 TEST_F(UsbChooserContextTest, CheckGrantAndRevokePermission) {
   GURL origin("https://www.google.com");
-  scoped_refptr<UsbDevice> device =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "123ABC");
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
-  device_client_.usb_service()->AddDevice(device);
-  UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile());
+  UsbDeviceInfoPtr device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "123ABC");
+  UsbChooserContext* store = GetChooserContext(profile());
 
   base::DictionaryValue object_dict;
   object_dict.SetString("name", "Gizmo");
@@ -94,21 +97,16 @@
 
 TEST_F(UsbChooserContextTest, CheckGrantAndRevokeEphemeralPermission) {
   GURL origin("https://www.google.com");
-  scoped_refptr<UsbDevice> device =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "");
-  scoped_refptr<UsbDevice> other_device =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "");
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
-  auto other_device_info = device::mojom::UsbDeviceInfo::From(*other_device);
-  DCHECK(other_device_info);
+  UsbDeviceInfoPtr device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
+  UsbDeviceInfoPtr other_device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
 
-  device_client_.usb_service()->AddDevice(device);
-  UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile());
+  UsbChooserContext* store = GetChooserContext(profile());
 
   base::DictionaryValue object_dict;
   object_dict.SetString("name", "Gizmo");
-  object_dict.SetString("ephemeral-guid", device->guid());
+  object_dict.SetString("ephemeral-guid", device_info->guid);
 
   EXPECT_FALSE(store->HasDevicePermission(origin, origin, *device_info));
   store->GrantDevicePermission(origin, origin, *device_info);
@@ -136,18 +134,15 @@
 
 TEST_F(UsbChooserContextTest, DisconnectDeviceWithPermission) {
   GURL origin("https://www.google.com");
-  scoped_refptr<UsbDevice> device =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "123ABC");
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
+  UsbDeviceInfoPtr device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "123ABC");
 
-  device_client_.usb_service()->AddDevice(device);
-  UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile());
+  UsbChooserContext* store = GetChooserContext(profile());
   {
     // Call GetDevices once to make sure the connection with DeviceManager has
     // been set up, so that it can be notified when device is removed.
     std::set<std::string> guids;
-    guids.insert(device->guid());
+    guids.insert(device_info->guid);
     base::RunLoop loop;
     store->GetDevices(
         base::BindOnce(&ExpectDevicesAndThen, guids, loop.QuitClosure()));
@@ -164,7 +159,7 @@
       store->GetAllGrantedObjects();
   EXPECT_EQ(1u, all_origin_objects.size());
 
-  device_client_.usb_service()->RemoveDevice(device);
+  device_manager_.RemoveDevice(device_info->guid);
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(store->HasDevicePermission(origin, origin, *device_info));
@@ -173,13 +168,9 @@
   all_origin_objects = store->GetAllGrantedObjects();
   EXPECT_EQ(1u, all_origin_objects.size());
 
-  scoped_refptr<UsbDevice> reconnected_device =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "123ABC");
-  auto reconnected_device_info =
-      device::mojom::UsbDeviceInfo::From(*reconnected_device);
-  DCHECK(reconnected_device_info);
+  UsbDeviceInfoPtr reconnected_device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "123ABC");
 
-  device_client_.usb_service()->AddDevice(reconnected_device);
   EXPECT_TRUE(
       store->HasDevicePermission(origin, origin, *reconnected_device_info));
   objects = store->GetGrantedObjects(origin, origin);
@@ -190,18 +181,15 @@
 
 TEST_F(UsbChooserContextTest, DisconnectDeviceWithEphemeralPermission) {
   GURL origin("https://www.google.com");
-  scoped_refptr<UsbDevice> device =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "");
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
+  UsbDeviceInfoPtr device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
 
-  device_client_.usb_service()->AddDevice(device);
-  UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile());
+  UsbChooserContext* store = GetChooserContext(profile());
   {
     // Call GetDevices once to make sure the connection with DeviceManager has
     // been set up, so that it can be notified when device is removed.
     std::set<std::string> guids;
-    guids.insert(device->guid());
+    guids.insert(device_info->guid);
     base::RunLoop loop;
     store->GetDevices(
         base::BindOnce(&ExpectDevicesAndThen, guids, loop.QuitClosure()));
@@ -218,7 +206,7 @@
       store->GetAllGrantedObjects();
   EXPECT_EQ(1u, all_origin_objects.size());
 
-  device_client_.usb_service()->RemoveDevice(device);
+  device_manager_.RemoveDevice(device_info->guid);
   base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(store->HasDevicePermission(origin, origin, *device_info));
@@ -227,13 +215,9 @@
   all_origin_objects = store->GetAllGrantedObjects();
   EXPECT_EQ(0u, all_origin_objects.size());
 
-  scoped_refptr<UsbDevice> reconnected_device =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "");
-  auto reconnected_device_info =
-      device::mojom::UsbDeviceInfo::From(*reconnected_device);
-  DCHECK(reconnected_device_info);
+  UsbDeviceInfoPtr reconnected_device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
 
-  device_client_.usb_service()->AddDevice(reconnected_device);
   EXPECT_FALSE(
       store->HasDevicePermission(origin, origin, *reconnected_device_info));
   objects = store->GetGrantedObjects(origin, origin);
@@ -244,20 +228,14 @@
 
 TEST_F(UsbChooserContextTest, GrantPermissionInIncognito) {
   GURL origin("https://www.google.com");
-  UsbChooserContext* store = UsbChooserContextFactory::GetForProfile(profile());
-  UsbChooserContext* incognito_store = UsbChooserContextFactory::GetForProfile(
-      profile()->GetOffTheRecordProfile());
+  UsbChooserContext* store = GetChooserContext(profile());
+  UsbChooserContext* incognito_store =
+      GetChooserContext(profile()->GetOffTheRecordProfile());
 
-  scoped_refptr<UsbDevice> device1 =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "");
-  scoped_refptr<UsbDevice> device2 =
-      new MockUsbDevice(0, 0, "Google", "Gizmo", "");
-  auto device_info_1 = device::mojom::UsbDeviceInfo::From(*device1);
-  DCHECK(device_info_1);
-  auto device_info_2 = device::mojom::UsbDeviceInfo::From(*device2);
-  DCHECK(device_info_2);
-  device_client_.usb_service()->AddDevice(device1);
-  device_client_.usb_service()->AddDevice(device2);
+  UsbDeviceInfoPtr device_info_1 =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
+  UsbDeviceInfoPtr device_info_2 =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
 
   store->GrantDevicePermission(origin, origin, *device_info_1);
   EXPECT_TRUE(store->HasDevicePermission(origin, origin, *device_info_1));
@@ -295,24 +273,17 @@
 TEST_F(UsbChooserContextTest, UsbGuardPermission) {
   const GURL kFooOrigin("https://foo.com");
   const GURL kBarOrigin("https://bar.com");
-  scoped_refptr<UsbDevice> device =
-      base::MakeRefCounted<MockUsbDevice>(0, 0, "Google", "Gizmo", "ABC123");
-  scoped_refptr<UsbDevice> ephemeral_device =
-      base::MakeRefCounted<MockUsbDevice>(0, 0, "Google", "Gizmo", "");
-  device_client_.usb_service()->AddDevice(device);
-  device_client_.usb_service()->AddDevice(ephemeral_device);
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  DCHECK(device_info);
-  auto ephemeral_device_info =
-      device::mojom::UsbDeviceInfo::From(*ephemeral_device);
-  DCHECK(ephemeral_device_info);
+  UsbDeviceInfoPtr device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "ABC123");
+  UsbDeviceInfoPtr ephemeral_device_info =
+      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
 
   auto* map = HostContentSettingsMapFactory::GetForProfile(profile());
   map->SetContentSettingDefaultScope(kFooOrigin, kFooOrigin,
                                      CONTENT_SETTINGS_TYPE_USB_GUARD,
                                      std::string(), CONTENT_SETTING_BLOCK);
 
-  auto* store = UsbChooserContextFactory::GetForProfile(profile());
+  auto* store = GetChooserContext(profile());
   store->GrantDevicePermission(kFooOrigin, kFooOrigin, *device_info);
   store->GrantDevicePermission(kFooOrigin, kFooOrigin, *ephemeral_device_info);
   store->GrantDevicePermission(kBarOrigin, kBarOrigin, *device_info);
@@ -408,13 +379,8 @@
 
   auto* store = UsbChooserContextFactory::GetForProfile(profile());
 
-  scoped_refptr<UsbDevice> specific_device =
-      base::MakeRefCounted<MockUsbDevice>(1234, 5678, "Google", "Gizmo",
-                                          "ABC123");
-
-  auto specific_device_info =
-      device::mojom::UsbDeviceInfo::From(*specific_device);
-  DCHECK(specific_device_info);
+  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
+      1234, 5678, "Google", "Gizmo", "ABC123");
 
   ExpectNoPermissions(store, *specific_device_info);
 
@@ -436,13 +402,9 @@
 
   auto* store = UsbChooserContextFactory::GetForProfile(profile());
 
-  scoped_refptr<UsbDevice> vendor_related_device =
-      base::MakeRefCounted<MockUsbDevice>(1234, 8765, "Google", "Widget",
-                                          "XYZ987");
-
-  auto vendor_related_device_info =
-      device::mojom::UsbDeviceInfo::From(*vendor_related_device);
-  DCHECK(vendor_related_device_info);
+  UsbDeviceInfoPtr vendor_related_device_info =
+      device_manager_.CreateAndAddDevice(1234, 8765, "Google", "Widget",
+                                         "XYZ987");
 
   ExpectNoPermissions(store, *vendor_related_device_info);
 
@@ -466,13 +428,8 @@
 
   auto* store = UsbChooserContextFactory::GetForProfile(profile());
 
-  scoped_refptr<UsbDevice> unrelated_device =
-      base::MakeRefCounted<MockUsbDevice>(2468, 1357, "Cool", "Gadget",
-                                          "4W350M3");
-
-  auto unrelated_device_info =
-      device::mojom::UsbDeviceInfo::From(*unrelated_device);
-  DCHECK(unrelated_device_info);
+  UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice(
+      2468, 1357, "Cool", "Gadget", "4W350M3");
 
   ExpectNoPermissions(store, *unrelated_device_info);
 
@@ -499,19 +456,10 @@
 
   auto* store = UsbChooserContextFactory::GetForProfile(profile());
 
-  scoped_refptr<UsbDevice> specific_device =
-      base::MakeRefCounted<MockUsbDevice>(1234, 5678, "Google", "Gizmo",
-                                          "ABC123");
-  scoped_refptr<UsbDevice> unrelated_device =
-      base::MakeRefCounted<MockUsbDevice>(2468, 1357, "Cool", "Gadget",
-                                          "4W350M3");
-
-  auto specific_device_info =
-      device::mojom::UsbDeviceInfo::From(*specific_device);
-  auto unrelated_device_info =
-      device::mojom::UsbDeviceInfo::From(*unrelated_device);
-  DCHECK(specific_device_info);
-  DCHECK(unrelated_device_info);
+  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
+      1234, 5678, "Google", "Gizmo", "ABC123");
+  UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice(
+      2468, 1357, "Cool", "Gadget", "4W350M3");
 
   ExpectNoPermissions(store, *specific_device_info);
   ExpectNoPermissions(store, *unrelated_device_info);
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc
index 6e0f4873..7d9233b0 100644
--- a/chrome/browser/usb/usb_chooser_controller.cc
+++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -19,7 +19,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/usb/usb_chooser_controller_unittest.cc b/chrome/browser/usb/usb_chooser_controller_unittest.cc
index 7932cd9a..03b5bba 100644
--- a/chrome/browser/usb/usb_chooser_controller_unittest.cc
+++ b/chrome/browser/usb/usb_chooser_controller_unittest.cc
@@ -9,12 +9,14 @@
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/usb/usb_chooser_context.h"
+#include "chrome/browser/usb/usb_chooser_context_factory.h"
 #include "chrome/browser/usb/usb_chooser_controller.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
 #include "content/public/test/web_contents_tester.h"
-#include "device/base/mock_device_client.h"
-#include "device/usb/mock_usb_device.h"
-#include "device/usb/mock_usb_service.h"
+#include "device/usb/public/cpp/fake_usb_device_manager.h"
+#include "device/usb/public/mojom/device.mojom.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
@@ -53,6 +55,13 @@
     content::WebContentsTester* web_contents_tester =
         content::WebContentsTester::For(web_contents());
     web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl));
+
+    // Set fake device manager for UsbChooserContext.
+    device::mojom::UsbDeviceManagerPtr device_manager_ptr;
+    device_manager_.AddBinding(mojo::MakeRequest(&device_manager_ptr));
+    UsbChooserContextFactory::GetForProfile(profile())
+        ->SetDeviceManagerForTesting(std::move(device_manager_ptr));
+
     usb_chooser_controller_.reset(new UsbChooserController(
         main_rfh(), std::move(device_filters), std::move(callback)));
     mock_usb_chooser_view_.reset(new MockUsbChooserView());
@@ -63,15 +72,14 @@
   }
 
  protected:
-  scoped_refptr<device::MockUsbDevice> CreateMockUsbDevice(
+  device::mojom::UsbDeviceInfoPtr CreateAndAddFakeUsbDevice(
       const std::string& product_string,
       const std::string& serial_number) {
-    scoped_refptr<device::MockUsbDevice> device(new device::MockUsbDevice(
-        0, 1, "Google", product_string, serial_number));
-    return device;
+    return device_manager_.CreateAndAddDevice(0, 1, "Google", product_string,
+                                              serial_number);
   }
 
-  device::MockDeviceClient device_client_;
+  device::FakeUsbDeviceManager device_manager_;
   std::unique_ptr<UsbChooserController> usb_chooser_controller_;
   std::unique_ptr<MockUsbChooserView> mock_usb_chooser_view_;
 
@@ -80,84 +88,57 @@
 };
 
 TEST_F(UsbChooserControllerTest, AddDevice) {
-  scoped_refptr<device::MockUsbDevice> device_a =
-      CreateMockUsbDevice("a", "001");
   EXPECT_CALL(*mock_usb_chooser_view_, OnOptionAdded(0)).Times(1);
-  device_client_.usb_service()->AddDevice(device_a);
+  CreateAndAddFakeUsbDevice("a", "001");
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, usb_chooser_controller_->NumOptions());
   EXPECT_EQ(base::ASCIIToUTF16("a"), usb_chooser_controller_->GetOption(0));
 
-  scoped_refptr<device::MockUsbDevice> device_b =
-      CreateMockUsbDevice("b", "002");
   EXPECT_CALL(*mock_usb_chooser_view_, OnOptionAdded(1)).Times(1);
-  device_client_.usb_service()->AddDevice(device_b);
+  CreateAndAddFakeUsbDevice("b", "002");
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(2u, usb_chooser_controller_->NumOptions());
   EXPECT_EQ(base::ASCIIToUTF16("b"), usb_chooser_controller_->GetOption(1));
 
-  scoped_refptr<device::MockUsbDevice> device_c =
-      CreateMockUsbDevice("c", "003");
   EXPECT_CALL(*mock_usb_chooser_view_, OnOptionAdded(2)).Times(1);
-  device_client_.usb_service()->AddDevice(device_c);
+  CreateAndAddFakeUsbDevice("c", "003");
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(3u, usb_chooser_controller_->NumOptions());
   EXPECT_EQ(base::ASCIIToUTF16("c"), usb_chooser_controller_->GetOption(2));
 }
 
 TEST_F(UsbChooserControllerTest, RemoveDevice) {
-  scoped_refptr<device::MockUsbDevice> device_a =
-      CreateMockUsbDevice("a", "001");
-  device_client_.usb_service()->AddDevice(device_a);
-  scoped_refptr<device::MockUsbDevice> device_b =
-      CreateMockUsbDevice("b", "002");
-  device_client_.usb_service()->AddDevice(device_b);
-  scoped_refptr<device::MockUsbDevice> device_c =
-      CreateMockUsbDevice("c", "003");
-  device_client_.usb_service()->AddDevice(device_c);
+  auto device_a = CreateAndAddFakeUsbDevice("a", "001");
+  auto device_b = CreateAndAddFakeUsbDevice("b", "002");
+  auto device_c = CreateAndAddFakeUsbDevice("c", "003");
   base::RunLoop().RunUntilIdle();
 
   EXPECT_CALL(*mock_usb_chooser_view_, OnOptionRemoved(1)).Times(1);
-  device_client_.usb_service()->RemoveDevice(device_b);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2u, usb_chooser_controller_->NumOptions());
-  EXPECT_EQ(base::ASCIIToUTF16("a"), usb_chooser_controller_->GetOption(0));
-  EXPECT_EQ(base::ASCIIToUTF16("c"), usb_chooser_controller_->GetOption(1));
-
-  // Remove a non-existent device, the number of devices should not change.
-  scoped_refptr<device::MockUsbDevice> device_non_existent =
-      CreateMockUsbDevice("d", "001");
-  device_client_.usb_service()->RemoveDevice(device_non_existent);
+  device_manager_.RemoveDevice(device_b->guid);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(2u, usb_chooser_controller_->NumOptions());
   EXPECT_EQ(base::ASCIIToUTF16("a"), usb_chooser_controller_->GetOption(0));
   EXPECT_EQ(base::ASCIIToUTF16("c"), usb_chooser_controller_->GetOption(1));
 
   EXPECT_CALL(*mock_usb_chooser_view_, OnOptionRemoved(0)).Times(1);
-  device_client_.usb_service()->RemoveDevice(device_a);
+  device_manager_.RemoveDevice(device_a->guid);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1u, usb_chooser_controller_->NumOptions());
   EXPECT_EQ(base::ASCIIToUTF16("c"), usb_chooser_controller_->GetOption(0));
 
   EXPECT_CALL(*mock_usb_chooser_view_, OnOptionRemoved(0)).Times(1);
-  device_client_.usb_service()->RemoveDevice(device_c);
+  device_manager_.RemoveDevice(device_c->guid);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, usb_chooser_controller_->NumOptions());
 }
 
 TEST_F(UsbChooserControllerTest, AddAndRemoveDeviceWithSameName) {
-  scoped_refptr<device::MockUsbDevice> device_a_1 =
-      CreateMockUsbDevice("a", "001");
-  device_client_.usb_service()->AddDevice(device_a_1);
+  auto device_a_1 = CreateAndAddFakeUsbDevice("a", "001");
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::ASCIIToUTF16("a"), usb_chooser_controller_->GetOption(0));
 
-  scoped_refptr<device::MockUsbDevice> device_b =
-      CreateMockUsbDevice("b", "002");
-  device_client_.usb_service()->AddDevice(device_b);
-  scoped_refptr<device::MockUsbDevice> device_a_2 =
-      CreateMockUsbDevice("a", "002");
-  device_client_.usb_service()->AddDevice(device_a_2);
+  auto device_b = CreateAndAddFakeUsbDevice("b", "002");
+  auto device_a_2 = CreateAndAddFakeUsbDevice("a", "002");
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::ASCIIToUTF16("a (001)"),
             usb_chooser_controller_->GetOption(0));
@@ -165,7 +146,7 @@
   EXPECT_EQ(base::ASCIIToUTF16("a (002)"),
             usb_chooser_controller_->GetOption(2));
 
-  device_client_.usb_service()->RemoveDevice(device_a_1);
+  device_manager_.RemoveDevice(device_a_1->guid);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::ASCIIToUTF16("b"), usb_chooser_controller_->GetOption(0));
   EXPECT_EQ(base::ASCIIToUTF16("a"), usb_chooser_controller_->GetOption(1));
@@ -174,9 +155,7 @@
 TEST_F(UsbChooserControllerTest, UnknownDeviceName) {
   uint16_t vendor_id = 123;
   uint16_t product_id = 456;
-  scoped_refptr<device::MockUsbDevice> device =
-      new device::MockUsbDevice(vendor_id, product_id);
-  device_client_.usb_service()->AddDevice(device);
+  device_manager_.CreateAndAddDevice(vendor_id, product_id);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::ASCIIToUTF16("Unknown device [007b:01c8]"),
             usb_chooser_controller_->GetOption(0));
diff --git a/chrome/browser/usb/web_usb_service_impl.cc b/chrome/browser/usb/web_usb_service_impl.cc
index f9b3016..cc403bc4 100644
--- a/chrome/browser/usb/web_usb_service_impl.cc
+++ b/chrome/browser/usb/web_usb_service_impl.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/usb/usb_chooser_context_factory.h"
 #include "chrome/browser/usb/usb_tab_helper.h"
 #include "content/public/browser/browser_thread.h"
-#include "device/usb/mojo/type_converters.h"
 
 WebUsbServiceImpl::WebUsbServiceImpl(
     content::RenderFrameHost* render_frame_host,
diff --git a/chrome/browser/usb/web_usb_service_impl_unittest.cc b/chrome/browser/usb/web_usb_service_impl_unittest.cc
index 6d46df2..a1a5b60 100644
--- a/chrome/browser/usb/web_usb_service_impl_unittest.cc
+++ b/chrome/browser/usb/web_usb_service_impl_unittest.cc
@@ -18,25 +18,22 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/web_contents_tester.h"
-#include "device/base/mock_device_client.h"
-#include "device/usb/mock_usb_device.h"
-#include "device/usb/mock_usb_service.h"
-#include "device/usb/mojo/type_converters.h"
+#include "device/usb/public/cpp/fake_usb_device_info.h"
+#include "device/usb/public/cpp/fake_usb_device_manager.h"
 #include "device/usb/public/mojom/device.mojom.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
 using ::testing::_;
-using ::testing::AtMost;
 
 using blink::mojom::WebUsbServicePtr;
 using device::mojom::UsbDeviceInfo;
 using device::mojom::UsbDeviceInfoPtr;
 using device::mojom::UsbDeviceManagerClient;
 using device::mojom::UsbDeviceManagerClientAssociatedPtrInfo;
-using device::MockUsbDevice;
-using device::UsbDevice;
+using device::FakeUsbDeviceInfo;
 
 namespace {
 
@@ -61,7 +58,17 @@
   }
 
  protected:
+  void SimulateDeviceServiceCrash() { device_manager()->CloseAllBindings(); }
+
   void ConnectToService(blink::mojom::WebUsbServiceRequest request) {
+    // Set fake device manager for UsbChooserContext.
+    if (!device_manager()->IsBound()) {
+      device::mojom::UsbDeviceManagerPtr device_manager_ptr;
+      device_manager()->AddBinding(mojo::MakeRequest(&device_manager_ptr));
+      GetChooserContext()->SetDeviceManagerForTesting(
+          std::move(device_manager_ptr));
+    }
+
     if (!web_usb_service_)
       web_usb_service_.reset(new WebUsbServiceImpl(main_rfh(), nullptr));
 
@@ -72,9 +79,15 @@
     return UsbChooserContextFactory::GetForProfile(profile());
   }
 
-  device::MockDeviceClient device_client_;
+  device::FakeUsbDeviceManager* device_manager() {
+    if (!device_manager_) {
+      device_manager_ = std::make_unique<device::FakeUsbDeviceManager>();
+    }
+    return device_manager_.get();
+  }
 
  private:
+  std::unique_ptr<device::FakeUsbDeviceManager> device_manager_;
   std::unique_ptr<WebUsbServiceImpl> web_usb_service_;
   DISALLOW_COPY_AND_ASSIGN(WebUsbServiceImplTest);
 };
@@ -128,21 +141,18 @@
 TEST_F(WebUsbServiceImplTest, NoPermissionDevice) {
   GURL origin(kDefaultTestUrl);
 
-  scoped_refptr<UsbDevice> device0 =
-      new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
-  scoped_refptr<UsbDevice> device1 =
-      new MockUsbDevice(0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
-  scoped_refptr<UsbDevice> no_permission_device1 =
-      new MockUsbDevice(0xffff, 0x567b, "ACME", "Frobinator II", "MNOPQR");
-  scoped_refptr<UsbDevice> no_permission_device2 =
-      new MockUsbDevice(0xffff, 0x567c, "ACME", "Frobinator Xtreme", "STUVWX");
+  auto device1 = base::MakeRefCounted<FakeUsbDeviceInfo>(
+      0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
+  auto device2 = base::MakeRefCounted<FakeUsbDeviceInfo>(
+      0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
+  auto no_permission_device1 = base::MakeRefCounted<FakeUsbDeviceInfo>(
+      0xffff, 0x567b, "ACME", "Frobinator II", "MNOPQR");
+  auto no_permission_device2 = base::MakeRefCounted<FakeUsbDeviceInfo>(
+      0xffff, 0x567c, "ACME", "Frobinator Xtreme", "STUVWX");
 
-  auto device_info_0 = device::mojom::UsbDeviceInfo::From(*device0);
-  auto device_info_1 = device::mojom::UsbDeviceInfo::From(*device1);
-
-  device_client_.usb_service()->AddDevice(device0);
-  GetChooserContext()->GrantDevicePermission(origin, origin, *device_info_0);
-  device_client_.usb_service()->AddDevice(no_permission_device1);
+  auto device_info_1 = device_manager()->AddDevice(device1);
+  GetChooserContext()->GrantDevicePermission(origin, origin, *device_info_1);
+  device_manager()->AddDevice(no_permission_device1);
 
   WebUsbServicePtr web_usb_service;
   ConnectToService(mojo::MakeRequest(&web_usb_service));
@@ -153,22 +163,22 @@
     // Call GetDevices once to make sure the WebUsbService is up and running
     // and the client is set or else we could block forever waiting for calls.
     // The site has no permission to access |no_permission_device1|, so result
-    // of GetDevices() should only contain the |guid| of |device0|.
+    // of GetDevices() should only contain the |guid| of |device1|.
     std::set<std::string> guids;
-    guids.insert(device0->guid());
+    guids.insert(device1->guid());
     base::RunLoop loop;
     web_usb_service->GetDevices(
         base::BindOnce(&ExpectDevicesAndThen, guids, loop.QuitClosure()));
     loop.Run();
   }
 
-  device_client_.usb_service()->AddDevice(device1);
-  GetChooserContext()->GrantDevicePermission(origin, origin, *device_info_1);
-  device_client_.usb_service()->AddDevice(no_permission_device2);
-  device_client_.usb_service()->RemoveDevice(device0);
-  device_client_.usb_service()->RemoveDevice(device1);
-  device_client_.usb_service()->RemoveDevice(no_permission_device1);
-  device_client_.usb_service()->RemoveDevice(no_permission_device2);
+  auto device_info_2 = device_manager()->AddDevice(device2);
+  GetChooserContext()->GrantDevicePermission(origin, origin, *device_info_2);
+  device_manager()->AddDevice(no_permission_device2);
+  device_manager()->RemoveDevice(device1);
+  device_manager()->RemoveDevice(device2);
+  device_manager()->RemoveDevice(no_permission_device1);
+  device_manager()->RemoveDevice(no_permission_device2);
   {
     base::RunLoop loop;
     base::RepeatingClosure barrier =
@@ -176,15 +186,15 @@
     testing::InSequence s;
 
     EXPECT_CALL(mock_client, DoOnDeviceRemoved(_))
-        .WillOnce(ExpectGuidAndThen(device0->guid(), barrier))
-        .WillOnce(ExpectGuidAndThen(device1->guid(), barrier));
+        .WillOnce(ExpectGuidAndThen(device1->guid(), barrier))
+        .WillOnce(ExpectGuidAndThen(device2->guid(), barrier));
     loop.Run();
   }
 
-  device_client_.usb_service()->AddDevice(device0);
-  device_client_.usb_service()->AddDevice(device1);
-  device_client_.usb_service()->AddDevice(no_permission_device1);
-  device_client_.usb_service()->AddDevice(no_permission_device2);
+  device_manager()->AddDevice(device1);
+  device_manager()->AddDevice(device2);
+  device_manager()->AddDevice(no_permission_device1);
+  device_manager()->AddDevice(no_permission_device2);
   {
     base::RunLoop loop;
     base::RepeatingClosure barrier =
@@ -192,8 +202,8 @@
     testing::InSequence s;
 
     EXPECT_CALL(mock_client, DoOnDeviceAdded(_))
-        .WillOnce(ExpectGuidAndThen(device0->guid(), barrier))
-        .WillOnce(ExpectGuidAndThen(device1->guid(), barrier));
+        .WillOnce(ExpectGuidAndThen(device1->guid(), barrier))
+        .WillOnce(ExpectGuidAndThen(device2->guid(), barrier));
     loop.Run();
   }
 }
@@ -202,18 +212,14 @@
   GURL origin(kDefaultTestUrl);
 
   auto* context = GetChooserContext();
-  scoped_refptr<UsbDevice> device =
-      new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
-  scoped_refptr<UsbDevice> ephemeral_device =
-      new MockUsbDevice(0, 0, "ACME", "Frobinator II", "");
+  auto device = base::MakeRefCounted<FakeUsbDeviceInfo>(0x1234, 0x5678, "ACME",
+                                                        "Frobinator", "ABCDEF");
+  auto ephemeral_device = base::MakeRefCounted<FakeUsbDeviceInfo>(
+      0, 0, "ACME", "Frobinator II", "");
 
-  auto device_info = device::mojom::UsbDeviceInfo::From(*device);
-  auto ephemeral_device_info =
-      device::mojom::UsbDeviceInfo::From(*ephemeral_device);
-
-  device_client_.usb_service()->AddDevice(device);
+  auto device_info = device_manager()->AddDevice(device);
   context->GrantDevicePermission(origin, origin, *device_info);
-  device_client_.usb_service()->AddDevice(ephemeral_device);
+  auto ephemeral_device_info = device_manager()->AddDevice(ephemeral_device);
   context->GrantDevicePermission(origin, origin, *ephemeral_device_info);
 
   WebUsbServicePtr web_usb_service;
@@ -235,7 +241,7 @@
   EXPECT_TRUE(
       context->HasDevicePermission(origin, origin, *ephemeral_device_info));
 
-  context->DestroyDeviceManagerForTesting();
+  SimulateDeviceServiceCrash();
   EXPECT_CALL(mock_client, ConnectionError()).Times(1);
   base::RunLoop().RunUntilIdle();
 
@@ -245,11 +251,9 @@
 
   // Although a new device added, as the Device manager has been destroyed, no
   // event will be triggered.
-  scoped_refptr<UsbDevice> another_device =
-      new MockUsbDevice(0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
-  device_client_.usb_service()->AddDevice(another_device);
-  auto another_device_info =
-      device::mojom::UsbDeviceInfo::From(*another_device);
+  auto another_device = base::MakeRefCounted<FakeUsbDeviceInfo>(
+      0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
+  auto another_device_info = device_manager()->AddDevice(another_device);
 
   EXPECT_CALL(mock_client, DoOnDeviceAdded(_)).Times(0);
   base::RunLoop().RunUntilIdle();
@@ -257,7 +261,7 @@
   // Grant permission to the new device when service is off.
   context->GrantDevicePermission(origin, origin, *another_device_info);
 
-  device_client_.usb_service()->RemoveDevice(device);
+  device_manager()->RemoveDevice(device);
   EXPECT_CALL(mock_client, DoOnDeviceRemoved(_)).Times(0);
   base::RunLoop().RunUntilIdle();
 
diff --git a/chrome/browser/web_applications/components/pending_app_manager.cc b/chrome/browser/web_applications/components/pending_app_manager.cc
index debac0f..182bf9b8 100644
--- a/chrome/browser/web_applications/components/pending_app_manager.cc
+++ b/chrome/browser/web_applications/components/pending_app_manager.cc
@@ -16,20 +16,17 @@
 const bool PendingAppManager::AppInfo::kDefaultCreateShortcuts = true;
 const bool PendingAppManager::AppInfo::kDefaultOverridePreviousUserUninstall =
     false;
-const bool PendingAppManager::AppInfo::kDefaultBypassServiceWorkerCheck = false;
 
 PendingAppManager::AppInfo::AppInfo(GURL url,
                                     LaunchContainer launch_container,
                                     InstallSource install_source,
                                     bool create_shortcuts,
-                                    bool override_previous_user_uninstall,
-                                    bool bypass_service_worker_check)
+                                    bool override_previous_user_uninstall)
     : url(std::move(url)),
       launch_container(launch_container),
       install_source(install_source),
       create_shortcuts(create_shortcuts),
-      override_previous_user_uninstall(override_previous_user_uninstall),
-      bypass_service_worker_check(bypass_service_worker_check) {}
+      override_previous_user_uninstall(override_previous_user_uninstall) {}
 
 PendingAppManager::AppInfo::AppInfo(PendingAppManager::AppInfo&& other) =
     default;
@@ -38,9 +35,9 @@
 
 std::unique_ptr<PendingAppManager::AppInfo> PendingAppManager::AppInfo::Clone()
     const {
-  std::unique_ptr<AppInfo> other(new AppInfo(
-      url, launch_container, install_source, create_shortcuts,
-      override_previous_user_uninstall, bypass_service_worker_check));
+  std::unique_ptr<AppInfo> other(new AppInfo(url, launch_container,
+                                             install_source, create_shortcuts,
+                                             override_previous_user_uninstall));
   DCHECK_EQ(*this, *other);
   return other;
 }
@@ -48,12 +45,10 @@
 bool PendingAppManager::AppInfo::operator==(
     const PendingAppManager::AppInfo& other) const {
   return std::tie(url, launch_container, install_source, create_shortcuts,
-                  override_previous_user_uninstall,
-                  bypass_service_worker_check) ==
+                  override_previous_user_uninstall) ==
          std::tie(other.url, other.launch_container, other.install_source,
                   other.create_shortcuts,
-                  other.override_previous_user_uninstall,
-                  other.bypass_service_worker_check);
+                  other.override_previous_user_uninstall);
 }
 
 PendingAppManager::PendingAppManager() = default;
@@ -91,9 +86,7 @@
              << static_cast<int32_t>(app_info.install_source)
              << "\n create_shortcuts: " << app_info.create_shortcuts
              << "\n override_previous_user_uninstall: "
-             << app_info.override_previous_user_uninstall
-             << "\n bypass_service_worker_check: "
-             << app_info.bypass_service_worker_check;
+             << app_info.override_previous_user_uninstall;
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/pending_app_manager.h b/chrome/browser/web_applications/components/pending_app_manager.h
index 4edddf3..6e4c823 100644
--- a/chrome/browser/web_applications/components/pending_app_manager.h
+++ b/chrome/browser/web_applications/components/pending_app_manager.h
@@ -39,16 +39,13 @@
   struct AppInfo {
     static const bool kDefaultCreateShortcuts;
     static const bool kDefaultOverridePreviousUserUninstall;
-    static const bool kDefaultBypassServiceWorkerCheck;
 
-    AppInfo(
-        GURL url,
-        LaunchContainer launch_container,
-        InstallSource install_source,
-        bool create_shortcuts = kDefaultCreateShortcuts,
-        bool override_previous_user_uninstall =
-            kDefaultOverridePreviousUserUninstall,
-        bool bypass_service_worker_check = kDefaultBypassServiceWorkerCheck);
+    AppInfo(GURL url,
+            LaunchContainer launch_container,
+            InstallSource install_source,
+            bool create_shortcuts = kDefaultCreateShortcuts,
+            bool override_previous_user_uninstall =
+                kDefaultOverridePreviousUserUninstall);
     AppInfo(AppInfo&& other);
     ~AppInfo();
 
@@ -62,11 +59,6 @@
     const bool create_shortcuts;
     const bool override_previous_user_uninstall;
 
-    // This must only be used by pre-installed default apps that are valid PWAs
-    // if loading the real service worker is too costly to verify
-    // programmatically.
-    const bool bypass_service_worker_check;
-
    private:
     DISALLOW_COPY_AND_ASSIGN(AppInfo);
   };
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
index 9840c52..fe3c45e 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
@@ -136,9 +136,6 @@
   if (!app_info_.create_shortcuts)
     helper_->set_skip_shortcut_creation();
 
-  if (app_info_.bypass_service_worker_check)
-    helper_->set_bypass_service_worker_check();
-
   helper_->Create(base::Bind(&BookmarkAppInstallationTask::OnInstalled,
                              weak_ptr_factory_.GetWeakPtr(),
                              base::Passed(&result_callback)));
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
index 6b6c593..c8b1cc0 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
@@ -9,7 +9,6 @@
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
-#include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/web_applications/components/install_result_code.h"
@@ -23,40 +22,33 @@
 
 namespace extensions {
 
-class PendingBookmarkAppManagerBrowserTest : public InProcessBrowserTest {
- protected:
-  void InstallApp(const GURL& url, bool bypass_service_worker_check = false) {
-    base::RunLoop run_loop;
-    web_app::WebAppProvider::Get(browser()->profile())
-        ->pending_app_manager()
-        .Install(web_app::PendingAppManager::AppInfo(
-                     url, web_app::LaunchContainer::kWindow,
-                     web_app::InstallSource::kInternal,
-                     false /* create_shortcuts */,  // Avoid creating real
-                                                    // shortcuts in tests.
-                     web_app::PendingAppManager::AppInfo::
-                         kDefaultOverridePreviousUserUninstall,
-                     bypass_service_worker_check),
-                 base::BindLambdaForTesting(
-                     [this, &run_loop](const GURL& provided_url,
-                                       web_app::InstallResultCode code) {
-                       result_code_ = code;
-                       run_loop.QuitClosure().Run();
-                     }));
-    run_loop.Run();
-    ASSERT_TRUE(result_code_.has_value());
-  }
-
-  base::Optional<web_app::InstallResultCode> result_code_;
-};
+class PendingBookmarkAppManagerBrowserTest : public InProcessBrowserTest {};
 
 // Basic integration test to make sure the whole flow works. Each step in the
 // flow is unit tested separately.
 IN_PROC_BROWSER_TEST_F(PendingBookmarkAppManagerBrowserTest, InstallSucceeds) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url(embedded_test_server()->GetURL("/banners/manifest_test_page.html"));
-  InstallApp(url);
-  EXPECT_EQ(web_app::InstallResultCode::kSuccess, result_code_.value());
+  base::RunLoop run_loop;
+  base::Optional<web_app::InstallResultCode> result_code;
+
+  web_app::WebAppProvider::Get(browser()->profile())
+      ->pending_app_manager()
+      .Install(web_app::PendingAppManager::AppInfo(
+                   url, web_app::LaunchContainer::kWindow,
+                   web_app::InstallSource::kInternal,
+                   false /* create_shortcuts */),  // Avoid creating real
+                                                   // shortcuts in tests.
+               base::BindLambdaForTesting(
+                   [&run_loop, &result_code](const GURL& provided_url,
+                                             web_app::InstallResultCode code) {
+                     result_code = code;
+                     run_loop.QuitClosure().Run();
+                   }));
+  run_loop.Run();
+
+  ASSERT_TRUE(result_code.has_value());
+  EXPECT_EQ(web_app::InstallResultCode::kSuccess, result_code.value());
   base::Optional<std::string> id =
       web_app::ExtensionIdsMap(browser()->profile()->GetPrefs())
           .LookupExtensionId(url);
@@ -90,27 +82,4 @@
   // installation.
 }
 
-IN_PROC_BROWSER_TEST_F(PendingBookmarkAppManagerBrowserTest,
-                       BypassServiceWorkerCheck) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url(embedded_test_server()->GetURL(
-      "/banners/manifest_no_service_worker.html"));
-  InstallApp(url, true /* bypass_service_worker_check */);
-  const extensions::Extension* app =
-      extensions::util::GetInstalledPwaForUrl(browser()->profile(), url);
-  EXPECT_TRUE(app);
-  EXPECT_EQ("Manifest test app", app->name());
-}
-
-IN_PROC_BROWSER_TEST_F(PendingBookmarkAppManagerBrowserTest,
-                       PerformServiceWorkerCheck) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url(embedded_test_server()->GetURL(
-      "/banners/manifest_no_service_worker.html"));
-  InstallApp(url, false /* bypass_service_worker_check */);
-  const extensions::Extension* app =
-      extensions::util::GetInstalledPwaForUrl(browser()->profile(), url);
-  EXPECT_FALSE(app);
-}
-
 }  // namespace extensions
diff --git a/chrome/chrome_cleaner/chrome_utils/extensions_util.cc b/chrome/chrome_cleaner/chrome_utils/extensions_util.cc
index c2828733..ac79c873 100644
--- a/chrome/chrome_cleaner/chrome_utils/extensions_util.cc
+++ b/chrome/chrome_cleaner/chrome_utils/extensions_util.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <array>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 
@@ -16,6 +17,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/optional.h"
+#include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
@@ -43,7 +45,8 @@
   }
 
   void Increment() {
-    DCHECK(count_ > 0) << "Once decremented to zero, Increment should never be called.";
+    DCHECK(count_ > 0)
+        << "Once decremented to zero, Increment should never be called.";
     count_++;
   }
 
diff --git a/chrome/chrome_cleaner/crash/crashpad_crash_client.cc b/chrome/chrome_cleaner/crash/crashpad_crash_client.cc
index 58658f9..189df2b 100644
--- a/chrome/chrome_cleaner/crash/crashpad_crash_client.cc
+++ b/chrome/chrome_cleaner/crash/crashpad_crash_client.cc
@@ -8,6 +8,7 @@
 #include <psapi.h>
 #include <stdio.h>
 
+#include <algorithm>
 #include <string>
 #include <vector>
 
diff --git a/chrome/chrome_cleaner/interfaces/zip_archiver.mojom b/chrome/chrome_cleaner/interfaces/zip_archiver.mojom
index dbe5f67..ee53bbc 100644
--- a/chrome/chrome_cleaner/interfaces/zip_archiver.mojom
+++ b/chrome/chrome_cleaner/interfaces/zip_archiver.mojom
@@ -15,6 +15,8 @@
   kErrorCannotCreateZipFile = 5,
   kZipFileExists = 6,
   kIgnoredSourceFile = 7,
+  kErrorNotEnoughDiskSpace = 8,
+  kErrorSourceFileTooBig = 9,
 };
 
 interface ZipArchiver {
diff --git a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.cc b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.cc
index d0cd063..7349a40 100644
--- a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.cc
+++ b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.cc
@@ -9,7 +9,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
-#include "base/command_line.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
@@ -65,16 +64,38 @@
                          base::Unretained(this), std::move(callback))));
 }
 
+void ChromePromptIPC::PostDisableExtensionsTask(
+    const std::vector<base::string16>& extension_ids,
+    mojom::ChromePrompt::DisableExtensionsCallback callback) {
+  DCHECK(task_runner_);
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &ChromePromptIPC::RunDisableExtensionsTask, base::Unretained(this),
+          extension_ids,
+          base::BindOnce(&ChromePromptIPC::OnChromeResponseReceivedExtensions,
+                         base::Unretained(this), std::move(callback))));
+}
+
 void ChromePromptIPC::OnChromeResponseReceived(
     mojom::ChromePrompt::PromptUserCallback callback,
     mojom::PromptAcceptance prompt_acceptance) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(State::kWaitingForResponseFromChrome, state_);
 
-  state_ = State::kDone;
+  state_ = State::kDoneInteraction;
   std::move(callback).Run(prompt_acceptance);
 }
 
+void ChromePromptIPC::OnChromeResponseReceivedExtensions(
+    mojom::ChromePrompt::DisableExtensionsCallback callback,
+    bool extensions_disabled_callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_EQ(State::kDoneInteraction, state_);
+
+  std::move(callback).Run(extensions_disabled_callback);
+}
+
 void ChromePromptIPC::OnConnectionError() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_NE(State::kUninitialized, state_);
@@ -82,10 +103,10 @@
   if (!error_handler_)
     return;
 
-  if (state_ == State::kDone) {
+  if (state_ == State::kDoneInteraction) {
     error_handler_->OnConnectionClosedAfterDone();
   } else {
-    state_ = State::kDone;
+    state_ = State::kDoneInteraction;
     error_handler_->OnConnectionClosed();
   }
 }
@@ -125,7 +146,7 @@
   // This is a corner case, in which we receive the disconnect message on the
   // IPC thread right before this task is posted. In that case, this function
   // will be a no-op.
-  if (state_ == State::kDone)
+  if (state_ == State::kDoneInteraction)
     return;
 
   state_ = State::kWaitingForResponseFromChrome;
@@ -135,4 +156,15 @@
                    base::nullopt, std::move(callback));
 }
 
+void ChromePromptIPC::RunDisableExtensionsTask(
+    const std::vector<base::string16>& extension_ids,
+    mojom::ChromePrompt::DisableExtensionsCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(chrome_prompt_service_);
+  DCHECK(state_ == State::kDoneInteraction);
+
+  (*chrome_prompt_service_)
+      ->DisableExtensions(std::move(extension_ids), std::move(callback));
+}
+
 }  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h
index 7b1e3bf..0824161 100644
--- a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h
+++ b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h
@@ -79,6 +79,12 @@
       const std::vector<base::string16>& registry_keys,
       mojom::ChromePrompt::PromptUserCallback callback);
 
+  // Posts a PromptDisableExtensions() task to the IPC controller's thread.
+  // Internal state must be State::kDoneInteraction when the posted task runs.
+  virtual void PostDisableExtensionsTask(
+      const std::vector<base::string16>& extension_ids,
+      mojom::ChromePrompt::DisableExtensionsCallback callback);
+
  protected:
   // The destructor is only called by tests for doubles of this class. In the
   // cleaner, this object leaks, so we don't bother closing the connection
@@ -93,9 +99,9 @@
     kWaitingForScanResults,
     // Scan results sent to Chrome, waiting for the user's response.
     kWaitingForResponseFromChrome,
-    // Response from Chrome received. In this state, the IPC will no longer be
-    // used.
-    kDone,
+    // Response from Chrome received. In this state, there will be no further
+    // user interaction.
+    kDoneInteraction,
   };
 
   // Initializes |chrome_prompt_service_| and sets the connection error
@@ -109,13 +115,23 @@
       const std::vector<base::string16>& registry_keys,
       mojom::ChromePrompt::PromptUserCallback callback);
 
+  virtual void RunDisableExtensionsTask(
+      const std::vector<base::string16>& extension_ids,
+      mojom::ChromePrompt::DisableExtensionsCallback callback);
+
   // Callback for ChromePrompt::PromptUser, internal state must be
   // State::kWaitingForResponseFromChrome. Invokes callback(prompt_acceptance)
-  // and transitions to state State::kDone.
+  // and transitions to state State::kDoneInteraction.
   void OnChromeResponseReceived(
       mojom::ChromePrompt::PromptUserCallback callback,
       mojom::PromptAcceptance prompt_acceptance);
 
+  // Callback for ChromePrompt::DisableExtensions, internal state must be
+  // State::kDoneInteraction. Invokes callback(extensions_deleted_callback).
+  void OnChromeResponseReceivedExtensions(
+      mojom::ChromePrompt::DisableExtensionsCallback callback,
+      bool extensions_deleted_callback);
+
   // Connection error handler. Invokes either
   // error_handler_->OnConnectionClosed() or
   // error_handler_->OnConnectionClosedAfterDone(), depending on the internal
diff --git a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc
index 756d755..0e22ee21 100644
--- a/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc
+++ b/chrome/chrome_cleaner/ipc/chrome_prompt_ipc_unittest.cc
@@ -31,6 +31,7 @@
 using testing::Bool;
 using testing::Values;
 
+constexpr char kIncludeUwESwitch[] = "include-uwe";
 constexpr char kIncludeUwSSwitch[] = "include-uws";
 constexpr char kIncludeRegistryKeysSwitch[] = "include-registry-keys";
 constexpr char kExpectedPromptResultSwitch[] = "expected-prompt-result";
@@ -39,6 +40,7 @@
 
 const base::FilePath kBadFilePath(L"/path/to/bad.dll");
 const base::string16 kBadRegistryKey(L"HKCU:32\\Software\\ugly-uws\\nasty");
+const base::string16 kExtensionId(L"expected-extension-id");
 
 // Possible moments when the parent process can disconnect from the IPC to
 // check connection error handling in the child process.
@@ -78,6 +80,7 @@
 
 struct TestConfig {
   bool uws_expected;
+  bool uwe_expected;
   bool with_registry_keys;
   mojom::PromptAcceptance expected_prompt_acceptance;
   ParentDisconnected expected_parent_disconnected;
@@ -107,12 +110,22 @@
     }
     CloseConnectionIf(ParentDisconnected::kWhileProcessingChildRequest);
     std::move(callback).Run(test_config_.expected_prompt_acceptance);
-    CloseConnectionIf(ParentDisconnected::kOnDone);
+    if (!test_config_.uwe_expected) {
+      CloseConnectionIf(ParentDisconnected::kOnDone);
+    }
   }
 
-  void DisableExtensions(
-      const std::vector<base::string16>& extension_ids,
-      ChromePrompt::DisableExtensionsCallback callback) override {}
+  void DisableExtensions(const std::vector<base::string16>& extension_ids,
+                         DisableExtensionsCallback callback) override {
+    EXPECT_NE(test_config_.uwe_expected, extension_ids.empty());
+    if (test_config_.uwe_expected) {
+      EXPECT_EQ(kExtensionId, extension_ids.front());
+    } else {
+      EXPECT_EQ(0UL, extension_ids.size());
+    }
+    std::move(callback).Run(true);
+    CloseConnectionIf(ParentDisconnected::kOnDone);
+  }
 
   // Close the IPC connection on the parent process depending on the value of
   // |parent_disconnected|.
@@ -132,6 +145,9 @@
       : ParentProcess(std::move(mojo_task_runner)), test_config_(test_config) {
     if (test_config.uws_expected)
       AppendSwitch(kIncludeUwSSwitch);
+    if (test_config.uwe_expected) {
+      AppendSwitch(kIncludeUwESwitch);
+    }
     if (test_config.with_registry_keys)
       AppendSwitch(kIncludeRegistryKeysSwitch);
     AppendSwitch(kExpectedPromptResultSwitch,
@@ -187,6 +203,23 @@
       scoped_refptr<MojoTaskRunner> mojo_task_runner)
       : ChildProcess(std::move(mojo_task_runner)) {}
 
+  void SendUwEDataToParentProcess(ChromePromptIPC* chrome_prompt_ipc,
+                                  base::OnceClosure done) {
+    CHECK(chrome_prompt_ipc);
+    std::vector<base::string16> extensions;
+    if (uwe_expected()) {
+      extensions.push_back(kExtensionId);
+    } else {
+      std::move(done).Run();
+      return;
+    }
+    chrome_prompt_ipc->PostDisableExtensionsTask(
+        std::move(extensions),
+        base::BindOnce(
+            &ChromePromptIPCChildProcess::ReceiveDisableExtensionsResult,
+            base::Unretained(this), base::Passed(&done)));
+  }
+
   void SendUwSDataToParentProcess(ChromePromptIPC* chrome_prompt_ipc,
                                   base::OnceClosure done) {
     CHECK(chrome_prompt_ipc);
@@ -223,10 +256,19 @@
     std::move(done).Run();
   }
 
+  void ReceiveDisableExtensionsResult(base::OnceClosure done, bool completed) {
+    CHECK(completed);
+    std::move(done).Run();
+  }
+
   bool uws_expected() const {
     return command_line().HasSwitch(kIncludeUwSSwitch);
   }
 
+  bool uwe_expected() const {
+    return command_line().HasSwitch(kIncludeUwESwitch);
+  }
+
   bool with_registry_keys() const {
     return uws_expected() &&
            command_line().HasSwitch(kIncludeRegistryKeysSwitch);
@@ -278,10 +320,14 @@
   // After the response from the parent process is received, this will post a
   // task to unblock the child process's main thread. Not blocking the main
   // thread can lead to race condition on exit.
-  base::RunLoop run_loop;
+  base::RunLoop prompt_user_run_loop;
+  base::RunLoop extension_run_loop;
   child_process->SendUwSDataToParentProcess(chrome_prompt_ipc,
-                                            run_loop.QuitClosure());
-  run_loop.Run();
+                                            prompt_user_run_loop.QuitClosure());
+  prompt_user_run_loop.Run();
+  child_process->SendUwEDataToParentProcess(chrome_prompt_ipc,
+                                            extension_run_loop.QuitClosure());
+  extension_run_loop.Run();
 
   if (child_process->expected_parent_disconnected() ==
       ParentDisconnected::kOnDone) {
@@ -295,8 +341,11 @@
 }
 
 class ChromePromptIPCTest
-    : public ::testing::TestWithParam<
-          std::tuple<bool, bool, mojom::PromptAcceptance, ParentDisconnected>> {
+    : public ::testing::TestWithParam<std::tuple<bool,
+                                                 bool,
+                                                 bool,
+                                                 mojom::PromptAcceptance,
+                                                 ParentDisconnected>> {
  public:
   void SetUp() override { mojo_task_runner_ = MojoTaskRunner::Create(); }
 
@@ -306,7 +355,8 @@
 
 TEST_P(ChromePromptIPCTest, Communication) {
   TestConfig test_config;
-  std::tie(test_config.uws_expected, test_config.with_registry_keys,
+  std::tie(test_config.uws_expected, test_config.uwe_expected,
+           test_config.with_registry_keys,
            test_config.expected_prompt_acceptance,
            test_config.expected_parent_disconnected) = GetParam();
   if (test_config.with_registry_keys)
@@ -332,6 +382,7 @@
                         ChromePromptIPCTest,
                         testing::Combine(
                             /*uws_expected=*/Values(false),
+                            /*uwe_expected=*/Values(false),
                             /*with_registry_keys=*/Values(false),
                             Values(mojom::PromptAcceptance::DENIED),
                             Values(ParentDisconnected::kNone,
@@ -343,6 +394,7 @@
     ChromePromptIPCTest,
     testing::Combine(
         /*uws_expected=*/Values(true),
+        /*uwe_expected=*/Bool(),
         /*with_registry_keys=*/Bool(),
         Values(mojom::PromptAcceptance::ACCEPTED_WITH_LOGS,
                mojom::PromptAcceptance::ACCEPTED_WITHOUT_LOGS,
diff --git a/chrome/chrome_cleaner/ipc/sandbox.cc b/chrome/chrome_cleaner/ipc/sandbox.cc
index 5423ab0..50073bc 100644
--- a/chrome/chrome_cleaner/ipc/sandbox.cc
+++ b/chrome/chrome_cleaner/ipc/sandbox.cc
@@ -7,7 +7,9 @@
 #include <windows.h>
 
 #include <iterator>
+#include <memory>
 #include <utility>
+#include <vector>
 
 #include "base/base_switches.h"
 #include "base/bind.h"
@@ -58,12 +60,11 @@
   sandbox_result = policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
   CHECK_EQ(sandbox::SBOX_ALL_OK, sandbox_result);
 
-  // Chromium ignores failures on this function but logs a warning. Do the same
-  // here.
+  // TODO(crbug.com/893740): Call SetAlternateDesktop. Chromium ignores
+  // failures on this function but logs a warning, so we should do the same.
   // https://chromium.googlesource.com/chromium/src/+/b6a4ff86c730756a73d63cc882ef818fb7818a53/content/common/sandbox_win.cc#420
-  sandbox::ResultCode result = policy->SetAlternateDesktop(true);
-  LOG_IF(WARNING, result != sandbox::SBOX_ALL_OK)
-      << "Failed to apply desktop security";
+  // Currently we're not using SetAlternateDesktop because it has static
+  // internal state that causes DCHECK's in unit tests if called more than once.
 
   sandbox_result =
       policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
@@ -394,4 +395,23 @@
   return hooks->TargetDroppedPrivileges(command_line);
 }
 
+ResultCode GetResultCodeForSandboxConnectionError(SandboxType sandbox_type) {
+  ResultCode result_code = RESULT_CODE_INVALID;
+  switch (sandbox_type) {
+    case SandboxType::kEset:
+      result_code = RESULT_CODE_ESET_SANDBOX_DISCONNECTED_TOO_SOON;
+      break;
+    case SandboxType::kJsonParser:
+      result_code = RESULT_CODE_JSON_PARSER_SANDBOX_DISCONNECTED_TOO_SOON;
+      break;
+    case SandboxType::kZipArchiver:
+      result_code = RESULT_CODE_ZIP_ARCHIVER_SANDBOX_DISCONNECTED_TOO_SOON;
+      break;
+    default:
+      NOTREACHED() << "No result code for unknown sandbox type "
+                   << static_cast<int>(sandbox_type);
+  }
+  return result_code;
+}
+
 }  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/ipc/sandbox.h b/chrome/chrome_cleaner/ipc/sandbox.h
index f8982a8..1b4ae9e 100644
--- a/chrome/chrome_cleaner/ipc/sandbox.h
+++ b/chrome/chrome_cleaner/ipc/sandbox.h
@@ -21,6 +21,9 @@
 
 namespace chrome_cleaner {
 
+using SandboxConnectionErrorCallback =
+    base::RepeatingCallback<void(SandboxType)>;
+
 // The suffix to append to log files for sandboxed processes.
 extern const wchar_t kSandboxLogFileSuffix[];
 
@@ -125,6 +128,8 @@
 // if the target processes have already exited.
 std::map<SandboxType, SystemResourceUsage> GetSandboxSystemResourceUsage();
 
+ResultCode GetResultCodeForSandboxConnectionError(SandboxType sandbox_type);
+
 }  // namespace chrome_cleaner
 
 #endif  // CHROME_CHROME_CLEANER_IPC_SANDBOX_H_
diff --git a/chrome/chrome_cleaner/json_parser/BUILD.gn b/chrome/chrome_cleaner/json_parser/BUILD.gn
index f774820..eb75e9f 100644
--- a/chrome/chrome_cleaner/json_parser/BUILD.gn
+++ b/chrome/chrome_cleaner/json_parser/BUILD.gn
@@ -2,6 +2,17 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+static_library("json_splicer") {
+  sources = [
+    "json_splicer.cc",
+    "json_splicer.h",
+  ]
+
+  deps = [
+    "//base:base",
+  ]
+}
+
 static_library("json_parser") {
   sources = [
     "json_parser_api.h",
@@ -24,6 +35,7 @@
     "//chrome/chrome_cleaner/ipc:mojo_task_runner",
     "//chrome/chrome_cleaner/ipc:sandbox",
     "//chrome/chrome_cleaner/os:common_os",
+    "//chrome/chrome_cleaner/settings:settings_types",
     "//components/chrome_cleaner/public/constants",
     "//mojo/public/cpp/bindings",
   ]
@@ -34,11 +46,13 @@
 
   sources = [
     "json_parser_impl_unittest.cc",
+    "json_splicer_unittest.cc",
     "sandbox_setup_unittest.cc",
   ]
 
   deps = [
     ":json_parser",
+    ":json_splicer",
     "//base:base",
     "//base/test:test_support",
     "//chrome/chrome_cleaner/interfaces:json_parser_interface",
diff --git a/chrome/chrome_cleaner/json_parser/DEPS b/chrome/chrome_cleaner/json_parser/DEPS
new file mode 100644
index 0000000..ef8ad28
--- /dev/null
+++ b/chrome/chrome_cleaner/json_parser/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+mojo/public",
+]
diff --git a/chrome/chrome_cleaner/json_parser/json_splicer.cc b/chrome/chrome_cleaner/json_parser/json_splicer.cc
new file mode 100644
index 0000000..3bdbf6b
--- /dev/null
+++ b/chrome/chrome_cleaner/json_parser/json_splicer.cc
@@ -0,0 +1,48 @@
+// Copyright 2018 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 "chrome/chrome_cleaner/json_parser/json_splicer.h"
+
+#include "base/values.h"
+
+namespace chrome_cleaner {
+
+JsonSplicer::~JsonSplicer() = default;
+
+bool JsonSplicer::RemoveKeyFromDictionary(base::Value* dictionary,
+                                          const std::string& key) {
+  bool result = false;
+  base::DictionaryValue* entries = nullptr;
+  if (dictionary == nullptr || !dictionary->is_dict() ||
+      !dictionary->GetAsDictionary(&entries)) {
+    LOG(ERROR) << "Got a "
+               << (dictionary ? dictionary->GetTypeName(dictionary->type())
+                              : "NULL")
+               << " but expected a dictionary.";
+    return result;
+  }
+  if (!(result = entries->RemoveKey(key))) {
+    LOG(ERROR) << key << " was not found in the dictionary";
+  }
+  return result;
+}
+
+bool JsonSplicer::RemoveValueFromList(base::Value* list,
+                                      const std::string& key) {
+  if (list == nullptr || !list->is_list()) {
+    LOG(ERROR) << "Got a " << (list ? list->GetTypeName(list->type()) : "NULL")
+               << " but expected a list.";
+    return false;
+  }
+  std::vector<base::Value>& entries = list->GetList();
+  auto iter = std::remove(entries.begin(), entries.end(), base::Value(key));
+  if (iter == entries.end()) {
+    LOG(ERROR) << key << " was not found in the list";
+    return false;
+  }
+  entries.erase(iter);
+  return true;
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/json_parser/json_splicer.h b/chrome/chrome_cleaner/json_parser/json_splicer.h
new file mode 100644
index 0000000..b5df59d
--- /dev/null
+++ b/chrome/chrome_cleaner/json_parser/json_splicer.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_CHROME_CLEANER_JSON_PARSER_JSON_SPLICER_H_
+#define CHROME_CHROME_CLEANER_JSON_PARSER_JSON_SPLICER_H_
+
+#include "base/values.h"
+
+namespace chrome_cleaner {
+
+class JsonSplicer {
+ public:
+  ~JsonSplicer();
+
+  // Deletes the |key| entry from the |dictionary|.
+  //
+  // Returns true on success.
+  bool RemoveKeyFromDictionary(base::Value* dictionary, const std::string& key);
+
+  // Deletes the entry from the |list| with |key|.
+  //
+  // Returns true on success.
+  bool RemoveValueFromList(base::Value* list, const std::string& key);
+};
+
+}  // namespace chrome_cleaner
+
+#endif  // CHROME_CHROME_CLEANER_JSON_PARSER_JSON_SPLICER_H_
diff --git a/chrome/chrome_cleaner/json_parser/json_splicer_unittest.cc b/chrome/chrome_cleaner/json_parser/json_splicer_unittest.cc
new file mode 100644
index 0000000..069cf7f
--- /dev/null
+++ b/chrome/chrome_cleaner/json_parser/json_splicer_unittest.cc
@@ -0,0 +1,199 @@
+// Copyright 2018 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 "chrome/chrome_cleaner/json_parser/json_splicer.h"
+
+#include "base/bind.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/test_timeouts.h"
+#include "base/values.h"
+#include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h"
+#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h"
+#include "chrome/chrome_cleaner/json_parser/json_parser_impl.h"
+#include "chrome/chrome_cleaner/json_parser/sandboxed_json_parser.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chrome_cleaner {
+
+namespace {
+
+const char kDaysOfWeekDict[] =
+    R"(
+    { "sunday": 1,
+      "monday": 2,
+      "tuesday": 3,
+      "wednesday": 4,
+      "thursday": 5,
+      "friday": 6,
+      "saturday": 7
+    })";
+const char kDaysOfWeekList[] =
+    R"(
+    [
+    "sunday", "monday", "tuesday", "wednesday",
+    "thursday", "friday", "saturday"
+    ])";
+
+bool IsDaysOfWeek(const base::DictionaryValue* dictionary) {
+  return dictionary->HasKey("sunday") && dictionary->HasKey("monday") &&
+         dictionary->HasKey("tuesday") && dictionary->HasKey("wednesday") &&
+         dictionary->HasKey("thursday") && dictionary->HasKey("friday") &&
+         dictionary->HasKey("saturday");
+}
+
+bool IsDaysOfWeek(const std::vector<base::Value>& list) {
+  return base::ContainsValue(list, base::Value("sunday")) &&
+         base::ContainsValue(list, base::Value("monday")) &&
+         base::ContainsValue(list, base::Value("tuesday")) &&
+         base::ContainsValue(list, base::Value("wednesday")) &&
+         base::ContainsValue(list, base::Value("thursday")) &&
+         base::ContainsValue(list, base::Value("friday")) &&
+         base::ContainsValue(list, base::Value("saturday"));
+}
+
+class JsonSplicerImplTest : public testing::Test {
+ public:
+  JsonSplicerImplTest()
+      : task_runner_(MojoTaskRunner::Create()),
+        json_parser_ptr_(new mojom::JsonParserPtr(),
+                         base::OnTaskRunnerDeleter(task_runner_)),
+        json_parser_impl_(nullptr, base::OnTaskRunnerDeleter(task_runner_)),
+        sandboxed_json_parser_(task_runner_.get(), json_parser_ptr_.get()) {
+    task_runner_->PostTask(
+        FROM_HERE,
+        BindOnce(BindParser, json_parser_ptr_.get(), &json_parser_impl_));
+  }
+
+ protected:
+  static void BindParser(
+      mojom::JsonParserPtr* json_parser,
+      std::unique_ptr<JsonParserImpl, base::OnTaskRunnerDeleter>*
+          json_parser_impl) {
+    json_parser_impl->reset(
+        new JsonParserImpl(mojo::MakeRequest(json_parser), base::DoNothing()));
+  }
+
+  scoped_refptr<MojoTaskRunner> task_runner_;
+  std::unique_ptr<mojom::JsonParserPtr, base::OnTaskRunnerDeleter>
+      json_parser_ptr_;
+  std::unique_ptr<JsonParserImpl, base::OnTaskRunnerDeleter> json_parser_impl_;
+  SandboxedJsonParser sandboxed_json_parser_;
+};
+
+}  // namespace
+
+TEST_F(JsonSplicerImplTest, FailedJsonDictSplice) {
+  base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+                           base::WaitableEvent::InitialState::NOT_SIGNALED);
+  sandboxed_json_parser_.Parse(
+      kDaysOfWeekDict,
+      base::BindOnce(
+          [](base::WaitableEvent* done, base::Optional<base::Value> value,
+             const base::Optional<std::string>& error) {
+            JsonSplicer splicer;
+            ASSERT_FALSE(error.has_value());
+            ASSERT_TRUE(value.has_value());
+            base::DictionaryValue* dict;
+            ASSERT_TRUE(value->GetAsDictionary(&dict));
+            ASSERT_TRUE(IsDaysOfWeek(dict));
+            std::string blank = "";
+            ASSERT_FALSE(splicer.RemoveKeyFromDictionary(dict, blank));
+            ASSERT_TRUE(IsDaysOfWeek(dict));
+            std::string random = "aoeu";
+            ASSERT_FALSE(splicer.RemoveKeyFromDictionary(dict, random));
+            ASSERT_TRUE(IsDaysOfWeek(dict));
+            done->Signal();
+          },
+          &done));
+  EXPECT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
+}
+
+TEST_F(JsonSplicerImplTest, JsonDictSplice) {
+  base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+                           base::WaitableEvent::InitialState::NOT_SIGNALED);
+  sandboxed_json_parser_.Parse(
+      kDaysOfWeekDict,
+      base::BindOnce(
+          [](base::WaitableEvent* done, base::Optional<base::Value> value,
+             const base::Optional<std::string>& error) {
+            JsonSplicer splicer;
+            ASSERT_FALSE(error.has_value());
+            ASSERT_TRUE(value.has_value());
+            base::DictionaryValue* dict;
+            ASSERT_TRUE(value->GetAsDictionary(&dict));
+            ASSERT_TRUE(IsDaysOfWeek(dict));
+
+            std::string monday = "monday";
+            ASSERT_TRUE(dict->HasKey(monday));
+            ASSERT_TRUE(splicer.RemoveKeyFromDictionary(dict, monday));
+            ASSERT_FALSE(IsDaysOfWeek(dict));
+            ASSERT_FALSE(dict->HasKey(monday));
+
+            std::string wednesday = "wednesday";
+            ASSERT_TRUE(dict->HasKey(wednesday));
+            ASSERT_TRUE(splicer.RemoveKeyFromDictionary(dict, wednesday));
+            ASSERT_FALSE(IsDaysOfWeek(dict));
+            ASSERT_FALSE(dict->HasKey(wednesday));
+            done->Signal();
+          },
+          &done));
+  EXPECT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
+}
+
+TEST_F(JsonSplicerImplTest, FailedJsonListSplice) {
+  base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+                           base::WaitableEvent::InitialState::NOT_SIGNALED);
+  sandboxed_json_parser_.Parse(
+      kDaysOfWeekList,
+      base::BindOnce(
+          [](base::WaitableEvent* done, base::Optional<base::Value> value,
+             const base::Optional<std::string>& error) {
+            JsonSplicer splicer;
+            ASSERT_FALSE(error.has_value());
+            ASSERT_TRUE(value.has_value());
+            std::vector<base::Value>& list = value->GetList();
+            ASSERT_TRUE(IsDaysOfWeek(list));
+            std::string blank = "";
+            ASSERT_FALSE(splicer.RemoveValueFromList(&*value, blank));
+            ASSERT_TRUE(IsDaysOfWeek(list));
+            std::string random = "aoeu";
+            ASSERT_FALSE(splicer.RemoveValueFromList(&*value, random));
+            ASSERT_TRUE(IsDaysOfWeek(list));
+            done->Signal();
+          },
+          &done));
+  EXPECT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
+}
+
+TEST_F(JsonSplicerImplTest, JsonListSplice) {
+  base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
+                           base::WaitableEvent::InitialState::NOT_SIGNALED);
+  sandboxed_json_parser_.Parse(
+      kDaysOfWeekList,
+      base::BindOnce(
+          [](base::WaitableEvent* done, base::Optional<base::Value> value,
+             const base::Optional<std::string>& error) {
+            JsonSplicer splicer;
+            ASSERT_FALSE(error.has_value());
+            ASSERT_TRUE(value.has_value());
+            std::vector<base::Value>& list = value->GetList();
+            ASSERT_TRUE(IsDaysOfWeek(list));
+            std::string monday = "monday";
+            ASSERT_TRUE(splicer.RemoveValueFromList(&*value, monday));
+            ASSERT_FALSE(IsDaysOfWeek(list));
+            ASSERT_FALSE(std::find(list.begin(), list.end(),
+                                   base::Value(monday)) != list.end());
+            std::string wednesday = "wednesday";
+            ASSERT_TRUE(splicer.RemoveValueFromList(&*value, wednesday));
+            ASSERT_FALSE(IsDaysOfWeek(list));
+            ASSERT_FALSE(std::find(list.begin(), list.end(),
+                                   base::Value(monday)) != list.end());
+            done->Signal();
+          },
+          &done));
+  EXPECT_TRUE(done.TimedWait(TestTimeouts::action_timeout()));
+}
+
+}  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.cc b/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.cc
index 237256f7..45e3098 100644
--- a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.cc
+++ b/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
+#include "chrome/chrome_cleaner/settings/settings_types.h"
 
 namespace chrome_cleaner {
 
@@ -48,10 +49,13 @@
 
 ResultCode SpawnJsonParserSandbox(
     scoped_refptr<MojoTaskRunner> mojo_task_runner,
-    base::OnceClosure connection_error_handler,
+    const SandboxConnectionErrorCallback& connection_error_callback,
     UniqueJsonParserPtr* json_parser_ptr) {
+  // Call |connection_error_callback| with json parser sandbox type.
+  auto error_handler =
+      base::BindOnce(connection_error_callback, SandboxType::kJsonParser);
   JsonParserSandboxSetupHooks setup_hooks(mojo_task_runner,
-                                          std::move(connection_error_handler));
+                                          std::move(error_handler));
   ResultCode result_code = SpawnSandbox(&setup_hooks, SandboxType::kJsonParser);
   *json_parser_ptr = setup_hooks.TakeJsonParserPtr();
 
diff --git a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h b/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h
index 9348f13..66e99442 100644
--- a/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h
+++ b/chrome/chrome_cleaner/json_parser/sandbox_setup_hooks.h
@@ -11,6 +11,7 @@
 #include "chrome/chrome_cleaner/interfaces/json_parser.mojom.h"
 #include "chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h"
 #include "chrome/chrome_cleaner/ipc/mojo_task_runner.h"
+#include "chrome/chrome_cleaner/ipc/sandbox.h"
 #include "components/chrome_cleaner/public/constants/result_codes.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 
@@ -50,7 +51,7 @@
 // |json_parser_ptr|.
 ResultCode SpawnJsonParserSandbox(
     scoped_refptr<MojoTaskRunner> mojo_task_runner,
-    base::OnceClosure connection_error_handler,
+    const SandboxConnectionErrorCallback& connection_error_callback,
     UniqueJsonParserPtr* json_parser_ptr);
 
 }  // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/logging/cleaner_logging_service.h b/chrome/chrome_cleaner/logging/cleaner_logging_service.h
index 80fce80..b0149970 100644
--- a/chrome/chrome_cleaner/logging/cleaner_logging_service.h
+++ b/chrome/chrome_cleaner/logging/cleaner_logging_service.h
@@ -141,7 +141,7 @@
   // FolderInformation objects. Expects the lock to be held by the caller.
   void UpdateMatchedFilesAndFoldersMaps(UwS* added_uws);
 
-  // Reads the removal status of all files and folders from
+  // Reads the removal and quarantine status of all files and folders from
   // FileRemovalStatusUpdater and updates them in the report.
   void UpdateFileRemovalStatuses();
 
diff --git a/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc b/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc
index 3b5125a5..cc44f68 100644
--- a/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc
+++ b/chrome/chrome_cleaner/logging/cleaner_logging_service_unittest.cc
@@ -1165,6 +1165,7 @@
   file->mutable_file_information()->set_active_file(
       PathHasActiveExtension(path));
   file->set_removal_status(REMOVAL_STATUS_MATCHED_ONLY);
+  file->set_quarantine_status(QUARANTINE_STATUS_UNSPECIFIED);
 }
 
 // Add a matched folder entry to |uws| with path given by SanitizePath(|path|)
@@ -1423,6 +1424,7 @@
   uws4.set_id(4);
   uws4.set_state(UwS::REMOVABLE);
   AddFileToUwS(kFile1, &uws4);
+  logging_service_->AddDetectedUwS(uws4);
   EXPECT_TRUE(logging_service_->AllExpectedRemovalsConfirmed());
 }
 
diff --git a/chrome/chrome_cleaner/logging/registry_logger_unittest.cc b/chrome/chrome_cleaner/logging/registry_logger_unittest.cc
index 4847596..d35154d 100644
--- a/chrome/chrome_cleaner/logging/registry_logger_unittest.cc
+++ b/chrome/chrome_cleaner/logging/registry_logger_unittest.cc
@@ -354,23 +354,18 @@
     EXPECT_EQ(1UL, expected_pups.count(pup_id));
 }
 
-// TODO(joenotcharles):
-// Have components/chrome_cleaner/public/constants/constant.cc use branding
-// instead of hardcoded strings so that we expect the correct company name here
-// on all builds
-TEST_F(RegistryLoggerTest, DISABLED_LoggingKeyPathContainsCompanyName) {
+TEST_F(RegistryLoggerTest, LoggingKeyPathContainsCompanyName) {
   const RegistryLogger::Mode mode = RegistryLogger::Mode::REPORTER;
   TestRegistryLogger logger(mode);
-  const base::string16 expected_name = base::StrCat(
-      {L"Software\\", COMPANY_SHORTNAME_STRING, L"\\Software Removal Tool"});
+  // This checks directly for the company name Google, instead of using
+  // COMPANY_SHORTNAME_STRING, because it's used for communication with Chrome
+  // so it needs to use Chrome's company name.
+  const base::string16 expected_name =
+      L"Software\\Google\\Software Removal Tool";
   EXPECT_EQ(expected_name, logger.GetLoggingKeyPath(mode));
 }
 
-// TODO(joenotcharles):
-// Have components/chrome_cleaner/public/constants/constant.cc use branding
-// instead of hardcoded strings so that we expect the correct company name here
-// on all builds
-TEST_F(RegistryLoggerTest, DISABLED_UseSuffixRegistryKey) {
+TEST_F(RegistryLoggerTest, UseSuffixRegistryKey) {
   const RegistryLogger::Mode mode = RegistryLogger::Mode::REPORTER;
   TestRegistryLogger logger(mode, kTestSuffix);
   TestRegistryLogger no_suffix_logger(mode);
@@ -379,10 +374,13 @@
   EXPECT_EQ(base::string16::npos,
             key_name.find(base::UTF8ToUTF16(kTestSuffix).c_str()));
 
+  // This checks directly for the company name Google, instead of using
+  // COMPANY_SHORTNAME_STRING, because it's used for communication with Chrome
+  // so it needs to use Chrome's company name.
   key_name = logger.GetLoggingKeyPath(mode);
-  base::string16 expected_name = base::StrCat(
-      {L"Software\\", COMPANY_SHORTNAME_STRING, L"\\Software Removal Tool\\",
-       base::UTF8ToUTF16(kTestSuffix)});
+  const base::string16 expected_name =
+      base::StrCat({L"Software\\Google\\Software Removal Tool\\",
+                    base::UTF8ToUTF16(kTestSuffix)});
   EXPECT_EQ(expected_name, key_name);
 
   base::win::RegKey no_suffix_key;
diff --git a/chrome/chrome_cleaner/logging/scoped_logging.cc b/chrome/chrome_cleaner/logging/scoped_logging.cc
index 9d2befd..e8e2ad6 100644
--- a/chrome/chrome_cleaner/logging/scoped_logging.cc
+++ b/chrome/chrome_cleaner/logging/scoped_logging.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/command_line.h"
 #include "base/file_version_info.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -60,16 +59,8 @@
   DCHECK(success);
   LOG(INFO) << "Starting logs for version: " << CHROME_VERSION_STRING;
 
-#if defined(CHROME_CLEANER_OFFICIAL_BUILD)
-  // Official builds are opt-out, unless no logs upload is specified.
-  bool enable_uploads =
-      chrome_cleaner::Settings::GetInstance()->logs_upload_allowed();
-#else   // if CHROME_CLEANER_OFFICIAL_BUILD
-  // Other builds are opt-in, unless a test logging URL is specified.
-  bool enable_uploads =
-      base::CommandLine::ForCurrentProcess()->HasSwitch(kTestLoggingURLSwitch);
-#endif  // else of if CHROME_CLEANER_OFFICIAL_BUILD
-  logging_service->EnableUploads(enable_uploads, nullptr);
+  logging_service->EnableUploads(
+      chrome_cleaner::Settings::GetInstance()->logs_upload_allowed(), nullptr);
 }
 
 ScopedLogging::~ScopedLogging() {
diff --git a/chrome/chrome_cleaner/logging/utils.cc b/chrome/chrome_cleaner/logging/utils.cc
index 4931802..032125d 100644
--- a/chrome/chrome_cleaner/logging/utils.cc
+++ b/chrome/chrome_cleaner/logging/utils.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <random>
+#include <set>
 #include <vector>
 
 #include "base/command_line.h"
@@ -63,6 +64,7 @@
   FileInformationToProtoObject(file_information,
                                matched_file->mutable_file_information());
   matched_file->set_removal_status(REMOVAL_STATUS_MATCHED_ONLY);
+  matched_file->set_quarantine_status(QUARANTINE_STATUS_UNSPECIFIED);
 }
 
 UwS PUPToUwS(const PUPData::PUP* found_uws,
diff --git a/chrome/chrome_cleaner/proto/uwe_matcher.proto b/chrome/chrome_cleaner/proto/uwe_matcher.proto
index 55e5b18..3e540557 100644
--- a/chrome/chrome_cleaner/proto/uwe_matcher.proto
+++ b/chrome/chrome_cleaner/proto/uwe_matcher.proto
@@ -1,4 +1,6 @@
-// Copyright 2018 Google Inc. All Rights Reserved.
+// Copyright 2018 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.
 
 syntax = "proto2";
 
@@ -54,4 +56,4 @@
 // Next tag: 2
 message UwEMatchers {
   repeated UwEMatcher uwe_matcher = 1;
-}
\ No newline at end of file
+}
diff --git a/chrome/common/apps/platform_apps/media_galleries_permission.cc b/chrome/common/apps/platform_apps/media_galleries_permission.cc
index 621bb130..3721456 100644
--- a/chrome/common/apps/platform_apps/media_galleries_permission.cc
+++ b/chrome/common/apps/platform_apps/media_galleries_permission.cc
@@ -79,9 +79,7 @@
   bool has_read = false;
   bool has_copy_to = false;
   bool has_delete = false;
-  for (std::set<MediaGalleriesPermissionData>::const_iterator it =
-           data_set_.begin();
-       it != data_set_.end(); ++it) {
+  for (auto it = data_set_.cbegin(); it != data_set_.cend(); ++it) {
     if (it->permission() == kAllAutoDetectedPermission) {
       continue;
     }
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn
index 45e6cbd..7866209 100644
--- a/chrome/renderer/BUILD.gn
+++ b/chrome/renderer/BUILD.gn
@@ -130,7 +130,6 @@
     "//components/autofill/content/renderer",
     "//components/cdm/renderer",
     "//components/contextual_search/content:renderer",
-    "//components/data_reduction_proxy/content/common",
     "//components/data_reduction_proxy/content/renderer",
     "//components/data_reduction_proxy/core/common",
     "//components/dom_distiller/content/renderer",
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index f565d31..55ca2694 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -8,7 +8,6 @@
   "+components/contextual_search/content/renderer",
   "+components/crash/core/common/crash_key.h",
   "+components/crx_file",
-  "+components/data_reduction_proxy/content/common",
   "+components/data_reduction_proxy/content/renderer",
   "+components/data_reduction_proxy/core/common",
   "+components/dom_distiller/content/common",
diff --git a/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js b/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js
index bdeabfa..2d328871 100644
--- a/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js
+++ b/chrome/renderer/resources/extensions/chromeos_ime_service_bindings.js
@@ -11,6 +11,20 @@
 
 loadScript('chromeos.ime.mojom.input_engine.mojom');
 
+/**
+ * Empty result to keep Mojo pipe from disconnection.
+ * @type {Promise}
+ * @const
+ */
+var IME_CHANNEL_EMPTY_RESULT = Promise.resolve({result: ""});
+
+/**
+ * Empty message to keep Mojo pipe from disconnection.
+ * @type {Uint8Array}
+ * @const
+ */
+var IME_CHANNEL_EMPTY_EXTRA = new Uint8Array(0);
+
 /*
  * Represents the js-side of the InputChannel.
  * Routes calls from IME service to the IME extension.
@@ -30,9 +44,6 @@
      */
     this.channelPtr_ = undefined;
 
-    /* Default result for calls without response. */
-    this.emptyResult_ = Promise.resolve({result: ""});
-
     /**
      * Handler for the text message.
      *
@@ -86,6 +97,7 @@
   /**
    * Process the text message from a connected input engine.
    *
+   * @type {function(string):Promise<string>}
    * @private
    * @param {string} message
    * @return {!Promise<string>} result.
@@ -94,32 +106,32 @@
     if (this.textHandler_) {
       return Promise.resolve({result: this.textHandler_(message)});
     }
-    return this.emptyResult_;
+    return IME_CHANNEL_EMPTY_RESULT;
   }
 
   /**
    * Process the protobuf message from a connected input engine.
    *
-   * @private
    * @type {function(Uint8Array):Promise<Uint8Array>}
+   * @private
+   * @param {string} message
    * @return {!Promise<!Uint8Array>}
    */
   processMessage(message) {
     if (this.protobufHandler_) {
       return Promise.resolve({result: this.protobufHandler_(message)});
     }
-    return this.emptyResult_;
+    return IME_CHANNEL_EMPTY_RESULT;
   }
 
   /**
-   * Set the error handler when the Mojo pipe is disconnected.
-   * @param {function} handler.
+   * Set the error handler when the channel Mojo pipe is disconnected.
+   * @param {function():void} handler.
    */
-  onConnectionError(handler) {
+  setConnectionErrorHandler(handler) {
     if (typeof handler == 'function') {
       this.binding_.setConnectionErrorHandler(handler);
     }
-    return this;
   }
 }
 
@@ -138,6 +150,7 @@
     this.manager_ = manager;
 
     /**
+     * TODO(crbug.com/837156): Build KeepAlive Mojo pipe.
      * Handle to a KeepAlive service object, which prevents the extension from
      * being suspended as long as it remains in scope.
      * @private
@@ -146,8 +159,8 @@
     this.keepAlive_ = null;
 
     /**
-     * Current active IME Engine proxy. Allows extension code to make calls on
-     * the connected InputEngine that resides in the IME service.
+     * An active IME Engine proxy. Allows extension code to make calls on the
+     * connected InputEngine that resides in the IME service.
      * @private
      * @type {!chromeos.ime.mojom.InputChannelPtr}
      */
@@ -167,29 +180,41 @@
     return this.manager_ && this.manager_.ptr.isBound();
   }
 
+  /**
+   * Set the error handler when the IME Mojo service is disconnected.
+   * @param {function():void} callback.
+   */
+  setConnectionErrorHandler(callback) {
+    if (typeof callback == 'function' && this.isConnected()) {
+      this.manager_.ptr.setConnectionErrorHandler(callback);
+    }
+  }
+
   /** @return {boolean} True if there is connected active IME engine. */
-  isEngineActive() {
+  hasActiveEngine() {
     return this.activeEngine_ && this.activeEngine_.ptr.isBound();
   }
 
   /**
    * Activates an input method based on its specification.
-   * @param {string} The specification of an IME (e.g. the engine ID).
-   * @param {?Uint8Array} The extra data (e.g. initial tasks to run).
-   * @param {function(Object):void} The callback function to invoke when
-   *     the IME activation is done.
+   * @param {string} imeSpec The specification of an IME (e.g. the engine ID).
+   * @param {!Uint8Array} extra The extra data (e.g. initial tasks to run).
+   * @param {function(boolean):void} onConnection The callback function to
+   *     invoke when the IME activation is done.
+   * @param {function():void} onConnectionError The callback function to
+   *     invoke when the Mojo pipe on the active engine is disconnected.
    */
-  activateIME(imeSpec, extra, callback) {
+  activateIME(imeSpec, extra, onConnection, onConnectionError) {
     if (this.isConnected()) {
 
-      // Disconnect the current active engine and make a new one.
       // TODO(crbug.com/837156): Try to reuse the current engine if possible.
-      if (this.isEngineActive()) {
-        this.activeEngine_.ptr.reset();
-        this.activeEngine_ = null;
-      }
+      // Disconnect the current active engine and make a new one.
+      this.deactivateIME();
       this.activeEngine_ = new chromeos.ime.mojom.InputChannelPtr;
 
+      // Null value will cause a disconnection on the Mojo pipe.
+      extra = extra ? extra : IME_CHANNEL_EMPTY_EXTRA;
+
       // Create a client side channel to receive data from service.
       if (!this.clientChannel_) {
         this.clientChannel_ = new ImeExtensionChannel();
@@ -199,9 +224,26 @@
           imeSpec,
           mojo.makeRequest(this.activeEngine_),
           this.clientChannel_.getChannelPtr(),
-          extra).then(callback);
+          extra).then(
+              bound => {
+                if (bound && typeof onConnectionError == 'function') {
+                  this.activeEngine_.ptr.setConnectionErrorHandler(
+                      onConnectionError);
+                };
+                if (typeof onConnection == 'function') {
+                  onConnection(bound);
+                };
+              });
     }
   }
+
+  /** Deactivate the IME engine if it is connected. */
+  deactivateIME() {
+    if (this.hasActiveEngine()) {
+      this.activeEngine_.ptr.reset();
+    }
+    this.activeEngine_ = null;
+  }
 }
 
 (function() {
diff --git a/chrome/renderer/url_loader_throttle_provider_impl.cc b/chrome/renderer/url_loader_throttle_provider_impl.cc
index 9455c5e..3c38ef8 100644
--- a/chrome/renderer/url_loader_throttle_provider_impl.cc
+++ b/chrome/renderer/url_loader_throttle_provider_impl.cc
@@ -16,8 +16,6 @@
 #include "chrome/renderer/chrome_render_thread_observer.h"
 #include "chrome/renderer/prerender/prerender_dispatcher.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
-#include "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/safe_browsing/features.h"
 #include "components/safe_browsing/renderer/renderer_url_loader_throttle.h"
 #include "components/subresource_filter/content/renderer/ad_delay_renderer_metadata_provider.h"
@@ -160,13 +158,6 @@
   DCHECK(!is_frame_resource ||
          type_ == content::URLLoaderThrottleProviderType::kFrame);
 
-  if (data_reduction_proxy::params::IsEnabledWithNetworkService()) {
-    throttles.push_back(
-        std::make_unique<
-            data_reduction_proxy::DataReductionProxyURLLoaderThrottle>(
-            net::HttpRequestHeaders()));
-  }
-
   if ((network_service_enabled ||
        base::FeatureList::IsEnabled(
            safe_browsing::kCheckByURLLoaderThrottle)) &&
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6d50cdd32..d84b250 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -614,10 +614,7 @@
       "../browser/media/webrtc/test_stats_dictionary.h",
       "../browser/media/webrtc/test_stats_dictionary_unittest.cc",
       "../browser/media/webrtc/webrtc_apprtc_browsertest.cc",
-      "../browser/media/webrtc/webrtc_audio_quality_browsertest.cc",
       "../browser/media/webrtc/webrtc_browsertest.cc",
-      "../browser/media/webrtc/webrtc_browsertest_audio.cc",
-      "../browser/media/webrtc/webrtc_browsertest_audio.h",
       "../browser/media/webrtc/webrtc_browsertest_base.cc",
       "../browser/media/webrtc/webrtc_browsertest_base.h",
       "../browser/media/webrtc/webrtc_browsertest_common.cc",
@@ -1032,6 +1029,7 @@
       "//device/base:mocks",
       "//device/bluetooth:mocks",
       "//device/usb:test_support",
+      "//device/usb/public/cpp:test_support",
       "//google_apis:test_support",
       "//media:test_support",
       "//media/cast:test_support",
@@ -2646,7 +2644,6 @@
     "../browser/signin/chrome_signin_url_loader_throttle_unittest.cc",
     "../browser/signin/local_auth_unittest.cc",
     "../browser/signin/signin_status_metrics_provider_chromeos_unittest.cc",
-    "../browser/signin/signin_tracker_unittest.cc",
     "../browser/signin/test_signin_client_builder.cc",
     "../browser/signin/test_signin_client_builder.h",
     "../browser/ssl/certificate_error_report_unittest.cc",
@@ -2884,7 +2881,7 @@
     "//crypto:test_support",
     "//device/base:mocks",
     "//device/bluetooth:mocks",
-    "//device/usb:test_support",
+    "//device/usb/public/cpp:test_support",
     "//extensions/buildflags",
     "//google_apis",
     "//gpu:test_support",
diff --git a/chrome/test/data/webrtc/resources/force_mic_volume_max.exe.sha1 b/chrome/test/data/webrtc/resources/force_mic_volume_max.exe.sha1
deleted file mode 100644
index 037caaca..0000000
--- a/chrome/test/data/webrtc/resources/force_mic_volume_max.exe.sha1
+++ /dev/null
@@ -1 +0,0 @@
-d721e0b1a8eec10d5d1e60ac22d755c1ec7a1587
\ No newline at end of file
diff --git a/chrome/test/data/webrtc/resources/speech_44kHz_16bit_stereo.wav.sha1 b/chrome/test/data/webrtc/resources/speech_44kHz_16bit_stereo.wav.sha1
deleted file mode 100644
index f2661b5..0000000
--- a/chrome/test/data/webrtc/resources/speech_44kHz_16bit_stereo.wav.sha1
+++ /dev/null
@@ -1 +0,0 @@
-98ee0246a46e1b8025353db62e73dbbc81423ef5
\ No newline at end of file
diff --git a/chrome/test/data/webrtc/resources/tools/README b/chrome/test/data/webrtc/resources/tools/README
index 230fa00..f5b4105 100644
--- a/chrome/test/data/webrtc/resources/tools/README
+++ b/chrome/test/data/webrtc/resources/tools/README
@@ -1,8 +1,3 @@
 The files in this directory are downloaded from gs://chrome-webrtc-resources,
 which is a google-internal bucket. The files in .. are downloaded from
 gs://chromium-webrtc-resources, which is public.
-
-About PESQ:
-The PESQ version is the http://www.itu.int/rec/T-REC-P.862-200511-I!Amd2/en.
-Don't download the 02/01 version which prints its results differently; that
-will not work with the test which expects a raw MOS and MOS-LQO number.
diff --git a/chrome/test/data/webrtc/resources/tools/linux/pesq.sha1 b/chrome/test/data/webrtc/resources/tools/linux/pesq.sha1
deleted file mode 100644
index 24f8a05..0000000
--- a/chrome/test/data/webrtc/resources/tools/linux/pesq.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bfbf5fa8fd9d6be5b4aa3f50caedbd786b0a034b
\ No newline at end of file
diff --git a/chrome/test/data/webrtc/resources/tools/mac/pesq.sha1 b/chrome/test/data/webrtc/resources/tools/mac/pesq.sha1
deleted file mode 100644
index 08b19a6f..0000000
--- a/chrome/test/data/webrtc/resources/tools/mac/pesq.sha1
+++ /dev/null
@@ -1 +0,0 @@
-9b9349dd7ef47709ca497cd66d9c453ab2b5c732
\ No newline at end of file
diff --git a/chrome/test/data/webrtc/resources/tools/win/pesq.exe.sha1 b/chrome/test/data/webrtc/resources/tools/win/pesq.exe.sha1
deleted file mode 100644
index 23c9869..0000000
--- a/chrome/test/data/webrtc/resources/tools/win/pesq.exe.sha1
+++ /dev/null
@@ -1 +0,0 @@
-67726dd1d186b142a95914efc93233b8a9e583fe
\ No newline at end of file
diff --git a/chrome/test/data/webrtc/resources/tools/win/sox.exe.sha1 b/chrome/test/data/webrtc/resources/tools/win/sox.exe.sha1
deleted file mode 100644
index bebbc03..0000000
--- a/chrome/test/data/webrtc/resources/tools/win/sox.exe.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c0997b90aed7664b64f47699f86e9ddbf065dc71
\ No newline at end of file
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index ae3d1ff7..f85b583 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -4,6 +4,8 @@
 
 #include <stddef.h>
 
+#include <vector>
+
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/optional.h"
@@ -386,16 +388,20 @@
 
   kBindClosePipe,
   kBindError,
+  kBindHangs,
 
   // These apply to both CreateTCPServerSocket and TCPBoundSocket::Listen().
   kCreateTCPServerSocketClosePipe,
   kCreateTCPServerSocketError,
+  kCreateTCPServerSocketHangs,
 
   kAcceptDropPipe,
   kAcceptError,
+  kAcceptHangs,
 
   kConnectClosePipe,
   kConnectError,
+  kConnectHangs,
   kWriteClosePipe,
   kWriteError,
   kReadClosePipe,
@@ -407,6 +413,7 @@
 
   kUpgradeToTLSClosePipe,
   kUpgradeToTLSError,
+  kUpgradeToTLSHangs,
   kSSLWriteClosePipe,
   kSSLWriteError,
   kSSLReadClosePipe,
@@ -444,6 +451,11 @@
       return;
     }
 
+    if (tcp_failure_type_ == TCPFailureType::kConnectHangs) {
+      create_connected_socket_callback_ = std::move(callback);
+      return;
+    }
+
     mojo::DataPipe send_pipe;
     mojo::DataPipe receive_pipe;
 
@@ -473,6 +485,11 @@
       return;
     }
 
+    if (tcp_failure_type_ == TCPFailureType::kAcceptHangs) {
+      accept_callback_ = std::move(callback);
+      return;
+    }
+
     mojo::DataPipe send_pipe;
     mojo::DataPipe receive_pipe;
 
@@ -516,6 +533,11 @@
       return;
     }
 
+    if (tcp_failure_type_ == TCPFailureType::kUpgradeToTLSHangs) {
+      upgrade_to_tls_callback_ = std::move(callback);
+      return;
+    }
+
     // Invoke callback immediately, without waiting for pipes to close - tests
     // that use a real NetworkContext already make sure that the class correctly
     // closes the sockets when upgrading.
@@ -600,6 +622,13 @@
 
   network::mojom::SocketObserverPtr observer_;
 
+  // Callbacks held onto when simulating a hang.
+  network::mojom::NetworkContext::CreateTCPConnectedSocketCallback
+      create_connected_socket_callback_;
+  network::mojom::TCPServerSocket::AcceptCallback accept_callback_;
+  network::mojom::TCPConnectedSocket::UpgradeToTLSCallback
+      upgrade_to_tls_callback_;
+
   mojo::ScopedDataPipeProducerHandle receive_pipe_handle_;
   mojo::ScopedDataPipeConsumerHandle send_pipe_handle_;
 
@@ -622,6 +651,10 @@
       std::move(callback).Run(net::ERR_FAILED, base::nullopt /* local_addr */);
       return;
     }
+    if (tcp_failure_type_ == TCPFailureType::kCreateTCPServerSocketHangs) {
+      create_server_socket_callback_ = std::move(callback);
+      return;
+    }
     std::move(callback).Run(net::OK, LocalAddress());
   }
 
@@ -635,6 +668,10 @@
       std::move(callback).Run(net::ERR_FAILED);
       return;
     }
+    if (tcp_failure_type_ == TCPFailureType::kCreateTCPServerSocketHangs) {
+      listen_callback_ = std::move(callback);
+      return;
+    }
     std::move(callback).Run(net::OK);
   }
 
@@ -655,6 +692,11 @@
 
   std::unique_ptr<MockTCPConnectedSocket> connected_socket_;
 
+  // Callbacks held onto when simulating a hang.
+  network::mojom::NetworkContext::CreateTCPServerSocketCallback
+      create_server_socket_callback_;
+  network::mojom::TCPBoundSocket::ListenCallback listen_callback_;
+
   mojo::Binding<network::mojom::TCPServerSocket> binding_;
 
   DISALLOW_COPY_AND_ASSIGN(MockTCPServerSocket);
@@ -672,6 +714,10 @@
       std::move(callback).Run(net::ERR_FAILED, base::nullopt /* local_addr */);
       return;
     }
+    if (tcp_failure_type_ == TCPFailureType::kBindHangs) {
+      callback_ = std::move(callback);
+      return;
+    }
     std::move(callback).Run(net::OK, LocalAddress());
   }
 
@@ -711,6 +757,9 @@
   std::unique_ptr<MockTCPServerSocket> server_socket_;
   std::unique_ptr<MockTCPConnectedSocket> connected_socket_;
 
+  // Callback held onto when simulating a hang.
+  network::mojom::NetworkContext::CreateTCPBoundSocketCallback callback_;
+
   mojo::Binding<network::mojom::TCPBoundSocket> binding_;
 
   DISALLOW_COPY_AND_ASSIGN(MockTCPBoundSocket);
@@ -738,8 +787,8 @@
     // TCPBoundSocket's pipe, which was just closed.
     if (tcp_failure_type_ == TCPFailureType::kCreateTCPServerSocketClosePipe)
       binding_.Close();
-    server_socket_ = std::make_unique<MockTCPServerSocket>(
-        tcp_failure_type_, std::move(request), std::move(callback));
+    server_sockets_.emplace_back(std::make_unique<MockTCPServerSocket>(
+        tcp_failure_type_, std::move(request), std::move(callback)));
   }
 
   void CreateTCPConnectedSocket(
@@ -752,9 +801,9 @@
       CreateTCPConnectedSocketCallback callback) override {
     if (tcp_failure_type_ == TCPFailureType::kConnectClosePipe)
       binding_.Close();
-    connected_socket_ = std::make_unique<MockTCPConnectedSocket>(
+    connected_sockets_.emplace_back(std::make_unique<MockTCPConnectedSocket>(
         tcp_failure_type_, std::move(socket), std::move(observer),
-        std::move(callback));
+        std::move(callback)));
   }
 
   void CreateTCPBoundSocket(
@@ -765,8 +814,8 @@
     if (tcp_failure_type_ == TCPFailureType::kBindClosePipe)
       binding_.Close();
     // These tests only create at most one object of a given type at a time.
-    bound_socket_ = std::make_unique<MockTCPBoundSocket>(
-        tcp_failure_type_, std::move(request), std::move(callback));
+    bound_sockets_.emplace_back(std::make_unique<MockTCPBoundSocket>(
+        tcp_failure_type_, std::move(request), std::move(callback)));
   }
 
   void ResolveHost(
@@ -779,9 +828,9 @@
  private:
   TCPFailureType tcp_failure_type_;
 
-  std::unique_ptr<MockTCPServerSocket> server_socket_;
-  std::unique_ptr<MockTCPBoundSocket> bound_socket_;
-  std::unique_ptr<MockTCPConnectedSocket> connected_socket_;
+  std::vector<std::unique_ptr<MockTCPServerSocket>> server_sockets_;
+  std::vector<std::unique_ptr<MockTCPBoundSocket>> bound_sockets_;
+  std::vector<std::unique_ptr<MockTCPConnectedSocket>> connected_sockets_;
 
   mojo::Binding<network::mojom::NetworkContext> binding_;
 
@@ -829,6 +878,9 @@
 TCP_SOCKET_FAILURE_TEST(TCPSocket_ConnectError,
                         TCPSocket_ConnectFails,
                         TCPFailureType::kConnectError);
+TCP_SOCKET_FAILURE_TEST(TCPSocket_ConnectHangs,
+                        TCPSocket_ConnectHangs,
+                        TCPFailureType::kConnectHangs);
 TCP_SOCKET_FAILURE_TEST(TCPSocket_WriteClosePipe,
                         TCPSocket_WriteFails,
                         TCPFailureType::kWriteClosePipe);
@@ -869,18 +921,27 @@
 TCP_SOCKET_FAILURE_TEST(TCPSocket_BindError,
                         TCPSocket_BindFailsConnectSucceeds,
                         TCPFailureType::kBindError);
+TCP_SOCKET_FAILURE_TEST(TCPSocket_BindHangs,
+                        TCPSocket_BindHangs,
+                        TCPFailureType::kBindHangs);
 TCP_SOCKET_FAILURE_TEST(TCPSocket_ListenClosePipe,
                         TCPSocket_ListenFails,
                         TCPFailureType::kCreateTCPServerSocketClosePipe);
 TCP_SOCKET_FAILURE_TEST(TCPSocket_ListenError,
                         TCPSocket_ListenFails,
                         TCPFailureType::kCreateTCPServerSocketError);
+TCP_SOCKET_FAILURE_TEST(TCPSocket_ListenHangs,
+                        TCPSocket_ListenHangs,
+                        TCPFailureType::kCreateTCPServerSocketHangs);
 TCP_SOCKET_FAILURE_TEST(TCPSocket_AcceptClosePipe,
                         TCPSocket_AcceptFails,
                         TCPFailureType::kAcceptDropPipe);
 TCP_SOCKET_FAILURE_TEST(TCPSocket_AcceptError,
                         TCPSocket_AcceptFails,
                         TCPFailureType::kAcceptError);
+TCP_SOCKET_FAILURE_TEST(TCPSocket_AcceptHangs,
+                        TCPSocket_AcceptHangs,
+                        TCPFailureType::kAcceptHangs);
 TCP_SOCKET_FAILURE_TEST(TCPSocket_AcceptedSocketWriteClosePipe,
                         TCPSocket_AcceptedSocketWriteFails,
                         TCPFailureType::kWriteClosePipe);
@@ -899,6 +960,9 @@
 TCP_SOCKET_FAILURE_TEST(TCPSocket_BindConnectError,
                         TCPSocket_BindConnectFails,
                         TCPFailureType::kConnectError);
+TCP_SOCKET_FAILURE_TEST(TCPSocket_BindConnectHangs,
+                        TCPSocket_BindConnectHangs,
+                        TCPFailureType::kConnectHangs);
 
 TCP_SOCKET_FAILURE_TEST(TCPSocketPrivate_SSLHandshakeClosePipe,
                         TCPSocketPrivate_SSLHandshakeFails,
@@ -906,6 +970,9 @@
 TCP_SOCKET_FAILURE_TEST(TCPSocketPrivate_SSLHandshakeError,
                         TCPSocketPrivate_SSLHandshakeFails,
                         TCPFailureType::kUpgradeToTLSError);
+TCP_SOCKET_FAILURE_TEST(TCPSocketPrivate_SSLHandshakeHangs,
+                        TCPSocketPrivate_SSLHandshakeHangs,
+                        TCPFailureType::kUpgradeToTLSHangs);
 TCP_SOCKET_FAILURE_TEST(TCPSocketPrivate_SSLWriteClosePipe,
                         TCPSocketPrivate_SSLWriteFails,
                         TCPFailureType::kSSLWriteClosePipe);
@@ -925,12 +992,18 @@
 TCP_SOCKET_FAILURE_TEST(TCPServerSocketPrivate_ListenError,
                         TCPServerSocketPrivate_ListenFails,
                         TCPFailureType::kCreateTCPServerSocketError);
+TCP_SOCKET_FAILURE_TEST(TCPServerSocketPrivate_ListenHangs,
+                        TCPServerSocketPrivate_ListenHangs,
+                        TCPFailureType::kCreateTCPServerSocketHangs);
 TCP_SOCKET_FAILURE_TEST(TCPServerSocketPrivate_AcceptClosePipe,
                         TCPServerSocketPrivate_AcceptFails,
                         TCPFailureType::kAcceptDropPipe);
 TCP_SOCKET_FAILURE_TEST(TCPServerSocketPrivate_AcceptError,
                         TCPServerSocketPrivate_AcceptFails,
                         TCPFailureType::kAcceptError);
+TCP_SOCKET_FAILURE_TEST(TCPServerSocketPrivate_AcceptHangs,
+                        TCPServerSocketPrivate_AcceptHangs,
+                        TCPFailureType::kAcceptHangs);
 
 // UDPSocket tests.
 
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 9aeb750..2d3f4bd 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-11142.0.0
\ No newline at end of file
+11143.0.0
\ No newline at end of file
diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc
index ca6a32a1..f1b26dc 100644
--- a/chromeos/dbus/update_engine_client.cc
+++ b/chromeos/dbus/update_engine_client.cc
@@ -380,6 +380,17 @@
       return;
     }
     status.status = UpdateStatusFromString(current_operation);
+    // TODO(hunyadym, https://crbug.com/864672): Add a new DBus call to
+    // determine this based on the Omaha response, and not version comparison.
+    const std::string current_version =
+        version_loader::GetVersion(version_loader::VERSION_SHORT);
+    status.is_rollback =
+        version_loader::IsRollback(current_version, status.new_version);
+    if (status.is_rollback) {
+      LOG(WARNING) << "New image is a rollback from " << current_version
+                   << " to " << status.new_version << ".";
+    }
+
     last_status_ = status;
     for (auto& observer : observers_)
       observer.UpdateStatusChanged(status);
@@ -506,7 +517,7 @@
     status.new_version = new_version;
     // TODO(hunyadym, https://crbug.com/864672): Add a new DBus call to
     // determine this based on the Omaha response, and not version comparison.
-    std::string current_version =
+    const std::string current_version =
         version_loader::GetVersion(version_loader::VERSION_SHORT);
     status.is_rollback =
         version_loader::IsRollback(current_version, status.new_version);
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 4abde54..714b7a0 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -207,7 +207,6 @@
       "//components/crash/content/browser:unit_tests",
       "//components/crash/core/common:unit_tests",
       "//components/data_reduction_proxy/content/browser:unit_tests",
-      "//components/data_reduction_proxy/content/common:unit_tests",
       "//components/data_reduction_proxy/content/renderer:unit_tests",
       "//components/data_reduction_proxy/core/browser:unit_tests",
       "//components/data_reduction_proxy/core/common:unit_tests",
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index 53c7396..43f7207 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -89,18 +89,18 @@
 }
 
 bool IsOptionElement(const WebElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kOption, ("option"));
-  return element.HasHTMLTagName(kOption);
+  static base::NoDestructor<WebString> kOption("option");
+  return element.HasHTMLTagName(*kOption);
 }
 
 bool IsScriptElement(const WebElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kScript, ("script"));
-  return element.HasHTMLTagName(kScript);
+  static base::NoDestructor<WebString> kScript("script");
+  return element.HasHTMLTagName(*kScript);
 }
 
 bool IsNoScriptElement(const WebElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kNoScript, ("noscript"));
-  return element.HasHTMLTagName(kNoScript);
+  static base::NoDestructor<WebString> kNoScript("noscript");
+  return element.HasHTMLTagName(*kNoScript);
 }
 
 bool HasTagName(const WebNode& node, const blink::WebString& tag) {
@@ -301,13 +301,13 @@
     // Coalesce any text contained in multiple consecutive
     //  (a) plain text nodes or
     //  (b) inline HTML elements that are essentially equivalent to text nodes.
-    CR_DEFINE_STATIC_LOCAL(WebString, kBold, ("b"));
-    CR_DEFINE_STATIC_LOCAL(WebString, kStrong, ("strong"));
-    CR_DEFINE_STATIC_LOCAL(WebString, kSpan, ("span"));
-    CR_DEFINE_STATIC_LOCAL(WebString, kFont, ("font"));
-    if (sibling.IsTextNode() || HasTagName(sibling, kBold) ||
-        HasTagName(sibling, kStrong) || HasTagName(sibling, kSpan) ||
-        HasTagName(sibling, kFont)) {
+    static base::NoDestructor<WebString> kBold("b");
+    static base::NoDestructor<WebString> kStrong("strong");
+    static base::NoDestructor<WebString> kSpan("span");
+    static base::NoDestructor<WebString> kFont("font");
+    if (sibling.IsTextNode() || HasTagName(sibling, *kBold) ||
+        HasTagName(sibling, *kStrong) || HasTagName(sibling, *kSpan) ||
+        HasTagName(sibling, *kFont)) {
       base::string16 value = FindChildText(sibling);
       // A text node's value will be empty if it is for a line break.
       bool add_space = sibling.IsTextNode() && value.empty();
@@ -328,16 +328,16 @@
 
     // <img> and <br> tags often appear between the input element and its
     // label text, so skip over them.
-    CR_DEFINE_STATIC_LOCAL(WebString, kImage, ("img"));
-    CR_DEFINE_STATIC_LOCAL(WebString, kBreak, ("br"));
-    if (HasTagName(sibling, kImage) || HasTagName(sibling, kBreak))
+    static base::NoDestructor<WebString> kImage("img");
+    static base::NoDestructor<WebString> kBreak("br");
+    if (HasTagName(sibling, *kImage) || HasTagName(sibling, *kBreak))
       continue;
 
     // We only expect <p> and <label> tags to contain the full label text.
-    CR_DEFINE_STATIC_LOCAL(WebString, kPage, ("p"));
-    CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label"));
-    bool has_label_tag = HasTagName(sibling, kLabel);
-    if (HasTagName(sibling, kPage) || has_label_tag) {
+    static base::NoDestructor<WebString> kPage("p");
+    static base::NoDestructor<WebString> kLabel("label");
+    bool has_label_tag = HasTagName(sibling, *kLabel);
+    if (HasTagName(sibling, *kPage) || has_label_tag) {
       inferred_label = FindChildText(sibling);
       inferred_label_source = has_label_tag
                                   ? FormFieldData::LabelSource::LABEL_TAG
@@ -385,9 +385,9 @@
 // Helper for |InferLabelForElement()| that infers a label, if possible, from
 // the placeholder text. e.g. <input placeholder="foo">
 base::string16 InferLabelFromPlaceholder(const WebFormControlElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kPlaceholder, ("placeholder"));
-  if (element.HasAttribute(kPlaceholder))
-    return element.GetAttribute(kPlaceholder).Utf16();
+  static base::NoDestructor<WebString> kPlaceholder("placeholder");
+  if (element.HasAttribute(*kPlaceholder))
+    return element.GetAttribute(*kPlaceholder).Utf16();
 
   return base::string16();
 }
@@ -406,10 +406,10 @@
 // the value attribute when it is present and user has not typed in (if
 // element's value attribute is same as the element's value).
 base::string16 InferLabelFromValueAttr(const WebFormControlElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kValue, ("value"));
-  if (element.HasAttribute(kValue) &&
-      element.GetAttribute(kValue) == element.Value()) {
-    return element.GetAttribute(kValue).Utf16();
+  static base::NoDestructor<WebString> kValue("value");
+  if (element.HasAttribute(*kValue) &&
+      element.GetAttribute(*kValue) == element.Value()) {
+    return element.GetAttribute(*kValue).Utf16();
   }
 
   return base::string16();
@@ -420,13 +420,13 @@
 // e.g. <li>Some Text<input ...><input ...><input ...></li>
 base::string16 InferLabelFromListItem(const WebFormControlElement& element) {
   WebNode parent = element.ParentNode();
-  CR_DEFINE_STATIC_LOCAL(WebString, kListItem, ("li"));
+  static base::NoDestructor<WebString> kListItem("li");
   while (!parent.IsNull() && parent.IsElementNode() &&
-         !parent.To<WebElement>().HasHTMLTagName(kListItem)) {
+         !parent.To<WebElement>().HasHTMLTagName(*kListItem)) {
     parent = parent.ParentNode();
   }
 
-  if (!parent.IsNull() && HasTagName(parent, kListItem))
+  if (!parent.IsNull() && HasTagName(parent, *kListItem))
     return FindChildText(parent);
 
   return base::string16();
@@ -438,13 +438,13 @@
 base::string16 InferLabelFromEnclosingLabel(
     const WebFormControlElement& element) {
   WebNode parent = element.ParentNode();
-  CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label"));
+  static base::NoDestructor<WebString> kLabel("label");
   while (!parent.IsNull() && parent.IsElementNode() &&
-         !parent.To<WebElement>().HasHTMLTagName(kLabel)) {
+         !parent.To<WebElement>().HasHTMLTagName(*kLabel)) {
     parent = parent.ParentNode();
   }
 
-  if (!parent.IsNull() && HasTagName(parent, kLabel))
+  if (!parent.IsNull() && HasTagName(parent, *kLabel))
     return FindChildText(parent);
 
   return base::string16();
@@ -457,10 +457,10 @@
 // or   <tr><td><b>Some Text</b></td><td><b><input ...></b></td></tr>
 // or   <tr><th><b>Some Text</b></th><td><b><input ...></b></td></tr>
 base::string16 InferLabelFromTableColumn(const WebFormControlElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kTableCell, ("td"));
+  static base::NoDestructor<WebString> kTableCell("td");
   WebNode parent = element.ParentNode();
   while (!parent.IsNull() && parent.IsElementNode() &&
-         !parent.To<WebElement>().HasHTMLTagName(kTableCell)) {
+         !parent.To<WebElement>().HasHTMLTagName(*kTableCell)) {
     parent = parent.ParentNode();
   }
 
@@ -471,9 +471,10 @@
   // non-empty text block.
   base::string16 inferred_label;
   WebNode previous = parent.PreviousSibling();
-  CR_DEFINE_STATIC_LOCAL(WebString, kTableHeader, ("th"));
+  static base::NoDestructor<WebString> kTableHeader("th");
   while (inferred_label.empty() && !previous.IsNull()) {
-    if (HasTagName(previous, kTableCell) || HasTagName(previous, kTableHeader))
+    if (HasTagName(previous, *kTableCell) ||
+        HasTagName(previous, *kTableHeader))
       inferred_label = FindChildText(previous);
 
     previous = previous.PreviousSibling();
@@ -493,14 +494,14 @@
 // Otherwise, just look in the entire previous row.
 // e.g. <tr><td>Some Text</td></tr><tr><td><input ...></td></tr>
 base::string16 InferLabelFromTableRow(const WebFormControlElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kTableCell, ("td"));
+  static base::NoDestructor<WebString> kTableCell("td");
   base::string16 inferred_label;
 
   // First find the <td> that contains |element|.
   WebNode cell = element.ParentNode();
   while (!cell.IsNull()) {
     if (cell.IsElementNode() &&
-        cell.To<WebElement>().HasHTMLTagName(kTableCell)) {
+        cell.To<WebElement>().HasHTMLTagName(*kTableCell)) {
       break;
     }
     cell = cell.ParentNode();
@@ -519,7 +520,7 @@
   for (WebNode cell_it = cell.PreviousSibling(); !cell_it.IsNull();
        cell_it = cell_it.PreviousSibling()) {
     if (cell_it.IsElementNode() &&
-        cell_it.To<WebElement>().HasHTMLTagName(kTableCell)) {
+        cell_it.To<WebElement>().HasHTMLTagName(*kTableCell)) {
       cell_position += CalculateTableCellColumnSpan(cell_it.To<WebElement>());
     }
   }
@@ -528,7 +529,7 @@
   for (WebNode cell_it = cell.NextSibling(); !cell_it.IsNull();
        cell_it = cell_it.NextSibling()) {
     if (cell_it.IsElementNode() &&
-        cell_it.To<WebElement>().HasHTMLTagName(kTableCell)) {
+        cell_it.To<WebElement>().HasHTMLTagName(*kTableCell)) {
       cell_count += CalculateTableCellColumnSpan(cell_it.To<WebElement>());
     }
   }
@@ -538,10 +539,10 @@
   cell_position_end += cell_position;
 
   // Find the current row.
-  CR_DEFINE_STATIC_LOCAL(WebString, kTableRow, ("tr"));
+  static base::NoDestructor<WebString> kTableRow("tr");
   WebNode parent = element.ParentNode();
   while (!parent.IsNull() && parent.IsElementNode() &&
-         !parent.To<WebElement>().HasHTMLTagName(kTableRow)) {
+         !parent.To<WebElement>().HasHTMLTagName(*kTableRow)) {
     parent = parent.ParentNode();
   }
 
@@ -552,7 +553,7 @@
   WebNode row_it = parent.PreviousSibling();
   while (!row_it.IsNull()) {
     if (row_it.IsElementNode() &&
-        row_it.To<WebElement>().HasHTMLTagName(kTableRow)) {
+        row_it.To<WebElement>().HasHTMLTagName(*kTableRow)) {
       break;
     }
     row_it = row_it.PreviousSibling();
@@ -564,12 +565,12 @@
     WebNode matching_cell;
     size_t prev_row_count = 0;
     WebNode prev_row_it = row_it.FirstChild();
-    CR_DEFINE_STATIC_LOCAL(WebString, kTableHeader, ("th"));
+    static base::NoDestructor<WebString> kTableHeader("th");
     while (!prev_row_it.IsNull()) {
       if (prev_row_it.IsElementNode()) {
         WebElement prev_row_element = prev_row_it.To<WebElement>();
-        if (prev_row_element.HasHTMLTagName(kTableCell) ||
-            prev_row_element.HasHTMLTagName(kTableHeader)) {
+        if (prev_row_element.HasHTMLTagName(*kTableCell) ||
+            prev_row_element.HasHTMLTagName(*kTableHeader)) {
           size_t span = CalculateTableCellColumnSpan(prev_row_element);
           size_t prev_row_count_end = prev_row_count + span - 1;
           if (prev_row_count == cell_position &&
@@ -593,7 +594,7 @@
   // find a non-empty text block.
   WebNode previous = parent.PreviousSibling();
   while (inferred_label.empty() && !previous.IsNull()) {
-    if (HasTagName(previous, kTableRow))
+    if (HasTagName(previous, *kTableRow))
       inferred_label = FindChildText(previous);
 
     previous = previous.PreviousSibling();
@@ -616,10 +617,10 @@
 
   // Search the sibling and parent <div>s until we find a candidate label.
   base::string16 inferred_label;
-  CR_DEFINE_STATIC_LOCAL(WebString, kDiv, ("div"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label"));
+  static base::NoDestructor<WebString> kDiv("div");
+  static base::NoDestructor<WebString> kLabel("label");
   while (inferred_label.empty() && !node.IsNull()) {
-    if (HasTagName(node, kDiv)) {
+    if (HasTagName(node, *kDiv)) {
       if (looking_for_parent)
         inferred_label = FindChildTextWithIgnoreList(node, divs_to_skip);
       else
@@ -627,9 +628,9 @@
 
       // Avoid sibling DIVs that contain autofillable fields.
       if (!looking_for_parent && !inferred_label.empty()) {
-        CR_DEFINE_STATIC_LOCAL(WebString, kSelector,
-                               ("input, select, textarea"));
-        WebElement result_element = node.QuerySelector(kSelector);
+        static base::NoDestructor<WebString> kSelector(
+            "input, select, textarea");
+        WebElement result_element = node.QuerySelector(*kSelector);
         if (!result_element.IsNull()) {
           inferred_label.clear();
           divs_to_skip.insert(node);
@@ -637,7 +638,7 @@
       }
 
       looking_for_parent = false;
-    } else if (!looking_for_parent && HasTagName(node, kLabel)) {
+    } else if (!looking_for_parent && HasTagName(node, *kLabel)) {
       WebLabelElement label_element = node.To<WebLabelElement>();
       if (label_element.CorrespondingControl().IsNull())
         inferred_label = FindChildText(node);
@@ -663,13 +664,13 @@
 // e.g. <dl><dt><b>Some Text</b></dt><dd><b><input ...></b></dd></dl>
 base::string16 InferLabelFromDefinitionList(
     const WebFormControlElement& element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionData, ("dd"));
+  static base::NoDestructor<WebString> kDefinitionData("dd");
   WebNode parent = element.ParentNode();
   while (!parent.IsNull() && parent.IsElementNode() &&
-         !parent.To<WebElement>().HasHTMLTagName(kDefinitionData))
+         !parent.To<WebElement>().HasHTMLTagName(*kDefinitionData))
     parent = parent.ParentNode();
 
-  if (parent.IsNull() || !HasTagName(parent, kDefinitionData))
+  if (parent.IsNull() || !HasTagName(parent, *kDefinitionData))
     return base::string16();
 
   // Skip by any intervening text nodes.
@@ -677,8 +678,8 @@
   while (!previous.IsNull() && previous.IsTextNode())
     previous = previous.PreviousSibling();
 
-  CR_DEFINE_STATIC_LOCAL(WebString, kDefinitionTag, ("dt"));
-  if (previous.IsNull() || !HasTagName(previous, kDefinitionTag))
+  static base::NoDestructor<WebString> kDefinitionTag("dt");
+  if (previous.IsNull() || !HasTagName(previous, *kDefinitionTag))
     return base::string16();
 
   return FindChildText(previous);
@@ -850,8 +851,8 @@
     // attribute) and the field that initiated the filling, i.e. the field the
     // user is currently editing and interacting with.
     const WebInputElement* input_element = ToWebInputElement(element);
-    CR_DEFINE_STATIC_LOCAL(WebString, kValue, ("value"));
-    CR_DEFINE_STATIC_LOCAL(WebString, kPlaceholder, ("placeholder"));
+    static base::NoDestructor<WebString> kValue("value");
+    static base::NoDestructor<WebString> kPlaceholder("placeholder");
 
     if (!is_initiating_element &&
         element->GetAutofillState() == WebAutofillState::kAutofilled)
@@ -870,10 +871,10 @@
         (element->UserHasEditedTheField() ||
          !base::FeatureList::IsEnabled(features::kAutofillPrefilledFields)) &&
         !SanitizedFieldIsEmpty(element->Value().Utf16()) &&
-        (!element->HasAttribute(kValue) ||
-         element->GetAttribute(kValue) != element->Value()) &&
-        (!element->HasAttribute(kPlaceholder) ||
-         base::i18n::ToLower(element->GetAttribute(kPlaceholder).Utf16()) !=
+        (!element->HasAttribute(*kValue) ||
+         element->GetAttribute(*kValue) != element->Value()) &&
+        (!element->HasAttribute(*kPlaceholder) ||
+         base::i18n::ToLower(element->GetAttribute(*kPlaceholder).Utf16()) !=
              base::i18n::ToLower(element->Value().Utf16())))
       continue;
 
@@ -1059,8 +1060,8 @@
 void MatchLabelsAndFields(
     const WebElementCollection& labels,
     std::map<WebFormControlElement, FormFieldData*>* element_map) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kFor, ("for"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kHidden, ("hidden"));
+  static base::NoDestructor<WebString> kFor("for");
+  static base::NoDestructor<WebString> kHidden("hidden");
 
   for (WebElement item = labels.FirstItem(); !item.IsNull();
        item = labels.NextItem()) {
@@ -1071,7 +1072,7 @@
     if (control.IsNull()) {
       // Sometimes site authors will incorrectly specify the corresponding
       // field element's name rather than its id, so we compensate here.
-      base::string16 element_name = label.GetAttribute(kFor).Utf16();
+      base::string16 element_name = label.GetAttribute(*kFor).Utf16();
       if (element_name.empty())
         continue;
       // Look through the list for elements with this name. There can actually
@@ -1088,7 +1089,7 @@
       }
     } else if (control.IsFormControlElement()) {
       WebFormControlElement form_control = control.To<WebFormControlElement>();
-      if (form_control.FormControlTypeForAutofill() == kHidden)
+      if (form_control.FormControlTypeForAutofill() == *kHidden)
         continue;
       // Typical case: look up |field_data| in |element_map|.
       auto iter = element_map->find(form_control);
@@ -1126,7 +1127,7 @@
     ExtractMask extract_mask,
     FormData* form,
     FormFieldData* field) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kLabel, ("label"));
+  static base::NoDestructor<WebString> kLabel("label");
 
   if (form_element)
     DCHECK(fieldsets.empty());
@@ -1157,14 +1158,14 @@
     // previously created FormFieldData and set the FormFieldData's label to the
     // label.firstChild().nodeValue() of the label element.
     WebElementCollection labels =
-        form_element->GetElementsByHTMLTagName(kLabel);
+        form_element->GetElementsByHTMLTagName(*kLabel);
     DCHECK(!labels.IsNull());
     MatchLabelsAndFields(labels, &element_map);
   } else {
     // Same as the if block, but for all the labels in fieldsets.
     for (size_t i = 0; i < fieldsets.size(); ++i) {
       WebElementCollection labels =
-          fieldsets[i].GetElementsByHTMLTagName(kLabel);
+          fieldsets[i].GetElementsByHTMLTagName(*kLabel);
       DCHECK(!labels.IsNull());
       MatchLabelsAndFields(labels, &element_map);
     }
@@ -1374,9 +1375,9 @@
 }
 
 bool IsMonthInput(const WebInputElement* element) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kMonth, ("month"));
+  static base::NoDestructor<WebString> kMonth("month");
   return element && !element->IsNull() &&
-         element->FormControlTypeForAutofill() == kMonth;
+         element->FormControlTypeForAutofill() == *kMonth;
 }
 
 // All text fields, including password fields, should be extracted.
@@ -1386,15 +1387,16 @@
 
 bool IsSelectElement(const WebFormControlElement& element) {
   // Static for improved performance.
-  CR_DEFINE_STATIC_LOCAL(WebString, kSelectOne, ("select-one"));
+  static base::NoDestructor<WebString> kSelectOne("select-one");
   return !element.IsNull() &&
-         element.FormControlTypeForAutofill() == kSelectOne;
+         element.FormControlTypeForAutofill() == *kSelectOne;
 }
 
 bool IsTextAreaElement(const WebFormControlElement& element) {
   // Static for improved performance.
-  CR_DEFINE_STATIC_LOCAL(WebString, kTextArea, ("textarea"));
-  return !element.IsNull() && element.FormControlTypeForAutofill() == kTextArea;
+  static base::NoDestructor<WebString> kTextArea("textarea");
+  return !element.IsNull() &&
+         element.FormControlTypeForAutofill() == *kTextArea;
 }
 
 bool IsCheckableElement(const WebInputElement* element) {
@@ -1422,9 +1424,9 @@
 
 const base::string16 GetFormIdentifier(const WebFormElement& form) {
   base::string16 identifier = form.GetName().Utf16();
-  CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id"));
+  static base::NoDestructor<WebString> kId("id");
   if (identifier.empty())
-    identifier = form.GetAttribute(kId).Utf16();
+    identifier = form.GetAttribute(*kId).Utf16();
 
   return identifier;
 }
@@ -1471,35 +1473,35 @@
     FormFieldData* field) {
   DCHECK(field);
   DCHECK(!element.IsNull());
-  CR_DEFINE_STATIC_LOCAL(WebString, kAutocomplete, ("autocomplete"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kId, ("id"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kRole, ("role"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kPlaceholder, ("placeholder"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kClass, ("class"));
+  static base::NoDestructor<WebString> kAutocomplete("autocomplete");
+  static base::NoDestructor<WebString> kId("id");
+  static base::NoDestructor<WebString> kRole("role");
+  static base::NoDestructor<WebString> kPlaceholder("placeholder");
+  static base::NoDestructor<WebString> kClass("class");
 
   // Save both id and name attributes, if present. If there is only one of them,
   // it will be saved to |name|. See HTMLFormControlElement::nameForAutofill.
   field->name = element.NameForAutofill().Utf16();
-  base::string16 id = element.GetAttribute(kId).Utf16();
+  base::string16 id = element.GetAttribute(*kId).Utf16();
   if (id != field->name)
     field->id = id;
 
   field->unique_renderer_id = element.UniqueRendererFormControlId();
   field->form_control_type = element.FormControlTypeForAutofill().Utf8();
-  field->autocomplete_attribute = element.GetAttribute(kAutocomplete).Utf8();
+  field->autocomplete_attribute = element.GetAttribute(*kAutocomplete).Utf8();
   if (field->autocomplete_attribute.size() > kMaxDataLength) {
     // Discard overly long attribute values to avoid DOS-ing the browser
     // process.  However, send over a default string to indicate that the
     // attribute was present.
     field->autocomplete_attribute = "x-max-data-length-exceeded";
   }
-  if (base::LowerCaseEqualsASCII(element.GetAttribute(kRole).Utf16(),
+  if (base::LowerCaseEqualsASCII(element.GetAttribute(*kRole).Utf16(),
                                  "presentation"))
     field->role = FormFieldData::ROLE_ATTRIBUTE_PRESENTATION;
 
-  field->placeholder = element.GetAttribute(kPlaceholder).Utf16();
-  if (element.HasAttribute(kClass))
-    field->css_classes = element.GetAttribute(kClass).Utf16();
+  field->placeholder = element.GetAttribute(*kPlaceholder).Utf16();
+  if (element.HasAttribute(*kClass))
+    field->css_classes = element.GetAttribute(*kClass).Utf16();
 
   if (field_data_manager &&
       field_data_manager->HasFieldData(element.UniqueRendererFormControlId())) {
@@ -1723,13 +1725,13 @@
 
   // Since it's not a checkout flow, only add fields that have a non-"off"
   // autocomplete attribute to the formless autofill.
-  CR_DEFINE_STATIC_LOCAL(WebString, kOffAttribute, ("off"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kFalseAttribute, ("false"));
+  static base::NoDestructor<WebString> kOffAttribute("off");
+  static base::NoDestructor<WebString> kFalseAttribute("false");
   std::vector<WebFormControlElement> elements_with_autocomplete;
   for (const WebFormControlElement& element : control_elements) {
     blink::WebString autocomplete = element.GetAttribute("autocomplete");
-    if (autocomplete.length() && autocomplete != kOffAttribute &&
-        autocomplete != kFalseAttribute) {
+    if (autocomplete.length() && autocomplete != *kOffAttribute &&
+        autocomplete != *kFalseAttribute) {
       elements_with_autocomplete.push_back(element);
     }
   }
@@ -1919,9 +1921,9 @@
 }
 
 bool IsWebElementEmpty(const blink::WebElement& root) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kScript, ("script"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kMeta, ("meta"));
-  CR_DEFINE_STATIC_LOCAL(WebString, kTitle, ("title"));
+  static base::NoDestructor<WebString> kScript("script");
+  static base::NoDestructor<WebString> kMeta("meta");
+  static base::NoDestructor<WebString> kTitle("title");
 
   if (root.IsNull())
     return true;
@@ -1936,8 +1938,8 @@
       continue;
 
     WebElement element = child.To<WebElement>();
-    if (!element.HasHTMLTagName(kScript) && !element.HasHTMLTagName(kMeta) &&
-        !element.HasHTMLTagName(kTitle))
+    if (!element.HasHTMLTagName(*kScript) && !element.HasHTMLTagName(*kMeta) &&
+        !element.HasHTMLTagName(*kTitle))
       return false;
   }
   return true;
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 732c9cc0..95f4b04 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -571,7 +571,7 @@
 
 // Returns true iff there is a password field in |frame|.
 bool HasPasswordField(const WebLocalFrame& frame) {
-  CR_DEFINE_STATIC_LOCAL(WebString, kPassword, ("password"));
+  static base::NoDestructor<WebString> kPassword("password");
 
   const WebElementCollection elements = frame.GetDocument().All();
   for (WebElement element = elements.FirstItem(); !element.IsNull();
@@ -579,7 +579,7 @@
     if (element.IsFormControlElement()) {
       const WebFormControlElement& control =
           element.To<WebFormControlElement>();
-      if (control.FormControlTypeForAutofill() == kPassword)
+      if (control.FormControlTypeForAutofill() == *kPassword)
         return true;
     }
   }
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index 55e2bb6f..5c131169 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -809,9 +809,9 @@
   for (const blink::WebFormControlElement& element : web_control_elements) {
     // We're only interested in the presence
     // of <input type="hidden" /> elements.
-    CR_DEFINE_STATIC_LOCAL(WebString, kHidden, ("hidden"));
+    static base::NoDestructor<WebString> kHidden("hidden");
     const blink::WebInputElement* input = blink::ToWebInputElement(&element);
-    if (!input || input->FormControlTypeForAutofill() != kHidden)
+    if (!input || input->FormControlTypeForAutofill() != *kHidden)
       continue;
 
     // There must be a hidden input named "rart".
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn
index 2376f29..d9d69ae 100644
--- a/components/autofill/core/browser/BUILD.gn
+++ b/components/autofill/core/browser/BUILD.gn
@@ -80,6 +80,8 @@
     "autofill_type.h",
     "autofill_wallet_data_type_controller.cc",
     "autofill_wallet_data_type_controller.h",
+    "autofill_wallet_model_type_controller.cc",
+    "autofill_wallet_model_type_controller.h",
     "card_unmask_delegate.cc",
     "card_unmask_delegate.h",
     "contact_info.cc",
diff --git a/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc b/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
index a6836d1..a25d1d3 100644
--- a/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
+++ b/components/autofill/core/browser/autofill_credit_card_filling_infobar_delegate_mobile.cc
@@ -6,6 +6,7 @@
 
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/common/autofill_constants.h"
+#include "components/autofill/core/common/autofill_features.h"
 #include "components/grit/components_scaled_resources.h"
 #include "components/infobars/core/infobar_delegate.h"
 #include "components/strings/grit/components_strings.h"
@@ -27,7 +28,9 @@
 #else
       card_label_(base::string16(kMidlineEllipsis) + card.LastFourDigits()),
 #endif
-      card_sub_label_(card.AbbreviatedExpirationDateForDisplay()) {
+      card_sub_label_(card.AbbreviatedExpirationDateForDisplay(
+          !features::
+              IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled())) {
 }
 
 AutofillCreditCardFillingInfoBarDelegateMobile::
diff --git a/components/autofill/core/browser/autofill_merge_unittest.cc b/components/autofill/core/browser/autofill_merge_unittest.cc
index cbbc5c1..6f83de7 100644
--- a/components/autofill/core/browser/autofill_merge_unittest.cc
+++ b/components/autofill/core/browser/autofill_merge_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
+#include "base/no_destructor.h"
 #include "base/path_service.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -55,14 +56,14 @@
                                               PHONE_HOME_WHOLE_NUMBER};
 
 const base::FilePath& GetTestDataDir() {
-  CR_DEFINE_STATIC_LOCAL(base::FilePath, dir, ());
-  if (dir.empty()) {
+  static base::NoDestructor<base::FilePath> dir([]() {
+    base::FilePath dir;
     base::PathService::Get(base::DIR_SOURCE_ROOT, &dir);
-    dir = dir.AppendASCII("components");
-    dir = dir.AppendASCII("test");
-    dir = dir.AppendASCII("data");
-  }
-  return dir;
+    return dir.AppendASCII("components")
+        .AppendASCII("test")
+        .AppendASCII("data");
+  }());
+  return *dir;
 }
 
 const std::vector<base::FilePath> GetTestFiles() {
diff --git a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
index 176ab5b8..63510585 100644
--- a/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
+++ b/components/autofill/core/browser/autofill_save_card_infobar_delegate_mobile.cc
@@ -41,7 +41,9 @@
       had_user_interaction_(false),
       issuer_icon_id_(CreditCard::IconResourceId(card.network())),
       card_label_(card.NetworkAndLastFourDigits()),
-      card_sub_label_(card.AbbreviatedExpirationDateForDisplay()) {
+      card_sub_label_(card.AbbreviatedExpirationDateForDisplay(
+          !features::
+              IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled())) {
   if (upload) {
     DCHECK(!upload_save_card_callback_.is_null());
     DCHECK(local_save_card_callback_.is_null());
diff --git a/components/autofill/core/browser/autofill_wallet_model_type_controller.cc b/components/autofill/core/browser/autofill_wallet_model_type_controller.cc
new file mode 100644
index 0000000..e042831
--- /dev/null
+++ b/components/autofill/core/browser/autofill_wallet_model_type_controller.cc
@@ -0,0 +1,87 @@
+// Copyright 2018 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 "components/autofill/core/browser/autofill_wallet_model_type_controller.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/prefs/pref_service.h"
+#include "components/sync/driver/sync_client.h"
+#include "components/sync/driver/sync_service.h"
+
+namespace browser_sync {
+
+AutofillWalletModelTypeController::AutofillWalletModelTypeController(
+    syncer::ModelType type,
+    std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+    syncer::SyncClient* sync_client)
+    : ModelTypeController(type, std::move(delegate_on_disk)),
+      sync_client_(sync_client) {
+  DCHECK(type == syncer::AUTOFILL_WALLET_DATA ||
+         type == syncer::AUTOFILL_WALLET_METADATA);
+  currently_enabled_ = IsEnabled();
+  SubscribeToPrefChanges();
+}
+
+AutofillWalletModelTypeController::AutofillWalletModelTypeController(
+    syncer::ModelType type,
+    std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+    std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory,
+    syncer::SyncClient* sync_client)
+    : ModelTypeController(type,
+                          std::move(delegate_on_disk),
+                          std::move(delegate_in_memory)),
+      sync_client_(sync_client) {
+  DCHECK(type == syncer::AUTOFILL_WALLET_DATA ||
+         type == syncer::AUTOFILL_WALLET_METADATA);
+  currently_enabled_ = IsEnabled();
+  SubscribeToPrefChanges();
+}
+
+AutofillWalletModelTypeController::~AutofillWalletModelTypeController() {}
+
+bool AutofillWalletModelTypeController::ReadyForStart() const {
+  DCHECK(CalledOnValidThread());
+  return currently_enabled_;
+}
+
+void AutofillWalletModelTypeController::OnUserPrefChanged() {
+  DCHECK(CalledOnValidThread());
+
+  bool newly_enabled = IsEnabled();
+  if (currently_enabled_ == newly_enabled) {
+    return;  // No change to sync state.
+  }
+  currently_enabled_ = newly_enabled;
+
+  syncer::SyncService* sync_service = sync_client_->GetSyncService();
+  sync_service->ReadyForStartChanged(type());
+}
+
+bool AutofillWalletModelTypeController::IsEnabled() const {
+  DCHECK(CalledOnValidThread());
+
+  // Require two user-visible prefs to be enabled to sync Wallet data/metadata.
+  return sync_client_->GetPrefService()->GetBoolean(
+             autofill::prefs::kAutofillWalletImportEnabled) &&
+         sync_client_->GetPrefService()->GetBoolean(
+             autofill::prefs::kAutofillCreditCardEnabled);
+}
+
+void AutofillWalletModelTypeController::SubscribeToPrefChanges() {
+  pref_registrar_.Init(sync_client_->GetPrefService());
+  pref_registrar_.Add(
+      autofill::prefs::kAutofillWalletImportEnabled,
+      base::BindRepeating(&AutofillWalletModelTypeController::OnUserPrefChanged,
+                          base::Unretained(this)));
+  pref_registrar_.Add(
+      autofill::prefs::kAutofillCreditCardEnabled,
+      base::BindRepeating(&AutofillWalletModelTypeController::OnUserPrefChanged,
+                          base::Unretained(this)));
+}
+
+}  // namespace browser_sync
diff --git a/components/autofill/core/browser/autofill_wallet_model_type_controller.h b/components/autofill/core/browser/autofill_wallet_model_type_controller.h
new file mode 100644
index 0000000..5d0feac
--- /dev/null
+++ b/components/autofill/core/browser/autofill_wallet_model_type_controller.h
@@ -0,0 +1,58 @@
+// Copyright 2018 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 COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_MODEL_TYPE_CONTROLLER_H_
+#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_MODEL_TYPE_CONTROLLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "components/sync/driver/model_type_controller.h"
+
+namespace syncer {
+class SyncClient;
+}
+
+namespace browser_sync {
+
+// Controls syncing of AUTOFILL_WALLET_DATA and AUTOFILL_WALLET_METADATA.
+class AutofillWalletModelTypeController : public syncer::ModelTypeController {
+ public:
+  // The delegates and |sync_client| must not be null. Furthermore,
+  // |sync_client| must outlive this object.
+  AutofillWalletModelTypeController(
+      syncer::ModelType type,
+      std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+      syncer::SyncClient* sync_client);
+  AutofillWalletModelTypeController(
+      syncer::ModelType type,
+      std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_on_disk,
+      std::unique_ptr<syncer::ModelTypeControllerDelegate> delegate_in_memory,
+      syncer::SyncClient* sync_client);
+  ~AutofillWalletModelTypeController() override;
+
+  // DataTypeController overrides.
+  bool ReadyForStart() const override;
+
+ private:
+  // Callback for changes to the autofill pref.
+  void OnUserPrefChanged();
+
+  bool IsEnabled() const;
+  void SubscribeToPrefChanges();
+
+  syncer::SyncClient* const sync_client_;
+
+  PrefChangeRegistrar pref_registrar_;
+
+  bool currently_enabled_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutofillWalletModelTypeController);
+};
+
+}  // namespace browser_sync
+
+#endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_WALLET_MODEL_TYPE_CONTROLLER_H_
diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc
index 0a4a2894..ec045366 100644
--- a/components/autofill/core/browser/credit_card.cc
+++ b/components/autofill/core/browser/credit_card.cc
@@ -832,16 +832,16 @@
       GetInfo(AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale));
 }
 
-base::string16 CreditCard::AbbreviatedExpirationDateForDisplay() const {
+base::string16 CreditCard::AbbreviatedExpirationDateForDisplay(
+    bool with_prefix) const {
   base::string16 month = ExpirationMonthAsString();
   base::string16 year = Expiration2DigitYearAsString();
   if (month.empty() || year.empty())
     return base::string16();
 
   return l10n_util::GetStringFUTF16(
-      features::IsAutofillSaveCardDialogUnlabeledExpirationDateEnabled()
-          ? IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR_V2
-          : IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR,
+      with_prefix ? IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR
+                  : IDS_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE_ABBR_V2,
       month, year);
 }
 
diff --git a/components/autofill/core/browser/credit_card.h b/components/autofill/core/browser/credit_card.h
index 815d788..570be5e 100644
--- a/components/autofill/core/browser/credit_card.h
+++ b/components/autofill/core/browser/credit_card.h
@@ -265,8 +265,9 @@
   // uses a two line layout and the credit card number is selected.
   base::string16 DescriptiveExpiration(const std::string& app_locale) const;
 
-  // Localized expiration for this card formatted as 'Exp: 06/17'.
-  base::string16 AbbreviatedExpirationDateForDisplay() const;
+  // Localized expiration for this card formatted as 'Exp: 06/17' if with_prefix
+  // is true or as '06/17' otherwise.
+  base::string16 AbbreviatedExpirationDateForDisplay(bool with_prefix) const;
   // Formatted expiration date (e.g., 05/2020).
   base::string16 ExpirationDateForDisplay() const;
   // Expiration functions.
diff --git a/components/autofill/ios/browser/BUILD.gn b/components/autofill/ios/browser/BUILD.gn
index 4ee64dc..ce62b325 100644
--- a/components/autofill/ios/browser/BUILD.gn
+++ b/components/autofill/ios/browser/BUILD.gn
@@ -84,6 +84,7 @@
     "//components/autofill/core/browser:test_support",
     "//components/prefs",
     "//ios/web/public",
+    "//ios/web/public/test",
     "//ios/web/public/test/fakes",
     "//testing/gmock",
     "//testing/gtest",
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm
index bee156c5..077e66ad 100644
--- a/components/autofill/ios/browser/autofill_agent.mm
+++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -549,11 +549,26 @@
 - (void)webState:(web::WebState*)webState
     frameDidBecomeAvailable:(web::WebFrame*)web_frame {
   DCHECK(web_frame);
-  if (![self isAutofillEnabled] ||
-      !autofill::switches::IsAutofillIFrameMessagingEnabled() ||
-      webState->IsLoading())
+  if (![self isAutofillEnabled] || webState->IsLoading()) {
     return;
-
+  }
+  if (web_frame->IsMainFrame()) {
+    [self processPage:webState];
+    return;
+  }
+  if (!autofill::switches::IsAutofillIFrameMessagingEnabled()) {
+    // iFrame support is disabled.
+    return;
+  }
+  // Check that the main frame has already been processed.
+  if (!web::GetMainWebFrame(webState)) {
+    return;
+  }
+  if (!autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+           webState, web::GetMainWebFrame(webState))
+           ->is_processed()) {
+    return;
+  }
   [self processFrame:web_frame inWebState:webState];
 }
 
@@ -586,10 +601,16 @@
   web::WebFramesManager* framesManager =
       web::WebFramesManager::FromWebState(webState);
   DCHECK(framesManager);
-  if (!autofill::switches::IsAutofillIFrameMessagingEnabled()) {
+  if (!framesManager->GetMainWebFrame()) {
+    return;
+  }
+  [self processFrame:framesManager->GetMainWebFrame() inWebState:webState];
+  if (autofill::switches::IsAutofillIFrameMessagingEnabled()) {
     [self processFrame:framesManager->GetMainWebFrame() inWebState:webState];
-  } else {
     for (auto* frame : framesManager->GetAllWebFrames()) {
+      if (frame->IsMainFrame()) {
+        continue;
+      }
       [self processFrame:frame inWebState:webState];
     }
   }
diff --git a/components/autofill/ios/browser/autofill_agent_unittests.mm b/components/autofill/ios/browser/autofill_agent_unittests.mm
index 633664cd..0137c69 100644
--- a/components/autofill/ios/browser/autofill_agent_unittests.mm
+++ b/components/autofill/ios/browser/autofill_agent_unittests.mm
@@ -9,14 +9,18 @@
 #include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/autofill_test_utils.h"
 #include "components/autofill/core/browser/popup_item_ids.h"
+#include "components/autofill/core/browser/test_autofill_client.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/form_data.h"
+#include "components/autofill/ios/browser/autofill_driver_ios.h"
 #import "components/autofill/ios/browser/js_autofill_manager.h"
 #include "components/prefs/pref_service.h"
 #include "ios/web/public/features.h"
 #include "ios/web/public/test/fakes/fake_web_frame.h"
+#include "ios/web/public/test/fakes/test_browser_state.h"
 #import "ios/web/public/test/fakes/test_web_state.h"
+#include "ios/web/public/test/test_web_thread_bundle.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
 #include "ios/web/public/web_state/web_frame_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -35,6 +39,28 @@
 using autofill::POPUP_ITEM_ID_GOOGLE_PAY_BRANDING;
 using base::test::ios::WaitUntilCondition;
 
+// Subclass of web::FakeWebFrame that allow to set a callback before any
+// JavaScript call. This callback can be used to check the state of the page.
+class FakeWebFrameCallback : public web::FakeWebFrame {
+ public:
+  FakeWebFrameCallback(const std::string& frame_id,
+                       bool is_main_frame,
+                       GURL security_origin,
+                       std::function<void()> callback)
+      : web::FakeWebFrame(frame_id, is_main_frame, security_origin),
+        callback_(callback) {}
+
+  bool CallJavaScriptFunction(
+      const std::string& name,
+      const std::vector<base::Value>& parameters) override {
+    callback_();
+    return web::FakeWebFrame::CallJavaScriptFunction(name, parameters);
+  }
+
+ private:
+  std::function<void()> callback_;
+};
+
 // Test fixture for AutofillAgent testing.
 class AutofillAgentTests : public PlatformTest {
  public:
@@ -46,6 +72,7 @@
     // Mock CRWJSInjectionReceiver for verifying interactions.
     mock_js_injection_receiver_ =
         [OCMockObject mockForClass:[CRWJSInjectionReceiver class]];
+    test_web_state_.SetBrowserState(&test_browser_state_);
     test_web_state_.SetJSInjectionReceiver(mock_js_injection_receiver_);
     test_web_state_.SetContentIsHTML(true);
     GURL url("https://example.com");
@@ -68,8 +95,11 @@
     PlatformTest::TearDown();
   }
 
+  web::TestWebThreadBundle thread_bundle_;
+  web::TestBrowserState test_browser_state_;
   web::TestWebState test_web_state_;
   web::FakeWebFrame* fake_main_frame_ = nullptr;
+  autofill::TestAutofillClient client_;
   std::unique_ptr<PrefService> prefs_;
   AutofillAgent* autofill_agent_;
   id mock_js_injection_receiver_;
@@ -568,3 +598,194 @@
   EXPECT_EQ(123, completion_handler_suggestions[2].identifier);
   EXPECT_EQ(321, completion_handler_suggestions[3].identifier);
 }
+
+// Test that main frame is processed whatever is the order of pageloading
+// callbacks.
+TEST_F(AutofillAgentTests, FrameInitializationOrder) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  std::vector<base::Feature> enabled_features;
+  std::vector<base::Feature> disabled_features;
+  disabled_features.push_back(
+      autofill::features::kAutofillEnableIFrameSupportOniOS);
+  disabled_features.push_back(web::features::kWebFrameMessaging);
+  scoped_feature_list.InitWithFeatures(enabled_features, disabled_features);
+
+  std::string locale("en");
+  autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
+      &test_web_state_, &client_, nil, locale,
+      autofill::AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
+
+  test_web_state_.RemoveWebFrame(fake_main_frame_->GetFrameId());
+
+  // Add frame when page is loading.
+  auto main_frame_unique =
+      std::make_unique<web::FakeWebFrame>("main", true, GURL());
+  web::FakeWebFrame* main_frame = main_frame_unique.get();
+  autofill::AutofillDriverIOS* main_frame_driver =
+      autofill::AutofillDriverIOS::FromWebStateAndWebFrame(&test_web_state_,
+                                                           main_frame);
+  test_web_state_.SetLoading(true);
+  test_web_state_.AddWebFrame(std::move(main_frame_unique));
+  EXPECT_FALSE(main_frame_driver->is_processed());
+  test_web_state_.SetLoading(false);
+  // Toggle mutations.
+  [[mock_js_injection_receiver_ expect] executeJavaScript:[OCMArg any]
+                                        completionHandler:[OCMArg any]];
+  // Toggle user edited field.
+  [[mock_js_injection_receiver_ expect] executeJavaScript:[OCMArg any]
+                                        completionHandler:[OCMArg any]];
+  // Extract Forms
+  [[mock_js_injection_receiver_ expect] executeJavaScript:[OCMArg any]
+                                        completionHandler:[OCMArg any]];
+
+  test_web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  test_web_state_.RemoveWebFrame(main_frame->GetFrameId());
+  // Driver is in the WebState, so reset it manually.
+  main_frame_driver->set_processed(false);
+
+  // Add frame when page is loaded.
+  main_frame_unique = std::make_unique<web::FakeWebFrame>("main", true, GURL());
+  main_frame = main_frame_unique.get();
+  main_frame_driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+      &test_web_state_, main_frame);
+  test_web_state_.SetLoading(false);
+  test_web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
+  EXPECT_FALSE(main_frame_driver->is_processed());
+  // Toggle mutations.
+  [[mock_js_injection_receiver_ expect] executeJavaScript:[OCMArg any]
+                                        completionHandler:[OCMArg any]];
+  // Toggle user edited field.
+  [[mock_js_injection_receiver_ expect] executeJavaScript:[OCMArg any]
+                                        completionHandler:[OCMArg any]];
+  // Extract Forms
+  [[mock_js_injection_receiver_ expect] executeJavaScript:[OCMArg any]
+                                        completionHandler:[OCMArg any]];
+  test_web_state_.AddWebFrame(std::move(main_frame_unique));
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  test_web_state_.RemoveWebFrame(main_frame->GetFrameId());
+}
+
+// Test that every frames are processed whatever is the order of pageloading
+// callbacks. The main frame should always be processed first.
+TEST_F(AutofillAgentTests, FrameInitializationOrderFrames) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  std::vector<base::Feature> enabled_features;
+  std::vector<base::Feature> disabled_features;
+  enabled_features.push_back(
+      autofill::features::kAutofillEnableIFrameSupportOniOS);
+  enabled_features.push_back(web::features::kWebFrameMessaging);
+  scoped_feature_list.InitWithFeatures(enabled_features, disabled_features);
+
+  std::string locale("en");
+  autofill::AutofillDriverIOS::PrepareForWebStateWebFrameAndDelegate(
+      &test_web_state_, &client_, nil, locale,
+      autofill::AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
+  // Remove the current main frame
+  test_web_state_.RemoveWebFrame(fake_main_frame_->GetFrameId());
+
+  // Both frames available, then page loaded.
+  auto main_frame_unique =
+      std::make_unique<web::FakeWebFrame>("main", true, GURL());
+  web::FakeWebFrame* main_frame = main_frame_unique.get();
+  autofill::AutofillDriverIOS* main_frame_driver =
+      autofill::AutofillDriverIOS::FromWebStateAndWebFrame(&test_web_state_,
+                                                           main_frame);
+  auto iframe_unique = std::make_unique<FakeWebFrameCallback>(
+      "iframe", false, GURL(), [main_frame_driver]() {
+        EXPECT_TRUE(main_frame_driver->is_processed());
+      });
+  FakeWebFrameCallback* iframe = iframe_unique.get();
+  autofill::AutofillDriverIOS* iframe_driver =
+      autofill::AutofillDriverIOS::FromWebStateAndWebFrame(&test_web_state_,
+                                                           iframe);
+  test_web_state_.SetLoading(true);
+  test_web_state_.AddWebFrame(std::move(main_frame_unique));
+  test_web_state_.AddWebFrame(std::move(iframe_unique));
+  EXPECT_FALSE(main_frame_driver->is_processed());
+  EXPECT_FALSE(iframe_driver->is_processed());
+  test_web_state_.SetLoading(false);
+  test_web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  EXPECT_TRUE(iframe_driver->is_processed());
+  test_web_state_.RemoveWebFrame(main_frame->GetFrameId());
+  test_web_state_.RemoveWebFrame(iframe->GetFrameId());
+
+  // Main frame available, then page loaded, then iframe available
+  main_frame_unique = std::make_unique<web::FakeWebFrame>("main", true, GURL());
+  main_frame = main_frame_unique.get();
+  main_frame_driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+      &test_web_state_, main_frame);
+  iframe_unique = std::make_unique<FakeWebFrameCallback>(
+      "iframe", false, GURL(), [main_frame_driver]() {
+        EXPECT_TRUE(main_frame_driver->is_processed());
+      });
+  iframe = iframe_unique.get();
+  iframe_driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+      &test_web_state_, iframe);
+  test_web_state_.SetLoading(true);
+  test_web_state_.AddWebFrame(std::move(main_frame_unique));
+  EXPECT_FALSE(main_frame_driver->is_processed());
+  EXPECT_FALSE(iframe_driver->is_processed());
+  test_web_state_.SetLoading(false);
+  test_web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  EXPECT_FALSE(iframe_driver->is_processed());
+  test_web_state_.AddWebFrame(std::move(iframe_unique));
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  EXPECT_TRUE(iframe_driver->is_processed());
+  test_web_state_.RemoveWebFrame(main_frame->GetFrameId());
+  test_web_state_.RemoveWebFrame(iframe->GetFrameId());
+
+  // Page loaded, then main frame, then iframe
+  main_frame_unique = std::make_unique<web::FakeWebFrame>("main", true, GURL());
+  main_frame = main_frame_unique.get();
+  main_frame_driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+      &test_web_state_, main_frame);
+  iframe_unique = std::make_unique<FakeWebFrameCallback>(
+      "iframe", false, GURL(), [main_frame_driver]() {
+        EXPECT_TRUE(main_frame_driver->is_processed());
+      });
+  iframe = iframe_unique.get();
+  iframe_driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+      &test_web_state_, iframe);
+  test_web_state_.SetLoading(true);
+  test_web_state_.SetLoading(false);
+  test_web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
+  EXPECT_FALSE(main_frame_driver->is_processed());
+  EXPECT_FALSE(iframe_driver->is_processed());
+  test_web_state_.AddWebFrame(std::move(main_frame_unique));
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  EXPECT_FALSE(iframe_driver->is_processed());
+  test_web_state_.AddWebFrame(std::move(iframe_unique));
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  EXPECT_TRUE(iframe_driver->is_processed());
+  test_web_state_.RemoveWebFrame(main_frame->GetFrameId());
+  test_web_state_.RemoveWebFrame(iframe->GetFrameId());
+
+  // Page loaded, then iframe, then main frame
+  main_frame_unique = std::make_unique<web::FakeWebFrame>("main", true, GURL());
+  main_frame = main_frame_unique.get();
+  main_frame_driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+      &test_web_state_, main_frame);
+  iframe_unique = std::make_unique<FakeWebFrameCallback>(
+      "iframe", false, GURL(), [main_frame_driver]() {
+        EXPECT_TRUE(main_frame_driver->is_processed());
+      });
+  iframe = iframe_unique.get();
+  iframe_driver = autofill::AutofillDriverIOS::FromWebStateAndWebFrame(
+      &test_web_state_, iframe);
+  test_web_state_.SetLoading(true);
+  test_web_state_.SetLoading(false);
+  test_web_state_.OnPageLoaded(web::PageLoadCompletionStatus::SUCCESS);
+  EXPECT_FALSE(main_frame_driver->is_processed());
+  EXPECT_FALSE(iframe_driver->is_processed());
+  test_web_state_.AddWebFrame(std::move(iframe_unique));
+  EXPECT_FALSE(main_frame_driver->is_processed());
+  EXPECT_FALSE(iframe_driver->is_processed());
+  test_web_state_.AddWebFrame(std::move(main_frame_unique));
+  EXPECT_TRUE(main_frame_driver->is_processed());
+  EXPECT_TRUE(iframe_driver->is_processed());
+  test_web_state_.RemoveWebFrame(main_frame->GetFrameId());
+  test_web_state_.RemoveWebFrame(iframe->GetFrameId());
+}
diff --git a/components/autofill_assistant/browser/script_precondition.cc b/components/autofill_assistant/browser/script_precondition.cc
index f85785c..68948ea8 100644
--- a/components/autofill_assistant/browser/script_precondition.cc
+++ b/components/autofill_assistant/browser/script_precondition.cc
@@ -162,10 +162,14 @@
     bool has_same_status = status_match.status() == status;
     switch (status_match.comparator()) {
       case ScriptStatusMatchProto::DIFFERENT:
-        return !has_same_status;
+        if (has_same_status)
+          return false;
+        break;
       case ScriptStatusMatchProto::EQUAL:
       default:
-        return has_same_status;
+        if (!has_same_status)
+          return false;
+        break;
     }
   }
   return true;
diff --git a/components/autofill_assistant/browser/script_precondition_unittest.cc b/components/autofill_assistant/browser/script_precondition_unittest.cc
index 44c37d6..bc9da25 100644
--- a/components/autofill_assistant/browser/script_precondition_unittest.cc
+++ b/components/autofill_assistant/browser/script_precondition_unittest.cc
@@ -223,6 +223,24 @@
   EXPECT_FALSE(Check(proto));
 }
 
+TEST_F(ScriptPreconditionTest, MultipleScriptStatus) {
+  ScriptPreconditionProto proto;
+
+  ScriptStatusMatchProto* previous1 = proto.add_script_status_match();
+  previous1->set_script("previous1");
+  previous1->set_comparator(ScriptStatusMatchProto::EQUAL);
+  previous1->set_status(SCRIPT_STATUS_SUCCESS);
+
+  ScriptStatusMatchProto* previous2 = proto.add_script_status_match();
+  previous2->set_script("previous2");
+  previous2->set_comparator(ScriptStatusMatchProto::DIFFERENT);
+  previous2->set_status(SCRIPT_STATUS_NOT_RUN);
+
+  executed_scripts_["previous1"] = SCRIPT_STATUS_SUCCESS;
+
+  EXPECT_FALSE(Check(proto));
+}
+
 TEST_F(ScriptPreconditionTest, ParameterMustExist) {
   ScriptPreconditionProto proto;
   ScriptParameterMatchProto* match = proto.add_script_parameter_match();
diff --git a/components/bookmarks/browser/bookmark_codec_unittest.cc b/components/bookmarks/browser/bookmark_codec_unittest.cc
index 8040fd6..4accc279 100644
--- a/components/bookmarks/browser/bookmark_codec_unittest.cc
+++ b/components/bookmarks/browser/bookmark_codec_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_string_value_serializer.h"
+#include "base/no_destructor.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -38,14 +39,14 @@
 const char kFolder2Title[] = "folder2";
 
 const base::FilePath& GetTestDataDir() {
-  CR_DEFINE_STATIC_LOCAL(base::FilePath, dir, ());
-  if (dir.empty()) {
+  static base::NoDestructor<base::FilePath> dir([]() {
+    base::FilePath dir;
     base::PathService::Get(base::DIR_SOURCE_ROOT, &dir);
-    dir = dir.AppendASCII("components");
-    dir = dir.AppendASCII("test");
-    dir = dir.AppendASCII("data");
-  }
-  return dir;
+    return dir.AppendASCII("components")
+        .AppendASCII("test")
+        .AppendASCII("data");
+  }());
+  return *dir;
 }
 
 // Helper to get a mutable bookmark node.
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index 1beceded..8ecda1ec 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -11,6 +11,7 @@
 #include "base/single_thread_task_runner.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_wallet_data_type_controller.h"
+#include "components/autofill/core/browser/autofill_wallet_model_type_controller.h"
 #include "components/autofill/core/browser/webdata/autocomplete_sync_bridge.h"
 #include "components/autofill/core/browser/webdata/autofill_profile_data_type_controller.h"
 #include "components/autofill/core/browser/webdata/autofill_profile_sync_bridge.h"
@@ -177,7 +178,7 @@
     if (!wallet_disabled) {
       if (base::FeatureList::IsEnabled(switches::kSyncUSSAutofillWalletData)) {
         controllers.push_back(
-            CreateWebDataModelTypeControllerWithInMemorySupport(
+            CreateWalletModelTypeControllerWithInMemorySupport(
                 syncer::AUTOFILL_WALLET_DATA,
                 base::BindRepeating(&AutofillWalletDelegateFromDataService)));
       } else {
@@ -194,7 +195,7 @@
         !disabled_types.Has(syncer::AUTOFILL_WALLET_METADATA)) {
       if (base::FeatureList::IsEnabled(
               switches::kSyncUSSAutofillWalletMetadata)) {
-        controllers.push_back(CreateWebDataModelTypeController(
+        controllers.push_back(CreateWalletModelTypeController(
             syncer::AUTOFILL_WALLET_METADATA,
             base::BindRepeating(
                 &AutofillWalletMetadataDelegateFromDataService)));
@@ -486,13 +487,28 @@
                                 base::RetainedRef(web_data_service_on_disk_))));
 }
 
+std::unique_ptr<ModelTypeController>
+ProfileSyncComponentsFactoryImpl::CreateWalletModelTypeController(
+    syncer::ModelType type,
+    const base::RepeatingCallback<
+        base::WeakPtr<syncer::ModelTypeControllerDelegate>(
+            autofill::AutofillWebDataService*)>& delegate_from_web_data) {
+  return std::make_unique<AutofillWalletModelTypeController>(
+      type,
+      std::make_unique<syncer::ProxyModelTypeControllerDelegate>(
+          db_thread_,
+          base::BindRepeating(delegate_from_web_data,
+                              base::RetainedRef(web_data_service_on_disk_))),
+      sync_client_);
+}
+
 std::unique_ptr<ModelTypeController> ProfileSyncComponentsFactoryImpl::
-    CreateWebDataModelTypeControllerWithInMemorySupport(
+    CreateWalletModelTypeControllerWithInMemorySupport(
         syncer::ModelType type,
         const base::RepeatingCallback<
             base::WeakPtr<syncer::ModelTypeControllerDelegate>(
                 autofill::AutofillWebDataService*)>& delegate_from_web_data) {
-  return std::make_unique<ModelTypeController>(
+  return std::make_unique<AutofillWalletModelTypeController>(
       type, /*delegate_on_disk=*/
       std::make_unique<syncer::ProxyModelTypeControllerDelegate>(
           db_thread_,
@@ -502,7 +518,8 @@
       std::make_unique<syncer::ProxyModelTypeControllerDelegate>(
           db_thread_,
           base::BindRepeating(delegate_from_web_data,
-                              base::RetainedRef(web_data_service_in_memory_))));
+                              base::RetainedRef(web_data_service_in_memory_))),
+      sync_client_);
 }
 
 }  // namespace browser_sync
diff --git a/components/browser_sync/profile_sync_components_factory_impl.h b/components/browser_sync/profile_sync_components_factory_impl.h
index 79f3fe98..c81266ba 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.h
+++ b/components/browser_sync/profile_sync_components_factory_impl.h
@@ -87,7 +87,7 @@
   std::unique_ptr<syncer::ModelTypeController>
   CreateModelTypeControllerForModelRunningOnUIThread(syncer::ModelType type);
 
-  // Factory function for ModelTypeController instnaces for autofill-related
+  // Factory function for ModelTypeController instances for autofill-related
   // datatypes, which live in |db_thread_| and have a delegate accesible via
   // AutofillWebDataService.
   std::unique_ptr<syncer::ModelTypeController> CreateWebDataModelTypeController(
@@ -95,11 +95,17 @@
       const base::RepeatingCallback<
           base::WeakPtr<syncer::ModelTypeControllerDelegate>(
               autofill::AutofillWebDataService*)>& delegate_from_web_data);
-  // Same as above, but for datatypes supporting STORAGE_IN_MEMORY implemented
-  // as an independent AutofillWebDataService,
-  // namely |web_data_service_in_memory_|.
+  // Same as above, but for AUTOFILL_WALLET_* datatypes.
+  std::unique_ptr<syncer::ModelTypeController> CreateWalletModelTypeController(
+      syncer::ModelType type,
+      const base::RepeatingCallback<
+          base::WeakPtr<syncer::ModelTypeControllerDelegate>(
+              autofill::AutofillWebDataService*)>& delegate_from_web_data);
+  // Same as above, but datatypes supporting STORAGE_IN_MEMORY implemented
+  // as an independent AutofillWebDataService, namely
+  // |web_data_service_in_memory_|.
   std::unique_ptr<syncer::ModelTypeController>
-  CreateWebDataModelTypeControllerWithInMemorySupport(
+  CreateWalletModelTypeControllerWithInMemorySupport(
       syncer::ModelType type,
       const base::RepeatingCallback<
           base::WeakPtr<syncer::ModelTypeControllerDelegate>(
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 6130462a..f837eaf 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -901,6 +901,13 @@
   data_type_manager_->ReenableType(type);
 }
 
+void ProfileSyncService::ReadyForStartChanged(syncer::ModelType type) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  if (!engine_initialized_ || !data_type_manager_)
+    return;
+  data_type_manager_->ReadyForStartChanged(type);
+}
+
 void ProfileSyncService::UpdateEngineInitUMA(bool success) const {
   if (is_first_time_sync_configure_) {
     UMA_HISTOGRAM_BOOLEAN("Sync.BackendInitializeFirstTimeSuccess", success);
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 05d1160cb..c49bd41 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -263,6 +263,7 @@
       const syncer::BaseTransaction* trans) const override;
   syncer::UserShare* GetUserShare() const override;
   void ReenableDatatype(syncer::ModelType type) override;
+  void ReadyForStartChanged(syncer::ModelType type) override;
   syncer::SyncTokenStatus GetSyncTokenStatus() const override;
   bool QueryDetailedSyncStatus(syncer::SyncStatus* result) const override;
   base::Time GetLastSyncedTime() const override;
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc
index d1aae4ef..883427f 100644
--- a/components/browser_sync/profile_sync_service_unittest.cc
+++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -59,6 +59,7 @@
   }
 
   void ReenableType(syncer::ModelType type) override {}
+  void ReadyForStartChanged(syncer::ModelType type) override {}
   void ResetDataTypeErrors() override {}
   void PurgeForMigration(syncer::ModelTypeSet undesired_types) override {}
   void Stop(syncer::ShutdownReason reason) override {}
diff --git a/components/browsing_data/core/browsing_data_utils.cc b/components/browsing_data/core/browsing_data_utils.cc
index 63c6bea..fd5232b 100644
--- a/components/browsing_data/core/browsing_data_utils.cc
+++ b/components/browsing_data/core/browsing_data_utils.cc
@@ -7,6 +7,7 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
+#include "base/no_destructor.h"
 #include "components/browsing_data/core/counters/autofill_counter.h"
 #include "components/browsing_data/core/counters/history_counter.h"
 #include "components/browsing_data/core/counters/passwords_counter.h"
@@ -300,28 +301,25 @@
 BrowsingDataType GetDataTypeFromDeletionPreference(
     const std::string& pref_name) {
   using DataTypeMap = base::flat_map<std::string, BrowsingDataType>;
-  CR_DEFINE_STATIC_LOCAL(
-      DataTypeMap, preference_to_datatype,
-      (
-          {
-              {prefs::kDeleteBrowsingHistory, BrowsingDataType::HISTORY},
-              {prefs::kDeleteBrowsingHistoryBasic, BrowsingDataType::HISTORY},
-              {prefs::kDeleteCache, BrowsingDataType::CACHE},
-              {prefs::kDeleteCacheBasic, BrowsingDataType::CACHE},
-              {prefs::kDeleteCookies, BrowsingDataType::COOKIES},
-              {prefs::kDeleteCookiesBasic, BrowsingDataType::COOKIES},
-              {prefs::kDeletePasswords, BrowsingDataType::PASSWORDS},
-              {prefs::kDeleteFormData, BrowsingDataType::FORM_DATA},
-              {prefs::kDeleteSiteSettings, BrowsingDataType::SITE_SETTINGS},
-              {prefs::kDeleteDownloadHistory, BrowsingDataType::DOWNLOADS},
-              {prefs::kDeleteMediaLicenses, BrowsingDataType::MEDIA_LICENSES},
-              {prefs::kDeleteHostedAppsData,
-               BrowsingDataType::HOSTED_APPS_DATA},
-          },
-          base::KEEP_FIRST_OF_DUPES));
+  static base::NoDestructor<DataTypeMap> preference_to_datatype(
+      std::initializer_list<DataTypeMap::value_type>{
+          {prefs::kDeleteBrowsingHistory, BrowsingDataType::HISTORY},
+          {prefs::kDeleteBrowsingHistoryBasic, BrowsingDataType::HISTORY},
+          {prefs::kDeleteCache, BrowsingDataType::CACHE},
+          {prefs::kDeleteCacheBasic, BrowsingDataType::CACHE},
+          {prefs::kDeleteCookies, BrowsingDataType::COOKIES},
+          {prefs::kDeleteCookiesBasic, BrowsingDataType::COOKIES},
+          {prefs::kDeletePasswords, BrowsingDataType::PASSWORDS},
+          {prefs::kDeleteFormData, BrowsingDataType::FORM_DATA},
+          {prefs::kDeleteSiteSettings, BrowsingDataType::SITE_SETTINGS},
+          {prefs::kDeleteDownloadHistory, BrowsingDataType::DOWNLOADS},
+          {prefs::kDeleteMediaLicenses, BrowsingDataType::MEDIA_LICENSES},
+          {prefs::kDeleteHostedAppsData, BrowsingDataType::HOSTED_APPS_DATA},
+      },
+      base::KEEP_FIRST_OF_DUPES);
 
-  auto iter = preference_to_datatype.find(pref_name);
-  DCHECK(iter != preference_to_datatype.end());
+  auto iter = preference_to_datatype->find(pref_name);
+  DCHECK(iter != preference_to_datatype->end());
   return iter->second;
 }
 
diff --git a/components/data_reduction_proxy/content/browser/BUILD.gn b/components/data_reduction_proxy/content/browser/BUILD.gn
index 8960d16..997a9fd 100644
--- a/components/data_reduction_proxy/content/browser/BUILD.gn
+++ b/components/data_reduction_proxy/content/browser/BUILD.gn
@@ -17,7 +17,6 @@
   deps = [
     "//base",
     "//components/crash/content/browser",
-    "//components/data_reduction_proxy/content/common",
     "//components/data_reduction_proxy/core/browser",
     "//components/data_reduction_proxy/core/common",
     "//components/data_use_measurement/core",
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
index 267a958..cc538a5d 100644
--- a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
+++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
@@ -10,7 +10,6 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "components/data_reduction_proxy/content/common/header_util.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
@@ -63,10 +62,58 @@
   if (!request_info)
     return;
 
+  // Previews only operate on HTTP.
+  if (!request.url().SchemeIs("http"))
+    return;
+
+  // Chrome-Proxy-Accept-Transform takes at most one token.
+  if (headers->HasHeader(chrome_proxy_accept_transform_header()))
+    return;
+
   content::ResourceType resource_type = request_info->GetResourceType();
+
+  if (resource_type == content::RESOURCE_TYPE_MEDIA) {
+    headers->SetHeader(chrome_proxy_accept_transform_header(),
+                       compressed_video_directive());
+    return;
+  }
+
   content::PreviewsState previews_state = request_info->GetPreviewsState();
-  ::data_reduction_proxy::MaybeSetAcceptTransformHeader(
-      request.url(), resource_type, previews_state, headers);
+
+  // Do not add the Chrome-Proxy-Accept-Transform header when the page load
+  // explicitly forbids previews transformations.
+  if (previews_state & content::PREVIEWS_NO_TRANSFORM ||
+      previews_state & content::PREVIEWS_OFF) {
+    return;
+  }
+
+  std::string accept_transform_value;
+  if ((previews_state & content::SERVER_LITE_PAGE_ON) &&
+      resource_type == content::RESOURCE_TYPE_MAIN_FRAME) {
+    accept_transform_value = lite_page_directive();
+  } else if ((previews_state & content::SERVER_LOFI_ON)) {
+    // Note that for subresource requests, the Lo-Fi bit should only be set
+    // if the main frame response provided the "empty-image" directive (for
+    // the client to echo back to the server here for any image resources).
+    // Also, it should only be set for subresource requests that might be
+    // image requests.
+    bool resource_type_supports_empty_image =
+        !(resource_type == content::RESOURCE_TYPE_MAIN_FRAME ||
+          resource_type == content::RESOURCE_TYPE_STYLESHEET ||
+          resource_type == content::RESOURCE_TYPE_SCRIPT ||
+          resource_type == content::RESOURCE_TYPE_FONT_RESOURCE ||
+          resource_type == content::RESOURCE_TYPE_MEDIA ||
+          resource_type == content::RESOURCE_TYPE_CSP_REPORT);
+    if (resource_type_supports_empty_image) {
+      accept_transform_value = empty_image_directive();
+    }
+  }
+
+  if (accept_transform_value.empty())
+    return;
+
+  headers->SetHeader(chrome_proxy_accept_transform_header(),
+                     accept_transform_value);
 }
 
 void ContentLoFiDecider::RemoveAcceptTransformHeader(
diff --git a/components/data_reduction_proxy/content/common/BUILD.gn b/components/data_reduction_proxy/content/common/BUILD.gn
deleted file mode 100644
index ad50648..0000000
--- a/components/data_reduction_proxy/content/common/BUILD.gn
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2018 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.
-
-static_library("common") {
-  sources = [
-    "data_reduction_proxy_url_loader_throttle.cc",
-    "data_reduction_proxy_url_loader_throttle.h",
-    "header_util.cc",
-    "header_util.h",
-  ]
-
-  deps = [
-    "//components/data_reduction_proxy/core/common",
-    "//content/public/common",
-    "//net",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-  sources = [
-    "data_reduction_proxy_url_loader_throttle_unittest.cc",
-    "header_util_unittest.cc",
-  ]
-
-  deps = [
-    ":common",
-    "//components/data_reduction_proxy/core/common",
-    "//content/public/common",
-    "//net",
-    "//testing/gtest",
-  ]
-}
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
deleted file mode 100644
index 7eea6d0..0000000
--- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 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 "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h"
-
-#include "components/data_reduction_proxy/content/common/header_util.h"
-
-namespace net {
-class HttpRequestHeaders;
-}
-
-namespace data_reduction_proxy {
-
-DataReductionProxyURLLoaderThrottle::DataReductionProxyURLLoaderThrottle(
-    const net::HttpRequestHeaders& post_cache_headers)
-    : post_cache_headers_(post_cache_headers) {}
-
-DataReductionProxyURLLoaderThrottle::~DataReductionProxyURLLoaderThrottle() {}
-
-void DataReductionProxyURLLoaderThrottle::DetachFromCurrentSequence() {}
-
-void DataReductionProxyURLLoaderThrottle::WillStartRequest(
-    network::ResourceRequest* request,
-    bool* defer) {
-  MaybeSetAcceptTransformHeader(
-      request->url, static_cast<content::ResourceType>(request->resource_type),
-      request->previews_state, &request->custom_proxy_pre_cache_headers);
-  request->custom_proxy_post_cache_headers = post_cache_headers_;
-}
-
-}  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
deleted file mode 100644
index f50b3d4..0000000
--- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2018 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 COMPONENTS_DATA_REDUCTION_PROXY_CONTENT_COMMON_DATA_REDUCTION_PROXY_URL_LOADER_THROTTLE_H_
-#define COMPONENTS_DATA_REDUCTION_PROXY_CONTENT_COMMON_DATA_REDUCTION_PROXY_URL_LOADER_THROTTLE_H_
-
-#include "content/public/common/url_loader_throttle.h"
-
-namespace data_reduction_proxy {
-
-// Handles Data Reduction Proxy logic that needs to be applied to each request,
-// e.g. setting headers to be used with the proxy.
-class DataReductionProxyURLLoaderThrottle : public content::URLLoaderThrottle {
- public:
-  explicit DataReductionProxyURLLoaderThrottle(
-      const net::HttpRequestHeaders& post_cache_headers);
-  ~DataReductionProxyURLLoaderThrottle() override;
-
-  // content::URLLoaderThrottle:
-  void DetachFromCurrentSequence() override;
-  void WillStartRequest(network::ResourceRequest* request,
-                        bool* defer) override;
-
- private:
-  net::HttpRequestHeaders post_cache_headers_;
-};
-
-}  // namespace data_reduction_proxy
-
-#endif  // COMPONENTS_DATA_REDUCTION_PROXY_CONTENT_COMMON_DATA_REDUCTION_PROXY_URL_LOADER_THROTTLE_H_
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc
deleted file mode 100644
index f6a8bc7..0000000
--- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle_unittest.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2018 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 "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h"
-
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
-#include "content/public/common/previews_state.h"
-#include "net/http/http_request_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace data_reduction_proxy {
-
-TEST(DataReductionProxyURLLoaderThrottleTest, AcceptTransformHeaderSet) {
-  DataReductionProxyURLLoaderThrottle throttle((net::HttpRequestHeaders()));
-  network::ResourceRequest request;
-  request.url = GURL("http://example.com");
-  request.resource_type = content::RESOURCE_TYPE_MEDIA;
-  bool defer = false;
-
-  throttle.WillStartRequest(&request, &defer);
-
-  EXPECT_FALSE(defer);
-  std::string value;
-  EXPECT_TRUE(request.custom_proxy_pre_cache_headers.GetHeader(
-      chrome_proxy_accept_transform_header(), &value));
-  EXPECT_EQ(value, compressed_video_directive());
-}
-
-TEST(DataReductionProxyURLLoaderThrottleTest,
-     AcceptTransformHeaderSetForMainFrame) {
-  DataReductionProxyURLLoaderThrottle throttle((net::HttpRequestHeaders()));
-  network::ResourceRequest request;
-  request.url = GURL("http://example.com");
-  request.resource_type = content::RESOURCE_TYPE_MAIN_FRAME;
-  request.previews_state = content::SERVER_LITE_PAGE_ON;
-  bool defer = false;
-
-  throttle.WillStartRequest(&request, &defer);
-
-  EXPECT_FALSE(defer);
-  std::string value;
-  EXPECT_TRUE(request.custom_proxy_pre_cache_headers.GetHeader(
-      chrome_proxy_accept_transform_header(), &value));
-  EXPECT_EQ(value, lite_page_directive());
-}
-
-TEST(DataReductionProxyURLLoaderThrottleTest,
-     ConstructorHeadersAddedToPostCacheHeaders) {
-  net::HttpRequestHeaders headers;
-  headers.SetHeader("foo", "bar");
-  DataReductionProxyURLLoaderThrottle throttle(headers);
-  network::ResourceRequest request;
-  request.url = GURL("http://example.com");
-  bool defer = false;
-
-  throttle.WillStartRequest(&request, &defer);
-
-  EXPECT_FALSE(defer);
-  std::string value;
-  EXPECT_TRUE(request.custom_proxy_post_cache_headers.GetHeader("foo", &value));
-  EXPECT_EQ(value, "bar");
-}
-
-}  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/content/common/header_util.cc b/components/data_reduction_proxy/content/common/header_util.cc
deleted file mode 100644
index b26bdd5..0000000
--- a/components/data_reduction_proxy/content/common/header_util.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2018 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 "components/data_reduction_proxy/content/common/header_util.h"
-
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
-#include "net/http/http_request_headers.h"
-#include "url/gurl.h"
-
-namespace data_reduction_proxy {
-
-void MaybeSetAcceptTransformHeader(const GURL& url,
-                                   content::ResourceType resource_type,
-                                   content::PreviewsState previews_state,
-                                   net::HttpRequestHeaders* headers) {
-  // Previews only operate on HTTP.
-  if (!url.SchemeIs("http"))
-    return;
-
-  // Chrome-Proxy-Accept-Transform takes at most one token.
-  if (headers->HasHeader(chrome_proxy_accept_transform_header()))
-    return;
-
-  if (resource_type == content::RESOURCE_TYPE_MEDIA) {
-    headers->SetHeader(chrome_proxy_accept_transform_header(),
-                       compressed_video_directive());
-    return;
-  }
-
-  // Do not add the Chrome-Proxy-Accept-Transform header when the page load
-  // explicitly forbids previews transformations.
-  if (previews_state & content::PREVIEWS_NO_TRANSFORM ||
-      previews_state & content::PREVIEWS_OFF) {
-    return;
-  }
-
-  std::string accept_transform_value;
-  if ((previews_state & content::SERVER_LITE_PAGE_ON) &&
-      resource_type == content::RESOURCE_TYPE_MAIN_FRAME) {
-    accept_transform_value = lite_page_directive();
-  } else if ((previews_state & content::SERVER_LOFI_ON)) {
-    // Note that for subresource requests, the Lo-Fi bit should only be set
-    // if the main frame response provided the "empty-image" directive (for
-    // the client to echo back to the server here for any image resources).
-    // Also, it should only be set for subresource requests that might be
-    // image requests.
-    bool resource_type_supports_empty_image =
-        !(resource_type == content::RESOURCE_TYPE_MAIN_FRAME ||
-          resource_type == content::RESOURCE_TYPE_STYLESHEET ||
-          resource_type == content::RESOURCE_TYPE_SCRIPT ||
-          resource_type == content::RESOURCE_TYPE_FONT_RESOURCE ||
-          resource_type == content::RESOURCE_TYPE_MEDIA ||
-          resource_type == content::RESOURCE_TYPE_CSP_REPORT);
-    if (resource_type_supports_empty_image) {
-      accept_transform_value = empty_image_directive();
-    }
-  }
-
-  if (accept_transform_value.empty())
-    return;
-
-  headers->SetHeader(chrome_proxy_accept_transform_header(),
-                     accept_transform_value);
-}
-
-}  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/content/common/header_util.h b/components/data_reduction_proxy/content/common/header_util.h
deleted file mode 100644
index 7ed0bae..0000000
--- a/components/data_reduction_proxy/content/common/header_util.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2018 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 COMPONENTS_DATA_REDUCTION_PROXY_CONTENT_COMMON_HEADER_UTIL_H_
-#define COMPONENTS_DATA_REDUCTION_PROXY_CONTENT_COMMON_HEADER_UTIL_H_
-
-#include "content/public/common/previews_state.h"
-#include "content/public/common/resource_type.h"
-
-class GURL;
-
-namespace net {
-class HttpRequestHeaders;
-}
-
-namespace data_reduction_proxy {
-
-// Adds a previews-specific directive to the Chrome-Proxy-Accept-Transform
-// header if needed.
-void MaybeSetAcceptTransformHeader(const GURL& url,
-                                   content::ResourceType resource_type,
-                                   content::PreviewsState previews_state,
-                                   net::HttpRequestHeaders* headers);
-
-}  // namespace data_reduction_proxy
-
-#endif  // COMPONENTS_DATA_REDUCTION_PROXY_CONTENT_COMMON_HEADER_UTIL_H_
diff --git a/components/data_reduction_proxy/content/common/header_util_unittest.cc b/components/data_reduction_proxy/content/common/header_util_unittest.cc
deleted file mode 100644
index 8aee9f53..0000000
--- a/components/data_reduction_proxy/content/common/header_util_unittest.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2018 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 "components/data_reduction_proxy/content/common/header_util.h"
-
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
-#include "content/public/common/previews_state.h"
-#include "net/http/http_request_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace data_reduction_proxy {
-namespace {
-
-constexpr char kUrl[] = "http://example.com";
-constexpr char kHttpsUrl[] = "https://example.com";
-
-}  // namespace
-
-TEST(HeaderUtilTest, MaybeSetAcceptTransformHeader) {
-  const struct {
-    GURL url;
-    content::ResourceType resource_type;
-    content::PreviewsState previews_state;
-    std::string expected_header;
-  } tests[] = {
-      {GURL(kUrl), content::RESOURCE_TYPE_MEDIA, 0,
-       compressed_video_directive()},
-      {GURL(kHttpsUrl), content::RESOURCE_TYPE_MEDIA, 0, ""},
-      {GURL(kUrl), content::RESOURCE_TYPE_MAIN_FRAME,
-       content::SERVER_LITE_PAGE_ON, lite_page_directive()},
-      {GURL(kUrl), content::RESOURCE_TYPE_SUB_FRAME, content::SERVER_LOFI_ON,
-       empty_image_directive()},
-      {GURL(kUrl), content::RESOURCE_TYPE_SUB_FRAME, 0, ""},
-      {GURL(kUrl), content::RESOURCE_TYPE_SCRIPT, content::SERVER_LOFI_ON, ""},
-  };
-
-  for (const auto& test : tests) {
-    net::HttpRequestHeaders headers;
-    MaybeSetAcceptTransformHeader(test.url, test.resource_type,
-                                  test.previews_state, &headers);
-
-    std::string value;
-    EXPECT_EQ(headers.GetHeader(chrome_proxy_accept_transform_header(), &value),
-              !test.expected_header.empty());
-    EXPECT_EQ(value, test.expected_header);
-  }
-}
-
-}  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc
index c39da909..93cd04c2 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.cc
@@ -42,8 +42,6 @@
       net_log_, network_properties_manager.IsSecureProxyDisallowedByCarrier(),
       DataReductionProxyServer::ConvertToNetProxyServers(proxies_for_http));
   config_ = config;
-  if (config_updated_callback_)
-    config_updated_callback_.Run();
 }
 
 net::ProxyConfig DataReductionProxyConfigurator::CreateProxyConfig(
@@ -112,8 +110,6 @@
   net::ProxyConfig config = net::ProxyConfig::CreateDirect();
   data_reduction_proxy_event_creator_->AddProxyDisabledEvent(net_log_);
   config_ = config;
-  if (config_updated_callback_)
-    config_updated_callback_.Run();
 }
 
 void DataReductionProxyConfigurator::SetBypassRules(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h
index 471fabc..7a1a8dd 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "base/callback.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
@@ -65,11 +64,6 @@
       const NetworkPropertiesManager& network_properties_manager,
       const std::vector<DataReductionProxyServer>& proxies_for_http) const;
 
-  void SetConfigUpdatedCallback(
-      base::RepeatingClosure config_updated_callback) {
-    config_updated_callback_ = config_updated_callback;
-  }
-
  private:
   FRIEND_TEST_ALL_PREFIXES(DataReductionProxyConfiguratorTest, TestBypassList);
 
@@ -85,8 +79,6 @@
   net::NetLog* net_log_;
   DataReductionProxyEventCreator* data_reduction_proxy_event_creator_;
 
-  base::RepeatingClosure config_updated_callback_;
-
   // Enforce usage on the IO thread.
   base::ThreadChecker thread_checker_;
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
index d392e8b..879d3660 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -122,8 +122,6 @@
   event_creator_.reset(new DataReductionProxyEventCreator(this));
   configurator_.reset(
       new DataReductionProxyConfigurator(net_log, event_creator_.get()));
-  configurator_->SetConfigUpdatedCallback(base::BindRepeating(
-      &DataReductionProxyIOData::OnProxyConfigUpdated, base::Unretained(this)));
   DataReductionProxyMutableConfigValues* raw_mutable_config = nullptr;
     std::unique_ptr<DataReductionProxyMutableConfigValues> mutable_config =
         std::make_unique<DataReductionProxyMutableConfigValues>();
@@ -461,34 +459,12 @@
       FROM_HERE,
       base::BindOnce(&DataReductionProxyService::SetProxyRequestHeadersOnUI,
                      service_, std::move(headers)));
-  OnProxyConfigUpdated();
-}
-
-void DataReductionProxyIOData::OnProxyConfigUpdated() {
-  if (!proxy_config_client_)
-    return;
-
-  auto config = network::mojom::CustomProxyConfig::New();
-  config->rules = configurator_->GetProxyConfig().proxy_rules();
-
-  net::EffectiveConnectionType type = GetEffectiveConnectionType();
-  if (type > net::EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
-    DCHECK_NE(net::EFFECTIVE_CONNECTION_TYPE_LAST, type);
-    config->pre_cache_headers.SetHeader(
-        chrome_proxy_ect_header(),
-        net::GetNameForEffectiveConnectionType(type));
-  }
-
-  request_options_->AddRequestHeader(&config->post_cache_headers,
-                                     base::nullopt);
-  proxy_config_client_->OnCustomProxyConfigUpdated(std::move(config));
 }
 
 void DataReductionProxyIOData::OnEffectiveConnectionTypeChanged(
     net::EffectiveConnectionType type) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   effective_connection_type_ = type;
-  OnProxyConfigUpdated();
 }
 
 void DataReductionProxyIOData::OnRTTOrThroughputEstimatesComputed(
@@ -503,10 +479,4 @@
   return effective_connection_type_;
 }
 
-void DataReductionProxyIOData::SetCustomProxyConfigClient(
-    network::mojom::CustomProxyConfigClientPtrInfo config_client_info) {
-  proxy_config_client_.Bind(std::move(config_client_info));
-  OnProxyConfigUpdated();
-}
-
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
index f89c9e48..ba85b72 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
@@ -26,7 +26,6 @@
 #include "components/data_reduction_proxy/core/common/lofi_ui_service.h"
 #include "components/data_reduction_proxy/core/common/resource_type_provider.h"
 #include "components/data_use_measurement/core/data_use_user_data.h"
-#include "services/network/public/mojom/network_context.mojom.h"
 
 namespace base {
 class Value;
@@ -152,8 +151,6 @@
   // Forwards proxy authentication headers to the UI thread.
   void UpdateProxyRequestHeaders(const net::HttpRequestHeaders& headers);
 
-  void OnProxyConfigUpdated();
-
   // Notifies |this| that there there is a change in the effective connection
   // type.
   void OnEffectiveConnectionTypeChanged(net::EffectiveConnectionType type);
@@ -164,11 +161,6 @@
   // Returns the current estimate of the effective connection type.
   net::EffectiveConnectionType GetEffectiveConnectionType() const;
 
-  // Binds to a config client that can be used to update Data Reduction Proxy
-  // settings when the network service is enabled.
-  void SetCustomProxyConfigClient(
-      network::mojom::CustomProxyConfigClientPtrInfo config_client_info);
-
   // Various accessor methods.
   DataReductionProxyConfigurator* configurator() const {
     return configurator_.get();
@@ -341,8 +333,6 @@
   // Current estimate of the effective connection type.
   net::EffectiveConnectionType effective_connection_type_;
 
-  network::mojom::CustomProxyConfigClientPtr proxy_config_client_;
-
   base::WeakPtrFactory<DataReductionProxyIOData> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DataReductionProxyIOData);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index 0d96a67..43e1538 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -13,16 +13,13 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
-#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
-#include "components/data_reduction_proxy/core/browser/network_properties_manager.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_server.h"
-#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
 #include "net/http/http_network_session.h"
@@ -36,7 +33,6 @@
 #include "net/url_request/url_request_interceptor.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/network/test/test_network_connection_tracker.h"
-#include "services/network/test/test_network_quality_tracker.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -217,136 +213,4 @@
                    .is_direct());
 }
 
-class TestCustomProxyConfigClient
-    : public network::mojom::CustomProxyConfigClient {
- public:
-  TestCustomProxyConfigClient(
-      network::mojom::CustomProxyConfigClientRequest request)
-      : binding_(this, std::move(request)) {}
-
-  // network::mojom::CustomProxyConfigClient implementation:
-  void OnCustomProxyConfigUpdated(
-      network::mojom::CustomProxyConfigPtr proxy_config) override {
-    config = std::move(proxy_config);
-  }
-
-  network::mojom::CustomProxyConfigPtr config;
-
- private:
-  mojo::Binding<network::mojom::CustomProxyConfigClient> binding_;
-};
-
-TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigClient) {
-  auto proxy_server = net::ProxyServer::FromPacString("PROXY foo");
-  base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-      switches::kDataReductionProxyHttpProxies, proxy_server.ToURI());
-
-  net::TestURLRequestContext context(false);
-  std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
-      DataReductionProxyTestContext::Builder()
-          .WithURLRequestContext(&context)
-          .Build();
-  drp_test_context->SetDataReductionProxyEnabled(true);
-  drp_test_context->test_network_quality_tracker()
-      ->ReportEffectiveConnectionTypeForTesting(
-          net::EFFECTIVE_CONNECTION_TYPE_4G);
-  DataReductionProxyIOData* io_data = drp_test_context->io_data();
-
-  network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
-  TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
-  io_data->SetCustomProxyConfigClient(std::move(client_ptr_info));
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server);
-  EXPECT_TRUE(
-      client.config->post_cache_headers.HasHeader(chrome_proxy_header()));
-  EXPECT_TRUE(
-      client.config->pre_cache_headers.HasHeader(chrome_proxy_ect_header()));
-}
-
-TEST_F(DataReductionProxyIODataTest, TestCustomProxyConfigUpdatedOnECTChange) {
-  net::TestURLRequestContext context(false);
-  std::unique_ptr<DataReductionProxyTestContext> drp_test_context =
-      DataReductionProxyTestContext::Builder()
-          .WithURLRequestContext(&context)
-          .Build();
-  drp_test_context->SetDataReductionProxyEnabled(true);
-  drp_test_context->test_network_quality_tracker()
-      ->ReportEffectiveConnectionTypeForTesting(
-          net::EFFECTIVE_CONNECTION_TYPE_4G);
-  DataReductionProxyIOData* io_data = drp_test_context->io_data();
-
-  network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
-  TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
-  io_data->SetCustomProxyConfigClient(std::move(client_ptr_info));
-  base::RunLoop().RunUntilIdle();
-
-  std::string value;
-  EXPECT_TRUE(client.config->pre_cache_headers.GetHeader(
-      chrome_proxy_ect_header(), &value));
-  EXPECT_EQ(value, "4G");
-
-  drp_test_context->test_network_quality_tracker()
-      ->ReportEffectiveConnectionTypeForTesting(
-          net::EFFECTIVE_CONNECTION_TYPE_2G);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(client.config->pre_cache_headers.GetHeader(
-      chrome_proxy_ect_header(), &value));
-  EXPECT_EQ(value, "2G");
-}
-
-TEST_F(DataReductionProxyIODataTest,
-       TestCustomProxyConfigUpdatedOnHeaderChange) {
-  DataReductionProxyIOData io_data(
-      Client::UNKNOWN, prefs(), net_log(),
-      network::TestNetworkConnectionTracker::GetInstance(),
-      scoped_task_environment_.GetMainThreadTaskRunner(),
-      scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
-      std::string() /* user_agent */, std::string() /* channel */);
-
-  network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
-  TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
-  io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
-  base::RunLoop().RunUntilIdle();
-
-  std::string value;
-  EXPECT_TRUE(client.config->post_cache_headers.GetHeader(chrome_proxy_header(),
-                                                          &value));
-
-  io_data.request_options()->SetSecureSession("session_value");
-  base::RunLoop().RunUntilIdle();
-  std::string changed_value;
-  EXPECT_TRUE(client.config->post_cache_headers.GetHeader(chrome_proxy_header(),
-                                                          &changed_value));
-  EXPECT_NE(value, changed_value);
-}
-
-TEST_F(DataReductionProxyIODataTest,
-       TestCustomProxyConfigUpdatedOnProxyChange) {
-  DataReductionProxyIOData io_data(
-      Client::UNKNOWN, prefs(), net_log(),
-      network::TestNetworkConnectionTracker::GetInstance(),
-      scoped_task_environment_.GetMainThreadTaskRunner(),
-      scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */,
-      std::string() /* user_agent */, std::string() /* channel */);
-  NetworkPropertiesManager network_properties_manager(
-      base::DefaultClock::GetInstance(), prefs(),
-      scoped_task_environment_.GetMainThreadTaskRunner());
-  auto proxy_server = net::ProxyServer::FromPacString("PROXY foo");
-  io_data.configurator()->Enable(
-      network_properties_manager,
-      {DataReductionProxyServer(proxy_server, ProxyServer_ProxyType_CORE)});
-
-  network::mojom::CustomProxyConfigClientPtrInfo client_ptr_info;
-  TestCustomProxyConfigClient client(mojo::MakeRequest(&client_ptr_info));
-  io_data.SetCustomProxyConfigClient(std::move(client_ptr_info));
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(client.config->rules.proxies_for_http.Get(), proxy_server);
-
-  io_data.configurator()->Disable();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(client.config->rules.proxies_for_http.IsEmpty());
-}
-
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
index fcaeffe..28d20e7 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
@@ -283,14 +283,6 @@
   settings_->SetIgnoreLongTermBlackListRules(ignore_long_term_black_list_rules);
 }
 
-void DataReductionProxyService::SetCustomProxyConfigClient(
-    network::mojom::CustomProxyConfigClientPtrInfo config_client_info) {
-  io_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&DataReductionProxyIOData::SetCustomProxyConfigClient,
-                     io_data_, std::move(config_client_info)));
-}
-
 void DataReductionProxyService::LoadHistoricalDataUsage(
     const HistoricalDataUsageCallback& load_data_usage_callback) {
   std::unique_ptr<std::vector<DataUsageBucket>> data_usage(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
index 12b7521..70bd015 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
@@ -155,11 +155,6 @@
   // Sends the given |headers| to |DataReductionProxySettings|.
   void SetProxyRequestHeadersOnUI(const net::HttpRequestHeaders& headers);
 
-  // Sets a config client that can be used to update Data Reduction Proxy
-  // settings when the network service is enabled.
-  void SetCustomProxyConfigClient(
-      network::mojom::CustomProxyConfigClientPtrInfo config_client_info);
-
   // Accessor methods.
   DataReductionProxyCompressionStats* compression_stats() const {
     return compression_stats_.get();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
index 752116c..ace43150 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
@@ -109,10 +109,6 @@
   // Technically, this is not "at startup", but this is the first chance that
   // IO data objects can be called.
   UpdateIOData(true);
-  if (proxy_config_client_) {
-    data_reduction_proxy_service_->SetCustomProxyConfigClient(
-        std::move(proxy_config_client_));
-  }
 }
 
 void DataReductionProxySettings::SetCallbackToRegisterSyntheticFieldTrial(
@@ -123,10 +119,9 @@
 }
 
 bool DataReductionProxySettings::IsDataReductionProxyEnabled() const {
-  if (base::FeatureList::IsEnabled(network::features::kNetworkService) &&
-      !params::IsEnabledWithNetworkService()) {
+  // TODO(crbug.com/721403): Make DRP work with network service.
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService))
     return false;
-  }
 
   if (spdy_proxy_auth_enabled_.GetPrefName().empty())
     return false;
@@ -318,12 +313,6 @@
   return nullptr;
 }
 
-void DataReductionProxySettings::SetCustomProxyConfigClient(
-    network::mojom::CustomProxyConfigClientPtrInfo proxy_config_client) {
-  DCHECK(!data_reduction_proxy_service_);
-  proxy_config_client_ = std::move(proxy_config_client);
-}
-
 // Metrics methods
 void DataReductionProxySettings::RecordDataReductionInit() const {
   DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
index 9f448ecc05..a0289618 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
@@ -21,7 +21,6 @@
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service_observer.h"
 #include "components/prefs/pref_member.h"
 #include "net/http/http_request_headers.h"
-#include "services/network/public/mojom/network_context.mojom.h"
 #include "url/gurl.h"
 
 class PrefService;
@@ -174,11 +173,6 @@
   // InitDataReductionProxySettings has not been called.
   DataReductionProxyEventStore* GetEventStore() const;
 
-  // Sets a config client that can be used to update Data Reduction Proxy
-  // settings when the network service is enabled.
-  void SetCustomProxyConfigClient(
-      network::mojom::CustomProxyConfigClientPtrInfo proxy_config_client);
-
   DataReductionProxyService* data_reduction_proxy_service() {
     return data_reduction_proxy_service_.get();
   }
@@ -322,8 +316,6 @@
   // The headers to use for requests to the proxy server.
   net::HttpRequestHeaders proxy_request_headers_;
 
-  network::mojom::CustomProxyConfigClientPtrInfo proxy_config_client_;
-
   base::ThreadChecker thread_checker_;
 
   DISALLOW_COPY_AND_ASSIGN(DataReductionProxySettings);
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
index b1250224..e793bcf0 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
@@ -56,10 +56,5 @@
 const base::Feature kDataReductionProxyBrotliHoldback{
     "DataReductionProxyBrotliHoldback", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Enables data reduction proxy when network service is enabled.
-const base::Feature kDataReductionProxyEnabledWithNetworkService{
-    "DataReductionProxyEnabledWithNetworkService",
-    base::FEATURE_DISABLED_BY_DEFAULT};
-
 }  // namespace features
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h
index 6b035a9..3f2c48d 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.h
@@ -18,7 +18,6 @@
 extern const base::Feature kDogfood;
 extern const base::Feature kDataSaverSiteBreakdownUsingPageLoadMetrics;
 extern const base::Feature kDataReductionProxyBrotliHoldback;
-extern const base::Feature kDataReductionProxyEnabledWithNetworkService;
 
 }  // namespace features
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
index b5a83f3..aa7063f 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -22,7 +22,6 @@
 #include "net/base/host_port_pair.h"
 #include "net/base/proxy_server.h"
 #include "net/http/http_status_code.h"
-#include "services/network/public/cpp/features.h"
 #include "url/url_constants.h"
 
 #if defined(OS_ANDROID)
@@ -406,13 +405,6 @@
           kDataSaverSiteBreakdownUsingPageLoadMetrics);
 }
 
-bool IsEnabledWithNetworkService() {
-  return base::FeatureList::IsEnabled(
-             data_reduction_proxy::features::
-                 kDataReductionProxyEnabledWithNetworkService) &&
-         base::FeatureList::IsEnabled(network::features::kNetworkService);
-}
-
 base::Optional<DataReductionProxyTypeInfo> FindConfiguredProxyInVector(
     const std::vector<DataReductionProxyServer>& proxies,
     const net::ProxyServer& proxy_server) {
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
index 02153958..0ce2369 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -148,10 +148,6 @@
 // metrics harness.
 bool IsDataSaverSiteBreakdownUsingPLMEnabled();
 
-// Returns whether network service is enabled and data reduction proxy should be
-// used.
-bool IsEnabledWithNetworkService();
-
 // Returns the experiment parameter name to discard the cached result for canary
 // check probe.
 const char* GetDiscardCanaryCheckResultParam();
diff --git a/components/domain_reliability/quic_error_mapping.cc b/components/domain_reliability/quic_error_mapping.cc
index ccf9748..1aa9b24 100644
--- a/components/domain_reliability/quic_error_mapping.cc
+++ b/components/domain_reliability/quic_error_mapping.cc
@@ -292,6 +292,10 @@
     {quic::QUIC_INVALID_MESSAGE_DATA, "quic.invalid.message_data"},
     {quic::IETF_QUIC_PROTOCOL_VIOLATION, "quic.ietf.protocol_violation"},
     {quic::QUIC_INVALID_NEW_TOKEN, "quic.invalid_new_token"},
+    {quic::QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM,
+     "quic.data.received.on.write.unidirectional.stream"},
+    {quic::QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
+     "quic.try.to.write.data.on.read.unidirectional.stream"},
 
     // No error. Used as bound while iterating.
     {quic::QUIC_LAST_ERROR, "quic.last_error"}};
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc
index 5d0ad19..bd9010a 100644
--- a/components/download/content/internal/download_driver_impl.cc
+++ b/components/download/content/internal/download_driver_impl.cc
@@ -14,7 +14,6 @@
 #include "components/download/internal/background_service/driver_entry.h"
 #include "components/download/public/common/download_interrupt_reasons.h"
 #include "components/download/public/common/download_url_parameters.h"
-#include "content/public/browser/storage_partition.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
 
@@ -146,14 +145,8 @@
   if (!download_manager_)
     return;
 
-  content::StoragePartition* storage_partition =
-      content::BrowserContext::GetStoragePartitionForSite(
-          download_manager_->GetBrowserContext(), request_params.url);
-  DCHECK(storage_partition);
-
   std::unique_ptr<DownloadUrlParameters> download_url_params(
       new DownloadUrlParameters(request_params.url,
-                                storage_partition->GetURLRequestContext(),
                                 traffic_annotation));
 
   // TODO(xingliu): Make content::DownloadManager handle potential guid
diff --git a/components/download/internal/common/DEPS b/components/download/internal/common/DEPS
index 13ed39c..328cd26 100644
--- a/components/download/internal/common/DEPS
+++ b/components/download/internal/common/DEPS
@@ -19,6 +19,7 @@
   "+net/http/http_status_code.h",
   "+net/http/http_util.h",
   "+net/traffic_annotation/network_traffic_annotation.h",
+  "+net/url_request/url_request_context_getter.h",
   "+services/metrics/public/cpp",
   "+services/network/public/cpp",
   "+services/network/public/mojom",
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
index db1d6a89..559c71b 100644
--- a/components/download/internal/common/download_item_impl.cc
+++ b/components/download/internal/common/download_item_impl.cc
@@ -2345,7 +2345,7 @@
   // request will not be dropped if the WebContents (and by extension, the
   // associated renderer) goes away before a response is received.
   std::unique_ptr<DownloadUrlParameters> download_params(
-      new DownloadUrlParameters(GetURL(), nullptr, traffic_annotation));
+      new DownloadUrlParameters(GetURL(), traffic_annotation));
   download_params->set_file_path(GetFullPath());
   if (received_slices_.size() > 0) {
     std::vector<DownloadItem::ReceivedSlice> slices_to_download =
diff --git a/components/download/internal/common/download_job_factory.cc b/components/download/internal/common/download_job_factory.cc
index c9cffbeb..f3cea3ae 100644
--- a/components/download/internal/common/download_job_factory.cc
+++ b/components/download/internal/common/download_job_factory.cc
@@ -13,6 +13,7 @@
 #include "components/download/public/common/download_item.h"
 #include "components/download/public/common/download_stats.h"
 #include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "net/url_request/url_request_context_getter.h"
 
 namespace download {
 
diff --git a/components/download/internal/common/download_worker.cc b/components/download/internal/common/download_worker.cc
index b6f3aa5..c5fa6b4 100644
--- a/components/download/internal/common/download_worker.cc
+++ b/components/download/internal/common/download_worker.cc
@@ -12,6 +12,7 @@
 #include "components/download/public/common/download_utils.h"
 #include "components/download/public/common/input_stream.h"
 #include "components/download/public/common/url_download_handler_factory.h"
+#include "net/url_request/url_request_context_getter.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
@@ -45,10 +46,11 @@
     base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
     scoped_refptr<download::DownloadURLLoaderFactoryGetter>
         url_loader_factory_getter,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
   auto downloader = UrlDownloadHandlerFactory::Create(
       std::move(params), delegate, std::move(url_loader_factory_getter),
-      task_runner);
+      std::move(url_request_context_getter), task_runner);
   task_runner->PostTask(
       FROM_HERE,
       base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
@@ -76,11 +78,13 @@
 void DownloadWorker::SendRequest(
     std::unique_ptr<DownloadUrlParameters> params,
     scoped_refptr<download::DownloadURLLoaderFactoryGetter>
-        url_loader_factory_getter) {
+        url_loader_factory_getter,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
   GetIOTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&CreateUrlDownloadHandler, std::move(params),
                                 weak_factory_.GetWeakPtr(),
                                 std::move(url_loader_factory_getter),
+                                std::move(url_request_context_getter),
                                 base::ThreadTaskRunnerHandle::Get()));
 }
 
diff --git a/components/download/internal/common/download_worker.h b/components/download/internal/common/download_worker.h
index 8c71260..ec81471 100644
--- a/components/download/internal/common/download_worker.h
+++ b/components/download/internal/common/download_worker.h
@@ -8,12 +8,17 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "components/download/public/common/download_export.h"
 #include "components/download/public/common/download_request_handle_interface.h"
 #include "components/download/public/common/download_url_parameters.h"
 #include "components/download/public/common/url_download_handler.h"
 
+namespace net {
+class URLRequestContextGetter;
+}
+
 namespace download {
 class DownloadURLLoaderFactoryGetter;
 
@@ -44,9 +49,11 @@
   int64_t length() const { return length_; }
 
   // Send network request to ask for a download.
-  void SendRequest(std::unique_ptr<DownloadUrlParameters> params,
-                   scoped_refptr<download::DownloadURLLoaderFactoryGetter>
-                       url_loader_factory_getter);
+  void SendRequest(
+      std::unique_ptr<DownloadUrlParameters> params,
+      scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+          url_loader_factory_getter,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
 
   // Download operations.
   void Pause();
diff --git a/components/download/internal/common/parallel_download_job.cc b/components/download/internal/common/parallel_download_job.cc
index e72f9af..91612c25 100644
--- a/components/download/internal/common/parallel_download_job.cc
+++ b/components/download/internal/common/parallel_download_job.cc
@@ -14,6 +14,7 @@
 #include "components/download/public/common/download_stats.h"
 #include "components/download/public/common/download_url_loader_factory_getter.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_request_context_getter.h"
 
 namespace download {
 namespace {
@@ -273,7 +274,6 @@
   // The parallel requests only use GET method.
   std::unique_ptr<DownloadUrlParameters> download_params(
       new DownloadUrlParameters(download_item_->GetURL(),
-                                url_request_context_getter_.get(),
                                 traffic_annotation));
   download_params->set_file_path(download_item_->GetFullPath());
   download_params->set_last_modified(download_item_->GetLastModifiedTime());
@@ -293,7 +293,8 @@
   download_params->set_referrer_policy(net::URLRequest::NEVER_CLEAR_REFERRER);
 
   // Send the request.
-  worker->SendRequest(std::move(download_params), url_loader_factory_getter_);
+  worker->SendRequest(std::move(download_params), url_loader_factory_getter_,
+                      url_request_context_getter_);
   DCHECK(workers_.find(offset) == workers_.end());
   workers_[offset] = std::move(worker);
 }
diff --git a/components/download/internal/common/parallel_download_job.h b/components/download/internal/common/parallel_download_job.h
index a6803e2..1c79129 100644
--- a/components/download/internal/common/parallel_download_job.h
+++ b/components/download/internal/common/parallel_download_job.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/timer/timer.h"
 #include "components/download/internal/common/download_job_impl.h"
 #include "components/download/internal/common/download_worker.h"
diff --git a/components/download/internal/common/url_download_handler_factory.cc b/components/download/internal/common/url_download_handler_factory.cc
index 9a3a5f4..2b222df 100644
--- a/components/download/internal/common/url_download_handler_factory.cc
+++ b/components/download/internal/common/url_download_handler_factory.cc
@@ -10,6 +10,7 @@
 #include "components/download/public/common/download_item.h"
 #include "components/download/public/common/download_url_loader_factory_getter.h"
 #include "components/download/public/common/download_utils.h"
+#include "net/url_request/url_request_context_getter.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace download {
@@ -28,6 +29,7 @@
       base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
       scoped_refptr<download::DownloadURLLoaderFactoryGetter>
           url_loader_factory_getter,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override {
     std::unique_ptr<network::ResourceRequest> request =
         CreateResourceRequest(params.get());
@@ -61,13 +63,14 @@
     base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
     scoped_refptr<download::DownloadURLLoaderFactoryGetter>
         url_loader_factory_getter,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
   base::AutoLock auto_lock(GetURLDownloadHandlerFactoryLock());
   if (!g_url_download_handler_factory)
     g_url_download_handler_factory = new DefaultUrlDownloadHandlerFactory();
   return g_url_download_handler_factory->CreateUrlDownloadHandler(
       std::move(params), delegate, std::move(url_loader_factory_getter),
-      task_runner);
+      std::move(url_request_context_getter), task_runner);
 }
 
 // static
diff --git a/components/download/public/common/download_item_impl.h b/components/download/public/common/download_item_impl.h
index 4b3795e..01d9c4b 100644
--- a/components/download/public/common/download_item_impl.h
+++ b/components/download/public/common/download_item_impl.h
@@ -297,8 +297,6 @@
   // parameters. It may be different from the DownloadCreateInfo used to create
   // the DownloadItem if Start() is being called in response for a
   // download resumption request.
-  // TODO(qinmin): Remove |url_request_context_getter| once network service is
-  // enabled.
   virtual void Start(std::unique_ptr<DownloadFile> download_file,
                      std::unique_ptr<DownloadRequestHandleInterface> req_handle,
                      const DownloadCreateInfo& new_create_info,
diff --git a/components/download/public/common/download_url_parameters.cc b/components/download/public/common/download_url_parameters.cc
index 7e35514..67787e54 100644
--- a/components/download/public/common/download_url_parameters.cc
+++ b/components/download/public/common/download_url_parameters.cc
@@ -8,13 +8,11 @@
 
 DownloadUrlParameters::DownloadUrlParameters(
     const GURL& url,
-    net::URLRequestContextGetter* url_request_context_getter,
     const net::NetworkTrafficAnnotationTag& traffic_annotation)
     : DownloadUrlParameters(url,
                             -1,
                             -1,
                             -1,
-                            url_request_context_getter,
                             traffic_annotation) {}
 
 DownloadUrlParameters::DownloadUrlParameters(
@@ -22,7 +20,6 @@
     int render_process_host_id,
     int render_view_host_routing_id,
     int render_frame_host_routing_id,
-    net::URLRequestContextGetter* url_request_context_getter,
     const net::NetworkTrafficAnnotationTag& traffic_annotation)
     : content_initiated_(false),
       use_if_range_(true),
@@ -35,7 +32,6 @@
       render_process_host_id_(render_process_host_id),
       render_view_host_routing_id_(render_view_host_routing_id),
       render_frame_host_routing_id_(render_frame_host_routing_id),
-      url_request_context_getter_(url_request_context_getter),
       url_(url),
       do_not_prompt_for_login_(false),
       follow_cross_origin_redirects_(true),
diff --git a/components/download/public/common/download_url_parameters.h b/components/download/public/common/download_url_parameters.h
index d9f0455..db3ef01 100644
--- a/components/download/public/common/download_url_parameters.h
+++ b/components/download/public/common/download_url_parameters.h
@@ -14,14 +14,12 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "components/download/public/common/download_interrupt_reasons.h"
 #include "components/download/public/common/download_save_info.h"
 #include "components/download/public/common/download_source.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_request.h"
-#include "net/url_request/url_request_context_getter.h"
 #include "services/network/public/cpp/resource_request_body.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "url/gurl.h"
@@ -78,7 +76,6 @@
   // non-privileged frame.
   DownloadUrlParameters(
       const GURL& url,
-      net::URLRequestContextGetter* url_request_context_getter,
       const net::NetworkTrafficAnnotationTag& traffic_annotation);
 
   // The RenderView routing ID must correspond to the RenderView of the
@@ -89,7 +86,6 @@
       int render_process_host_id,
       int render_view_host_routing_id,
       int render_frame_host_routing_id,
-      net::URLRequestContextGetter* url_request_context_getter,
       const net::NetworkTrafficAnnotationTag& traffic_annotation);
 
   ~DownloadUrlParameters();
@@ -104,11 +100,6 @@
     request_headers_.push_back(make_pair(name, value));
   }
 
-  void set_url_request_context_getter(
-      net::URLRequestContextGetter* url_request_context_getter) {
-    url_request_context_getter_ = url_request_context_getter;
-  }
-
   // HTTP Referrer, referrer policy and encoding.
   void set_referrer(const GURL& referrer) { referrer_ = referrer; }
   void set_referrer_policy(net::URLRequest::ReferrerPolicy referrer_policy) {
@@ -276,9 +267,6 @@
   }
 
   const RequestHeadersType& request_headers() const { return request_headers_; }
-  net::URLRequestContextGetter* url_request_context_getter() {
-    return url_request_context_getter_.get();
-  }
   const base::FilePath& file_path() const { return save_info_.file_path; }
   const base::string16& suggested_name() const {
     return save_info_.suggested_name;
@@ -327,7 +315,6 @@
   int render_process_host_id_;
   int render_view_host_routing_id_;
   int render_frame_host_routing_id_;
-  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
   DownloadSaveInfo save_info_;
   GURL url_;
   bool do_not_prompt_for_login_;
diff --git a/components/download/public/common/url_download_handler_factory.h b/components/download/public/common/url_download_handler_factory.h
index c09c37a..4ba92f5 100644
--- a/components/download/public/common/url_download_handler_factory.h
+++ b/components/download/public/common/url_download_handler_factory.h
@@ -5,8 +5,13 @@
 #ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_FACTORY_H_
 #define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_URL_DOWNLOAD_HANDLER_FACTORY_H_
 
+#include "base/memory/ref_counted.h"
 #include "components/download/public/common/url_download_handler.h"
 
+namespace net {
+class URLRequestContextGetter;
+}
+
 namespace download {
 class DownloadURLLoaderFactoryGetter;
 class DownloadUrlParameters;
@@ -27,6 +32,7 @@
       base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
       scoped_refptr<download::DownloadURLLoaderFactoryGetter>
           url_loader_factory_getter,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
 
   virtual ~UrlDownloadHandlerFactory();
@@ -42,6 +48,7 @@
       base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
       scoped_refptr<download::DownloadURLLoaderFactoryGetter>
           url_loader_factory_getter,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) = 0;
 };
 
diff --git a/components/drive/file_system_core_util.cc b/components/drive/file_system_core_util.cc
index d14d3be..41854a5 100644
--- a/components/drive/file_system_core_util.cc
+++ b/components/drive/file_system_core_util.cc
@@ -18,6 +18,7 @@
 #include "base/i18n/icu_string_conversions.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/logging.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -66,24 +67,21 @@
 }  // namespace
 
 const base::FilePath& GetDriveGrandRootPath() {
-  CR_DEFINE_STATIC_LOCAL(
-      base::FilePath, grand_root_path,
-      (base::FilePath::FromUTF8Unsafe(kDriveGrandRootDirName)));
-  return grand_root_path;
+  static base::NoDestructor<base::FilePath> grand_root_path(
+      base::FilePath::FromUTF8Unsafe(kDriveGrandRootDirName));
+  return *grand_root_path;
 }
 
 const base::FilePath& GetDriveMyDriveRootPath() {
-  CR_DEFINE_STATIC_LOCAL(
-      base::FilePath, drive_root_path,
-      (GetDriveGrandRootPath().AppendASCII(kDriveMyDriveRootDirName)));
-  return drive_root_path;
+  static base::NoDestructor<base::FilePath> drive_root_path(
+      GetDriveGrandRootPath().AppendASCII(kDriveMyDriveRootDirName));
+  return *drive_root_path;
 }
 
 const base::FilePath& GetDriveTeamDrivesRootPath() {
-  CR_DEFINE_STATIC_LOCAL(
-      base::FilePath, team_drives_root_path,
-      (GetDriveGrandRootPath().AppendASCII(kDriveTeamDrivesDirName)));
-  return team_drives_root_path;
+  static base::NoDestructor<base::FilePath> team_drives_root_path(
+      GetDriveGrandRootPath().AppendASCII(kDriveTeamDrivesDirName));
+  return *team_drives_root_path;
 }
 
 bool IsTeamDrivesPath(const base::FilePath& file_path) {
diff --git a/components/exo/data_offer.cc b/components/exo/data_offer.cc
index 927f001d..e14bc9b 100644
--- a/components/exo/data_offer.cc
+++ b/components/exo/data_offer.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_util.h"
 #include "base/memory/ref_counted_memory.h"
+#include "base/no_destructor.h"
 #include "base/pickle.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
@@ -77,9 +78,9 @@
 
 ui::Clipboard::FormatType GetClipboardFormatType() {
   static const char kFormatString[] = "chromium/x-file-system-files";
-  CR_DEFINE_STATIC_LOCAL(ui::Clipboard::FormatType, format_type,
-                         (ui::Clipboard::GetFormatType(kFormatString)));
-  return format_type;
+  static base::NoDestructor<ui::Clipboard::FormatType> format_type(
+      ui::Clipboard::GetFormatType(kFormatString));
+  return *format_type;
 }
 
 }  // namespace
diff --git a/components/google/core/common/google_util.cc b/components/google/core/common/google_util.cc
index c01ba58..a44c843 100644
--- a/components/google/core/common/google_util.cc
+++ b/components/google/core/common/google_util.cc
@@ -12,6 +12,7 @@
 
 #include "base/command_line.h"
 #include "base/macros.h"
+#include "base/no_destructor.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
@@ -115,9 +116,9 @@
   // same page.
   StripTrailingDot(&tld);
 
-  CR_DEFINE_STATIC_LOCAL(std::set<std::string>, google_tlds,
-                         ({GOOGLE_TLD_LIST}));
-  return base::ContainsKey(google_tlds, tld.as_string());
+  static base::NoDestructor<std::set<std::string>> google_tlds(
+      {GOOGLE_TLD_LIST});
+  return base::ContainsKey(*google_tlds, tld.as_string());
 }
 
 // True if |url| is a valid URL with a host that is in the static list of
@@ -130,10 +131,10 @@
   base::StringPiece host(url.host_piece());
   StripTrailingDot(&host);
 
-  CR_DEFINE_STATIC_LOCAL(std::set<std::string>, google_subdomains,
-                         ({"ipv4.google.com", "ipv6.google.com"}));
+  static base::NoDestructor<std::set<std::string>> google_subdomains(
+      {"ipv4.google.com", "ipv6.google.com"});
 
-  return base::ContainsKey(google_subdomains, host.as_string());
+  return base::ContainsKey(*google_subdomains, host.as_string());
 }
 
 }  // namespace
@@ -206,18 +207,18 @@
   // Unit tests may add command-line flags after the first call to this
   // function, so we don't simply initialize a static |base_url| directly and
   // then unconditionally return it.
-  CR_DEFINE_STATIC_LOCAL(std::string, switch_value, ());
-  CR_DEFINE_STATIC_LOCAL(GURL, base_url, ());
+  static base::NoDestructor<std::string> switch_value;
+  static base::NoDestructor<GURL> base_url;
   std::string current_switch_value(
       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
           switches::kGoogleBaseURL));
-  if (current_switch_value != switch_value) {
-    switch_value = current_switch_value;
-    base_url = url_formatter::FixupURL(switch_value, std::string());
-    if (!base_url.is_valid() || base_url.has_query() || base_url.has_ref())
-      base_url = GURL();
+  if (current_switch_value != *switch_value) {
+    *switch_value = current_switch_value;
+    *base_url = url_formatter::FixupURL(*switch_value, std::string());
+    if (!base_url->is_valid() || base_url->has_query() || base_url->has_ref())
+      *base_url = GURL();
   }
-  return base_url;
+  return *base_url;
 }
 
 bool StartsWithCommandLineGoogleBaseURL(const GURL& url) {
@@ -284,29 +285,29 @@
 }
 
 const std::vector<std::string>& GetGoogleRegistrableDomains() {
-  CR_DEFINE_STATIC_LOCAL(std::vector<std::string>, kGoogleRegisterableDomains,
-                         ());
+  static base::NoDestructor<std::vector<std::string>>
+      kGoogleRegisterableDomains([]() {
+        std::vector<std::string> domains;
 
-  // Initialize the list.
-  if (kGoogleRegisterableDomains.empty()) {
-    std::vector<std::string> tlds{GOOGLE_TLD_LIST};
-    for (const std::string& tld : tlds) {
-      std::string domain = "google." + tld;
+        std::vector<std::string> tlds{GOOGLE_TLD_LIST};
+        for (const std::string& tld : tlds) {
+          std::string domain = "google." + tld;
 
-      // The Google TLD list might contain domains that are not considered
-      // to be registrable domains by net::registry_controlled_domains.
-      if (GetDomainAndRegistry(
-              domain,
-              net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) !=
-          domain) {
-        continue;
-      }
+          // The Google TLD list might contain domains that are not considered
+          // to be registrable domains by net::registry_controlled_domains.
+          if (GetDomainAndRegistry(domain,
+                                   net::registry_controlled_domains::
+                                       INCLUDE_PRIVATE_REGISTRIES) != domain) {
+            continue;
+          }
 
-      kGoogleRegisterableDomains.push_back(domain);
-    }
-  }
+          domains.push_back(domain);
+        }
 
-  return kGoogleRegisterableDomains;
+        return domains;
+      }());
+
+  return *kGoogleRegisterableDomains;
 }
 
 }  // namespace google_util
diff --git a/components/infobars/core/infobar_delegate.cc b/components/infobars/core/infobar_delegate.cc
index a975c13..b574402 100644
--- a/components/infobars/core/infobar_delegate.cc
+++ b/components/infobars/core/infobar_delegate.cc
@@ -5,6 +5,7 @@
 #include "components/infobars/core/infobar_delegate.h"
 
 #include "base/logging.h"
+#include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "components/infobars/core/infobar.h"
 #include "components/infobars/core/infobar_manager.h"
@@ -34,8 +35,8 @@
 }
 
 const gfx::VectorIcon& InfoBarDelegate::GetVectorIcon() const {
-  CR_DEFINE_STATIC_LOCAL(gfx::VectorIcon, empty_icon, ());
-  return empty_icon;
+  static base::NoDestructor<gfx::VectorIcon> empty_icon;
+  return *empty_icon;
 }
 
 gfx::Image InfoBarDelegate::GetIcon() const {
diff --git a/components/invalidation/impl/deprecated_invalidator_registrar.cc b/components/invalidation/impl/deprecated_invalidator_registrar.cc
index 342dbbbf..efab512 100644
--- a/components/invalidation/impl/deprecated_invalidator_registrar.cc
+++ b/components/invalidation/impl/deprecated_invalidator_registrar.cc
@@ -82,15 +82,15 @@
 ObjectIdSet DeprecatedInvalidatorRegistrar::GetRegisteredIds(
     InvalidationHandler* handler) const {
   DCHECK(thread_checker_.CalledOnValidThread());
-  HandlerIdsMap::const_iterator lookup = handler_to_ids_map_.find(handler);
+  auto lookup = handler_to_ids_map_.find(handler);
   return lookup != handler_to_ids_map_.end() ? lookup->second : ObjectIdSet();
 }
 
 ObjectIdSet DeprecatedInvalidatorRegistrar::GetAllRegisteredIds() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   ObjectIdSet registered_ids;
-  for (HandlerIdsMap::const_iterator it = handler_to_ids_map_.begin();
-       it != handler_to_ids_map_.end(); ++it) {
+  for (auto it = handler_to_ids_map_.begin(); it != handler_to_ids_map_.end();
+       ++it) {
     registered_ids.insert(it->second.begin(), it->second.end());
   }
   return registered_ids;
@@ -104,8 +104,8 @@
     return;
   }
 
-  for (HandlerIdsMap::iterator it = handler_to_ids_map_.begin();
-       it != handler_to_ids_map_.end(); ++it) {
+  for (auto it = handler_to_ids_map_.begin(); it != handler_to_ids_map_.end();
+       ++it) {
     ObjectIdInvalidationMap to_emit =
         invalidation_map.GetSubsetWithObjectIds(it->second);
     if (!to_emit.Empty()) {
diff --git a/components/invalidation/impl/fcm_invalidation_listener.cc b/components/invalidation/impl/fcm_invalidation_listener.cc
index 7a57693..dc466a01 100644
--- a/components/invalidation/impl/fcm_invalidation_listener.cc
+++ b/components/invalidation/impl/fcm_invalidation_listener.cc
@@ -97,10 +97,8 @@
 void FCMInvalidationListener::SaveInvalidations(
     const TopicInvalidationMap& to_save) {
   ObjectIdSet objects_to_save = ConvertTopicsToIds(to_save.GetTopics());
-  for (ObjectIdSet::const_iterator it = objects_to_save.begin();
-       it != objects_to_save.end(); ++it) {
-    UnackedInvalidationsMap::iterator lookup =
-        unacked_invalidations_map_.find(*it);
+  for (auto it = objects_to_save.begin(); it != objects_to_save.end(); ++it) {
+    auto lookup = unacked_invalidations_map_.find(*it);
     if (lookup == unacked_invalidations_map_.end()) {
       lookup = unacked_invalidations_map_
                    .insert(std::make_pair(*it, UnackedInvalidationSet(*it)))
@@ -124,8 +122,7 @@
 
 void FCMInvalidationListener::Acknowledge(const invalidation::ObjectId& id,
                                           const syncer::AckHandle& handle) {
-  UnackedInvalidationsMap::iterator lookup =
-      unacked_invalidations_map_.find(id);
+  auto lookup = unacked_invalidations_map_.find(id);
   if (lookup == unacked_invalidations_map_.end()) {
     DLOG(WARNING) << "Received acknowledgement for untracked object ID";
     return;
@@ -135,8 +132,7 @@
 
 void FCMInvalidationListener::Drop(const invalidation::ObjectId& id,
                                    const syncer::AckHandle& handle) {
-  UnackedInvalidationsMap::iterator lookup =
-      unacked_invalidations_map_.find(id);
+  auto lookup = unacked_invalidations_map_.find(id);
   if (lookup == unacked_invalidations_map_.end()) {
     DLOG(WARNING) << "Received drop for untracked object ID";
     return;
diff --git a/components/invalidation/impl/fcm_invalidation_listener_unittest.cc b/components/invalidation/impl/fcm_invalidation_listener_unittest.cc
index 4aa6bbc..7eef642 100644
--- a/components/invalidation/impl/fcm_invalidation_listener_unittest.cc
+++ b/components/invalidation/impl/fcm_invalidation_listener_unittest.cc
@@ -62,7 +62,7 @@
   ~FakeDelegate() override {}
 
   size_t GetInvalidationCount(const Topic& topic) const {
-    Map::const_iterator it = invalidations_.find(topic);
+    auto it = invalidations_.find(topic);
     if (it == invalidations_.end()) {
       return 0;
     } else {
@@ -71,7 +71,7 @@
   }
 
   int64_t GetVersion(const Topic& topic) const {
-    Map::const_iterator it = invalidations_.find(topic);
+    auto it = invalidations_.find(topic);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for topic " << topic;
       return 0;
@@ -81,7 +81,7 @@
   }
 
   std::string GetPayload(const Topic& topic) const {
-    Map::const_iterator it = invalidations_.find(topic);
+    auto it = invalidations_.find(topic);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for topic " << topic;
       return nullptr;
@@ -91,7 +91,7 @@
   }
 
   bool IsUnknownVersion(const Topic& topic) const {
-    Map::const_iterator it = invalidations_.find(topic);
+    auto it = invalidations_.find(topic);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for topic " << topic;
       return false;
@@ -101,7 +101,7 @@
   }
 
   bool StartsWithUnknownVersion(const Topic& topic) const {
-    Map::const_iterator it = invalidations_.find(topic);
+    auto it = invalidations_.find(topic);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for topic " << topic;
       return false;
@@ -114,27 +114,27 @@
 
   void AcknowledgeNthInvalidation(const Topic& topic, size_t n) {
     List& list = invalidations_[topic];
-    List::iterator it = list.begin() + n;
+    auto it = list.begin() + n;
     it->Acknowledge();
   }
 
   void AcknowledgeAll(const Topic& topic) {
     List& list = invalidations_[topic];
-    for (List::iterator it = list.begin(); it != list.end(); ++it) {
+    for (auto it = list.begin(); it != list.end(); ++it) {
       it->Acknowledge();
     }
   }
 
   void DropNthInvalidation(const Topic& topic, size_t n) {
     List& list = invalidations_[topic];
-    List::iterator it = list.begin() + n;
+    auto it = list.begin() + n;
     it->Drop();
     dropped_invalidations_map_.erase(topic);
     dropped_invalidations_map_.insert(std::make_pair(topic, *it));
   }
 
   void RecoverFromDropEvent(const Topic& topic) {
-    DropMap::iterator it = dropped_invalidations_map_.find(topic);
+    auto it = dropped_invalidations_map_.find(topic);
     if (it != dropped_invalidations_map_.end()) {
       it->second.Acknowledge();
       dropped_invalidations_map_.erase(it);
diff --git a/components/invalidation/impl/invalidation_logger.cc b/components/invalidation/impl/invalidation_logger.cc
index a101df0..384b641 100644
--- a/components/invalidation/impl/invalidation_logger.cc
+++ b/components/invalidation/impl/invalidation_logger.cc
@@ -26,8 +26,7 @@
 void InvalidationLogger::OnUnregistration(const std::string& registrar_name) {
   DCHECK(registered_handlers_.find(registrar_name) !=
          registered_handlers_.end());
-  std::multiset<std::string>::iterator it =
-      registered_handlers_.find(registrar_name);
+  auto it = registered_handlers_.find(registrar_name);
   // Delete only one instance of registrar_name.
   registered_handlers_.erase(it);
   EmitRegisteredHandlers();
@@ -77,10 +76,8 @@
        latest_ids_.begin(); it != latest_ids_.end(); ++it) {
     const syncer::ObjectIdSet& object_ids_for_handler = it->second;
     syncer::ObjectIdCountMap per_object_invalidation_count;
-    for (syncer::ObjectIdSet::const_iterator oid_it =
-             object_ids_for_handler.begin();
-         oid_it != object_ids_for_handler.end();
-         ++oid_it) {
+    for (auto oid_it = object_ids_for_handler.begin();
+         oid_it != object_ids_for_handler.end(); ++oid_it) {
       per_object_invalidation_count[*oid_it] = invalidation_count_[*oid_it];
     }
     for (auto& observer : observer_list_)
diff --git a/components/invalidation/impl/invalidator_registrar.cc b/components/invalidation/impl/invalidator_registrar.cc
index e68222d..45bc920 100644
--- a/components/invalidation/impl/invalidator_registrar.cc
+++ b/components/invalidation/impl/invalidator_registrar.cc
@@ -73,15 +73,14 @@
 TopicSet InvalidatorRegistrar::GetRegisteredTopics(
     InvalidationHandler* handler) const {
   DCHECK(thread_checker_.CalledOnValidThread());
-  HandlerTopicsMap::const_iterator lookup =
-      handler_to_topics_map_.find(handler);
+  auto lookup = handler_to_topics_map_.find(handler);
   return lookup != handler_to_topics_map_.end() ? lookup->second : TopicSet();
 }
 
 TopicSet InvalidatorRegistrar::GetAllRegisteredIds() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   TopicSet registered_ids;
-  for (HandlerTopicsMap::const_iterator it = handler_to_topics_map_.begin();
+  for (auto it = handler_to_topics_map_.begin();
        it != handler_to_topics_map_.end(); ++it) {
     registered_ids.insert(it->second.begin(), it->second.end());
   }
diff --git a/components/invalidation/impl/invalidator_storage.cc b/components/invalidation/impl/invalidator_storage.cc
index e4c3a38..4730f72 100644
--- a/components/invalidation/impl/invalidator_storage.cc
+++ b/components/invalidation/impl/invalidator_storage.cc
@@ -42,8 +42,7 @@
 std::unique_ptr<base::ListValue> UnackedInvalidationStorageMapToValue(
     const syncer::UnackedInvalidationsMap& map) {
   std::unique_ptr<base::ListValue> value(new base::ListValue);
-  for (syncer::UnackedInvalidationsMap::const_iterator it = map.begin();
-       it != map.end(); ++it) {
+  for (auto it = map.begin(); it != map.end(); ++it) {
     value->Append(it->second.ToValue());
   }
   return value;
diff --git a/components/invalidation/impl/mock_ack_handler.cc b/components/invalidation/impl/mock_ack_handler.cc
index d28976a..ca51a74 100644
--- a/components/invalidation/impl/mock_ack_handler.cc
+++ b/components/invalidation/impl/mock_ack_handler.cc
@@ -46,37 +46,29 @@
 
 bool MockAckHandler::IsUnacked(const Invalidation& invalidation) const {
   AckHandleMatcher matcher(invalidation.ack_handle());
-  InvalidationVector::const_iterator it = std::find_if(
-      unacked_invalidations_.begin(),
-      unacked_invalidations_.end(),
-      matcher);
+  auto it = std::find_if(unacked_invalidations_.begin(),
+                         unacked_invalidations_.end(), matcher);
   return it != unacked_invalidations_.end();
 }
 
 bool MockAckHandler::IsAcknowledged(const Invalidation& invalidation) const {
   AckHandleMatcher matcher(invalidation.ack_handle());
-  InvalidationVector::const_iterator it = std::find_if(
-      acked_invalidations_.begin(),
-      acked_invalidations_.end(),
-      matcher);
+  auto it = std::find_if(acked_invalidations_.begin(),
+                         acked_invalidations_.end(), matcher);
   return it != acked_invalidations_.end();
 }
 
 bool MockAckHandler::IsDropped(const Invalidation& invalidation) const {
   AckHandleMatcher matcher(invalidation.ack_handle());
-  InvalidationVector::const_iterator it = std::find_if(
-      dropped_invalidations_.begin(),
-      dropped_invalidations_.end(),
-      matcher);
+  auto it = std::find_if(dropped_invalidations_.begin(),
+                         dropped_invalidations_.end(), matcher);
   return it != dropped_invalidations_.end();
 }
 
 bool MockAckHandler::IsUnsent(const Invalidation& invalidation) const {
   AckHandleMatcher matcher(invalidation.ack_handle());
-  InvalidationVector::const_iterator it1 = std::find_if(
-      unsent_invalidations_.begin(),
-      unsent_invalidations_.end(),
-      matcher);
+  auto it1 = std::find_if(unsent_invalidations_.begin(),
+                          unsent_invalidations_.end(), matcher);
   return it1 != unsent_invalidations_.end();
 }
 
@@ -88,16 +80,14 @@
     const invalidation::ObjectId& id,
     const AckHandle& handle) {
   AckHandleMatcher matcher(handle);
-  InvalidationVector::iterator it = std::find_if(
-      unacked_invalidations_.begin(),
-      unacked_invalidations_.end(),
-      matcher);
+  auto it = std::find_if(unacked_invalidations_.begin(),
+                         unacked_invalidations_.end(), matcher);
   if (it != unacked_invalidations_.end()) {
     acked_invalidations_.push_back(*it);
     unacked_invalidations_.erase(it);
   }
 
-  IdHandleMap::iterator it2 = unrecovered_drop_events_.find(id);
+  auto it2 = unrecovered_drop_events_.find(id);
   if (it2 != unrecovered_drop_events_.end() && it2->second.Equals(handle)) {
     unrecovered_drop_events_.erase(it2);
   }
@@ -107,10 +97,8 @@
     const invalidation::ObjectId& id,
     const AckHandle& handle) {
   AckHandleMatcher matcher(handle);
-  InvalidationVector::iterator it = std::find_if(
-      unacked_invalidations_.begin(),
-      unacked_invalidations_.end(),
-      matcher);
+  auto it = std::find_if(unacked_invalidations_.begin(),
+                         unacked_invalidations_.end(), matcher);
   if (it != unacked_invalidations_.end()) {
     dropped_invalidations_.push_back(*it);
     unacked_invalidations_.erase(it);
diff --git a/components/invalidation/impl/object_id_invalidation_map_test_util.cc b/components/invalidation/impl/object_id_invalidation_map_test_util.cc
index d40965a8..03fa957 100644
--- a/components/invalidation/impl/object_id_invalidation_map_test_util.cc
+++ b/components/invalidation/impl/object_id_invalidation_map_test_util.cc
@@ -63,8 +63,7 @@
   std::vector<syncer::Invalidation> expected_only;
   std::vector<syncer::Invalidation> actual_only;
 
-  for (std::vector<syncer::Invalidation>::iterator it =
-       expected_invalidations.begin();
+  for (auto it = expected_invalidations.begin();
        it != expected_invalidations.end(); ++it) {
     if (std::find_if(actual_invalidations.begin(),
                      actual_invalidations.end(),
@@ -74,9 +73,8 @@
     }
   }
 
-  for (std::vector<syncer::Invalidation>::iterator it =
-       actual_invalidations.begin();
-       it != actual_invalidations.end(); ++it) {
+  for (auto it = actual_invalidations.begin(); it != actual_invalidations.end();
+       ++it) {
     if (std::find_if(expected_invalidations.begin(),
                      expected_invalidations.end(),
                      InvalidationEqPredicate(*it))
diff --git a/components/invalidation/impl/registration_manager.cc b/components/invalidation/impl/registration_manager.cc
index 8dc2fff..d39af92 100644
--- a/components/invalidation/impl/registration_manager.cc
+++ b/components/invalidation/impl/registration_manager.cc
@@ -79,13 +79,11 @@
                       std::inserter(to_unregister, to_unregister.begin()),
                       ObjectIdLessThan());
 
-  for (ObjectIdSet::const_iterator it = to_unregister.begin();
-       it != to_unregister.end(); ++it) {
+  for (auto it = to_unregister.begin(); it != to_unregister.end(); ++it) {
     UnregisterId(*it);
   }
 
-  for (ObjectIdSet::const_iterator it = to_register.begin();
-       it != to_register.end(); ++it) {
+  for (auto it = to_register.begin(); it != to_register.end(); ++it) {
     if (!base::ContainsKey(registration_statuses_, *it)) {
       registration_statuses_[*it] =
           std::make_unique<RegistrationStatus>(*it, this);
diff --git a/components/invalidation/impl/registration_manager_unittest.cc b/components/invalidation/impl/registration_manager_unittest.cc
index e644925f..b9b7d8bc 100644
--- a/components/invalidation/impl/registration_manager_unittest.cc
+++ b/components/invalidation/impl/registration_manager_unittest.cc
@@ -120,9 +120,8 @@
     double expected_delay_seconds,
     const RegistrationManager::PendingRegistrationMap& pending_registrations) {
   ObjectIdSet pending_ids;
-  for (RegistrationManager::PendingRegistrationMap::const_iterator it =
-           pending_registrations.begin(); it != pending_registrations.end();
-       ++it) {
+  for (auto it = pending_registrations.begin();
+       it != pending_registrations.end(); ++it) {
     SCOPED_TRACE(ObjectIdToString(it->first));
     pending_ids.insert(it->first);
     base::TimeDelta offset =
@@ -154,16 +153,14 @@
   ~RegistrationManagerTest() override {}
 
   void LoseRegistrations(const ObjectIdSet& oids) {
-    for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end();
-         ++it) {
+    for (auto it = oids.begin(); it != oids.end(); ++it) {
       fake_invalidation_client_.LoseRegistration(*it);
       fake_registration_manager_.MarkRegistrationLost(*it);
     }
   }
 
   void DisableIds(const ObjectIdSet& oids) {
-    for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end();
-         ++it) {
+    for (auto it = oids.begin(); it != oids.end(); ++it) {
       fake_invalidation_client_.LoseRegistration(*it);
       fake_registration_manager_.DisableId(*it);
     }
diff --git a/components/invalidation/impl/single_object_invalidation_set_unittest.cc b/components/invalidation/impl/single_object_invalidation_set_unittest.cc
index 35c4445..7643b6c 100644
--- a/components/invalidation/impl/single_object_invalidation_set_unittest.cc
+++ b/components/invalidation/impl/single_object_invalidation_set_unittest.cc
@@ -42,8 +42,8 @@
   ASSERT_EQ(3U, l1.GetSize());
   ASSERT_EQ(3U, l2.GetSize());
 
-  SingleObjectInvalidationSet::const_iterator it1 = l1.begin();
-  SingleObjectInvalidationSet::const_iterator it2 = l2.begin();
+  auto it1 = l1.begin();
+  auto it2 = l2.begin();
   EXPECT_THAT(inv0, Eq(*it1));
   EXPECT_THAT(inv0, Eq(*it2));
   it1++;
diff --git a/components/invalidation/impl/sync_invalidation_listener.cc b/components/invalidation/impl/sync_invalidation_listener.cc
index deff38b..0dbfeb3 100644
--- a/components/invalidation/impl/sync_invalidation_listener.cc
+++ b/components/invalidation/impl/sync_invalidation_listener.cc
@@ -175,8 +175,7 @@
   client->Acknowledge(ack_handle);
 
   ObjectIdInvalidationMap invalidations;
-  for (ObjectIdSet::iterator it = registered_ids_.begin();
-       it != registered_ids_.end(); ++it) {
+  for (auto it = registered_ids_.begin(); it != registered_ids_.end(); ++it) {
     Invalidation unknown_version = Invalidation::InitUnknownVersion(*it);
     unknown_version.SetAckHandler(AsWeakPtr(),
                                   base::ThreadTaskRunnerHandle::Get());
@@ -202,10 +201,8 @@
 void SyncInvalidationListener::SaveInvalidations(
     const ObjectIdInvalidationMap& to_save) {
   ObjectIdSet objects_to_save = to_save.GetObjectIds();
-  for (ObjectIdSet::const_iterator it = objects_to_save.begin();
-       it != objects_to_save.end(); ++it) {
-    UnackedInvalidationsMap::iterator lookup =
-        unacked_invalidations_map_.find(*it);
+  for (auto it = objects_to_save.begin(); it != objects_to_save.end(); ++it) {
+    auto lookup = unacked_invalidations_map_.find(*it);
     if (lookup == unacked_invalidations_map_.end()) {
       lookup = unacked_invalidations_map_.insert(
           std::make_pair(*it, UnackedInvalidationSet(*it))).first;
@@ -298,8 +295,7 @@
 void SyncInvalidationListener::Acknowledge(
   const invalidation::ObjectId& id,
   const syncer::AckHandle& handle) {
-  UnackedInvalidationsMap::iterator lookup =
-      unacked_invalidations_map_.find(id);
+  auto lookup = unacked_invalidations_map_.find(id);
   if (lookup == unacked_invalidations_map_.end()) {
     DLOG(WARNING) << "Received acknowledgement for untracked object ID";
     return;
@@ -314,8 +310,7 @@
 void SyncInvalidationListener::Drop(
     const invalidation::ObjectId& id,
     const syncer::AckHandle& handle) {
-  UnackedInvalidationsMap::iterator lookup =
-      unacked_invalidations_map_.find(id);
+  auto lookup = unacked_invalidations_map_.find(id);
   if (lookup == unacked_invalidations_map_.end()) {
     DLOG(WARNING) << "Received drop for untracked object ID";
     return;
@@ -339,8 +334,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const ObjectIdSet& unregistered_ids =
       registration_manager_->UpdateRegisteredIds(registered_ids_);
-  for (ObjectIdSet::iterator it = unregistered_ids.begin();
-       it != unregistered_ids.end(); ++it) {
+  for (auto it = unregistered_ids.begin(); it != unregistered_ids.end(); ++it) {
     unacked_invalidations_map_.erase(*it);
   }
   invalidation_state_tracker_task_runner_->PostTask(
@@ -349,8 +343,7 @@
                      invalidation_state_tracker_, unacked_invalidations_map_));
 
   ObjectIdInvalidationMap object_id_invalidation_map;
-  for (UnackedInvalidationsMap::iterator map_it =
-       unacked_invalidations_map_.begin();
+  for (auto map_it = unacked_invalidations_map_.begin();
        map_it != unacked_invalidations_map_.end(); ++map_it) {
     if (registered_ids_.find(map_it->first) == registered_ids_.end()) {
       continue;
@@ -384,10 +377,8 @@
                           std::string(InvalidatorStateToString(ticl_state_)));
   std::unique_ptr<base::DictionaryValue> unacked_map(
       new base::DictionaryValue());
-  for (UnackedInvalidationsMap::const_iterator it =
-           unacked_invalidations_map_.begin();
-       it != unacked_invalidations_map_.end();
-       ++it) {
+  for (auto it = unacked_invalidations_map_.begin();
+       it != unacked_invalidations_map_.end(); ++it) {
     unacked_map->Set((it->first).name(), (it->second).ToValue());
   }
   return_value->Set("SyncInvalidationListener.UnackedInvalidationsMap",
diff --git a/components/invalidation/impl/sync_invalidation_listener_unittest.cc b/components/invalidation/impl/sync_invalidation_listener_unittest.cc
index b0b0937..7b371f04 100644
--- a/components/invalidation/impl/sync_invalidation_listener_unittest.cc
+++ b/components/invalidation/impl/sync_invalidation_listener_unittest.cc
@@ -112,8 +112,7 @@
       ADD_FAILURE();
       return;
     }
-    for (invalidation::vector<ObjectId>::const_iterator
-             it = object_ids.begin(); it != object_ids.end(); ++it) {
+    for (auto it = object_ids.begin(); it != object_ids.end(); ++it) {
       registered_ids_.erase(*it);
     }
   }
@@ -141,7 +140,7 @@
   ~FakeDelegate() override {}
 
   size_t GetInvalidationCount(const ObjectId& id) const {
-    Map::const_iterator it = invalidations_.find(id);
+    auto it = invalidations_.find(id);
     if (it == invalidations_.end()) {
       return 0;
     } else {
@@ -150,7 +149,7 @@
   }
 
   int64_t GetVersion(const ObjectId& id) const {
-    Map::const_iterator it = invalidations_.find(id);
+    auto it = invalidations_.find(id);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
       return 0;
@@ -160,7 +159,7 @@
   }
 
   std::string GetPayload(const ObjectId& id) const {
-    Map::const_iterator it = invalidations_.find(id);
+    auto it = invalidations_.find(id);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
       return nullptr;
@@ -170,7 +169,7 @@
   }
 
   bool IsUnknownVersion(const ObjectId& id) const {
-    Map::const_iterator it = invalidations_.find(id);
+    auto it = invalidations_.find(id);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
       return false;
@@ -180,7 +179,7 @@
   }
 
   bool StartsWithUnknownVersion(const ObjectId& id) const {
-    Map::const_iterator it = invalidations_.find(id);
+    auto it = invalidations_.find(id);
     if (it == invalidations_.end()) {
       ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
       return false;
@@ -195,27 +194,27 @@
 
   void AcknowledgeNthInvalidation(const ObjectId& id, size_t n) {
     List& list = invalidations_[id];
-    List::iterator it = list.begin() + n;
+    auto it = list.begin() + n;
     it->Acknowledge();
   }
 
   void AcknowledgeAll(const ObjectId& id) {
     List& list = invalidations_[id];
-    for (List::iterator it = list.begin(); it != list.end(); ++it) {
+    for (auto it = list.begin(); it != list.end(); ++it) {
       it->Acknowledge();
     }
   }
 
   void DropNthInvalidation(const ObjectId& id, size_t n) {
     List& list = invalidations_[id];
-    List::iterator it = list.begin() + n;
+    auto it = list.begin() + n;
     it->Drop();
     dropped_invalidations_map_.erase(id);
     dropped_invalidations_map_.insert(std::make_pair(id, *it));
   }
 
   void RecoverFromDropEvent(const ObjectId& id) {
-    DropMap::iterator it = dropped_invalidations_map_.find(id);
+    auto it = dropped_invalidations_map_.find(id);
     if (it != dropped_invalidations_map_.end()) {
       it->second.Acknowledge();
       dropped_invalidations_map_.erase(it);
@@ -225,7 +224,7 @@
   // SyncInvalidationListener::Delegate implementation.
   void OnInvalidate(const ObjectIdInvalidationMap& invalidation_map) override {
     ObjectIdSet ids = invalidation_map.GetObjectIds();
-    for (ObjectIdSet::iterator it = ids.begin(); it != ids.end(); ++it) {
+    for (auto it = ids.begin(); it != ids.end(); ++it) {
       const SingleObjectInvalidationSet& incoming =
           invalidation_map.ForObject(*it);
       List& list = invalidations_[*it];
@@ -365,8 +364,7 @@
 
   SingleObjectInvalidationSet GetSavedInvalidationsForType(const ObjectId& id) {
     const UnackedInvalidationsMap& saved_state = GetSavedInvalidations();
-    UnackedInvalidationsMap::const_iterator it =
-        saved_state.find(kBookmarksId_);
+    auto it = saved_state.find(kBookmarksId_);
     if (it == saved_state.end()) {
       ADD_FAILURE() << "No state saved for ID " << ObjectIdToString(id);
       return SingleObjectInvalidationSet();
@@ -613,8 +611,7 @@
 TEST_F(SyncInvalidationListenerTest, InvalidateAll) {
   FireInvalidateAll();
 
-  for (ObjectIdSet::const_iterator it = registered_ids_.begin();
-       it != registered_ids_.end(); ++it) {
+  for (auto it = registered_ids_.begin(); it != registered_ids_.end(); ++it) {
     ASSERT_EQ(1U, GetInvalidationCount(*it));
     EXPECT_TRUE(IsUnknownVersion(*it));
   }
@@ -806,7 +803,7 @@
   // Expect that the duplicate was discarded.
   SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
   EXPECT_EQ(3U, list.GetSize());
-  SingleObjectInvalidationSet::const_iterator it = list.begin();
+  auto it = list.begin();
   EXPECT_EQ(1, it->version());
   it++;
   EXPECT_EQ(2, it->version());
diff --git a/components/invalidation/impl/unacked_invalidation_set.cc b/components/invalidation/impl/unacked_invalidation_set.cc
index dd02f6d..e7d1745 100644
--- a/components/invalidation/impl/unacked_invalidation_set.cc
+++ b/components/invalidation/impl/unacked_invalidation_set.cc
@@ -61,8 +61,7 @@
     base::WeakPtr<AckHandler> ack_handler,
     scoped_refptr<base::SingleThreadTaskRunner> ack_handler_task_runner,
     ObjectIdInvalidationMap* out) const {
-  for (SingleObjectInvalidationSet::const_iterator it = invalidations_.begin();
-       it != invalidations_.end(); ++it) {
+  for (auto it = invalidations_.begin(); it != invalidations_.end(); ++it) {
     // Copy the invalidation and set the copy's ack_handler.
     Invalidation inv(*it);
     inv.SetAckHandler(ack_handler, ack_handler_task_runner);
@@ -86,8 +85,7 @@
 // Removes the matching ack handle from the list.
 void UnackedInvalidationSet::Acknowledge(const AckHandle& handle) {
   bool handle_found = false;
-  for (SingleObjectInvalidationSet::const_iterator it = invalidations_.begin();
-       it != invalidations_.end(); ++it) {
+  for (auto it = invalidations_.begin(); it != invalidations_.end(); ++it) {
     if (it->ack_handle().Equals(handle)) {
       invalidations_.erase(*it);
       handle_found = true;
@@ -165,8 +163,7 @@
   value->SetString(kNameKey, object_id_.name());
 
   std::unique_ptr<base::ListValue> list_value(new base::ListValue);
-  for (InvalidationsSet::const_iterator it = invalidations_.begin();
-       it != invalidations_.end(); ++it) {
+  for (auto it = invalidations_.begin(); it != invalidations_.end(); ++it) {
     list_value->Append(it->ToValue());
   }
   value->Set(kInvalidationListKey, std::move(list_value));
diff --git a/components/invalidation/impl/unacked_invalidation_set_test_util.cc b/components/invalidation/impl/unacked_invalidation_set_test_util.cc
index c06ba1f..db0c67c 100644
--- a/components/invalidation/impl/unacked_invalidation_set_test_util.cc
+++ b/components/invalidation/impl/unacked_invalidation_set_test_util.cc
@@ -89,8 +89,7 @@
 ObjectIdInvalidationMap UnackedInvalidationsMapToObjectIdInvalidationMap(
     const UnackedInvalidationsMap& state_map) {
   ObjectIdInvalidationMap object_id_invalidation_map;
-  for (UnackedInvalidationsMap::const_iterator it = state_map.begin();
-       it != state_map.end(); ++it) {
+  for (auto it = state_map.begin(); it != state_map.end(); ++it) {
     it->second.ExportInvalidations(
         base::WeakPtr<AckHandler>(),
         scoped_refptr<base::SingleThreadTaskRunner>(),
@@ -158,8 +157,7 @@
 
 void PrintTo(const UnackedInvalidationsMap& map, ::std::ostream* os) {
   std::unique_ptr<base::ListValue> list(new base::ListValue);
-  for (UnackedInvalidationsMap::const_iterator it = map.begin();
-       it != map.end(); ++it) {
+  for (auto it = map.begin(); it != map.end(); ++it) {
     list->Append(it->second.ToValue());
   }
 
diff --git a/components/invalidation/public/object_id_invalidation_map.cc b/components/invalidation/public/object_id_invalidation_map.cc
index d760d56..253c8c4 100644
--- a/components/invalidation/public/object_id_invalidation_map.cc
+++ b/components/invalidation/public/object_id_invalidation_map.cc
@@ -14,7 +14,7 @@
 ObjectIdInvalidationMap ObjectIdInvalidationMap::InvalidateAll(
     const ObjectIdSet& ids) {
   ObjectIdInvalidationMap invalidate_all;
-  for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
+  for (auto it = ids.begin(); it != ids.end(); ++it) {
     invalidate_all.Insert(Invalidation::InitUnknownVersion(*it));
   }
   return invalidate_all;
@@ -29,7 +29,7 @@
 
 ObjectIdSet ObjectIdInvalidationMap::GetObjectIds() const {
   ObjectIdSet ret;
-  for (IdToListMap::const_iterator it = map_.begin(); it != map_.end(); ++it) {
+  for (auto it = map_.begin(); it != map_.end(); ++it) {
     ret.insert(it->first);
   }
   return ret;
@@ -46,8 +46,8 @@
 ObjectIdInvalidationMap ObjectIdInvalidationMap::GetSubsetWithObjectIds(
     const ObjectIdSet& ids) const {
   IdToListMap new_map;
-  for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
-    IdToListMap::const_iterator lookup = map_.find(*it);
+  for (auto it = ids.begin(); it != ids.end(); ++it) {
+    auto lookup = map_.find(*it);
     if (lookup != map_.end()) {
       new_map[*it] = lookup->second;
     }
@@ -57,7 +57,7 @@
 
 const SingleObjectInvalidationSet& ObjectIdInvalidationMap::ForObject(
     invalidation::ObjectId id) const {
-  IdToListMap::const_iterator lookup = map_.find(id);
+  auto lookup = map_.find(id);
   DCHECK(lookup != map_.end());
   DCHECK(!lookup->second.IsEmpty());
   return lookup->second;
@@ -65,15 +65,13 @@
 
 void ObjectIdInvalidationMap::GetAllInvalidations(
     std::vector<syncer::Invalidation>* out) const {
-  for (IdToListMap::const_iterator it = map_.begin(); it != map_.end(); ++it) {
+  for (auto it = map_.begin(); it != map_.end(); ++it) {
     out->insert(out->begin(), it->second.begin(), it->second.end());
   }
 }
 void ObjectIdInvalidationMap::AcknowledgeAll() const {
-  for (IdToListMap::const_iterator it1 = map_.begin();
-       it1 != map_.end(); ++it1) {
-    for (SingleObjectInvalidationSet::const_iterator it2 = it1->second.begin();
-         it2 != it1->second.end(); ++it2) {
+  for (auto it1 = map_.begin(); it1 != map_.end(); ++it1) {
+    for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) {
       it2->Acknowledge();
     }
   }
@@ -86,10 +84,8 @@
 
 std::unique_ptr<base::ListValue> ObjectIdInvalidationMap::ToValue() const {
   std::unique_ptr<base::ListValue> value(new base::ListValue());
-  for (IdToListMap::const_iterator it1 = map_.begin();
-       it1 != map_.end(); ++it1) {
-    for (SingleObjectInvalidationSet::const_iterator it2 =
-         it1->second.begin(); it2 != it1->second.end(); ++it2) {
+  for (auto it1 = map_.begin(); it1 != map_.end(); ++it1) {
+    for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) {
       value->Append(it2->ToValue());
     }
   }
diff --git a/components/invalidation/public/single_object_invalidation_set.cc b/components/invalidation/public/single_object_invalidation_set.cc
index 698f025..4986332 100644
--- a/components/invalidation/public/single_object_invalidation_set.cc
+++ b/components/invalidation/public/single_object_invalidation_set.cc
@@ -90,8 +90,7 @@
 
 std::unique_ptr<base::ListValue> SingleObjectInvalidationSet::ToValue() const {
   std::unique_ptr<base::ListValue> value(new base::ListValue);
-  for (InvalidationsSet::const_iterator it = invalidations_.begin();
-       it != invalidations_.end(); ++it) {
+  for (auto it = invalidations_.begin(); it != invalidations_.end(); ++it) {
     value->Append(it->ToValue());
   }
   return value;
diff --git a/components/invalidation/public/topic_invalidation_map.cc b/components/invalidation/public/topic_invalidation_map.cc
index e27dcfb..2200c01e 100644
--- a/components/invalidation/public/topic_invalidation_map.cc
+++ b/components/invalidation/public/topic_invalidation_map.cc
@@ -37,7 +37,7 @@
     const TopicSet& topics) const {
   TopicToListMap new_map;
   for (const auto& topic : topics) {
-    TopicToListMap::const_iterator lookup = map_.find(topic);
+    auto lookup = map_.find(topic);
     if (lookup != map_.end()) {
       new_map[topic] = lookup->second;
     }
@@ -47,7 +47,7 @@
 
 const SingleObjectInvalidationSet& TopicInvalidationMap::ForTopic(
     Topic topic) const {
-  TopicToListMap::const_iterator lookup = map_.find(topic);
+  auto lookup = map_.find(topic);
   DCHECK(lookup != map_.end());
   DCHECK(!lookup->second.IsEmpty());
   return lookup->second;
@@ -55,17 +55,14 @@
 
 void TopicInvalidationMap::GetAllInvalidations(
     std::vector<syncer::Invalidation>* out) const {
-  for (TopicToListMap::const_iterator it = map_.begin(); it != map_.end();
-       ++it) {
+  for (auto it = map_.begin(); it != map_.end(); ++it) {
     out->insert(out->begin(), it->second.begin(), it->second.end());
   }
 }
 
 void TopicInvalidationMap::AcknowledgeAll() const {
-  for (TopicToListMap::const_iterator it1 = map_.begin(); it1 != map_.end();
-       ++it1) {
-    for (SingleObjectInvalidationSet::const_iterator it2 = it1->second.begin();
-         it2 != it1->second.end(); ++it2) {
+  for (auto it1 = map_.begin(); it1 != map_.end(); ++it1) {
+    for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) {
       it2->Acknowledge();
     }
   }
@@ -77,10 +74,8 @@
 
 std::unique_ptr<base::ListValue> TopicInvalidationMap::ToValue() const {
   std::unique_ptr<base::ListValue> value(new base::ListValue());
-  for (TopicToListMap::const_iterator it1 = map_.begin(); it1 != map_.end();
-       ++it1) {
-    for (SingleObjectInvalidationSet::const_iterator it2 = it1->second.begin();
-         it2 != it1->second.end(); ++it2) {
+  for (auto it1 = map_.begin(); it1 != map_.end(); ++it1) {
+    for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2) {
       value->Append(it2->ToValue());
     }
   }
diff --git a/components/ntp_snippets/BUILD.gn b/components/ntp_snippets/BUILD.gn
index 2f3df3f..ea43fed 100644
--- a/components/ntp_snippets/BUILD.gn
+++ b/components/ntp_snippets/BUILD.gn
@@ -117,10 +117,6 @@
     "remote/request_params.h",
     "remote/request_throttler.cc",
     "remote/request_throttler.h",
-    "sessions/foreign_sessions_suggestions_provider.cc",
-    "sessions/foreign_sessions_suggestions_provider.h",
-    "sessions/tab_delegate_sync_adapter.cc",
-    "sessions/tab_delegate_sync_adapter.h",
     "status.cc",
     "status.h",
     "switches.cc",
@@ -165,9 +161,7 @@
     "//components/ntp_snippets/remote/proto",
     "//components/offline_pages/core",
     "//components/reading_list/core",
-    "//components/sessions",
     "//components/strings",
-    "//components/sync_sessions",
     "//components/unified_consent",
     "//components/url_formatter",
     "//components/variations",
@@ -239,8 +233,6 @@
     "remote/request_throttler_unittest.cc",
     "remote/test_utils.cc",
     "remote/test_utils.h",
-    "sessions/foreign_sessions_suggestions_provider_unittest.cc",
-    "sessions/tab_delegate_sync_adapter_unittest.cc",
     "time_serialization_unittest.cc",
     "user_classifier_unittest.cc",
   ]
@@ -268,12 +260,9 @@
     "//components/offline_pages/core/background:test_support",
     "//components/prefs:test_support",
     "//components/reading_list/core",
-    "//components/sessions",
-    "//components/sessions:test_support",
     "//components/strings",
     "//components/sync:test_support_driver",
     "//components/sync_preferences:test_support",
-    "//components/sync_sessions",
     "//components/ukm:test_support",
     "//components/variations:test_support",
     "//components/web_resource:web_resource",
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_features.cc b/components/ntp_snippets/contextual/contextual_suggestions_features.cc
index 7fb4b33..c15c2b0 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_features.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_features.cc
@@ -13,6 +13,9 @@
 const base::Feature kContextualSuggestionsButton{
     "ContextualSuggestionsButton", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kContextualSuggestionsIPHReverseScroll{
+    "ContextualSuggestionsIPHReverseScroll", base::FEATURE_ENABLED_BY_DEFAULT};
+
 const base::Feature kContextualSuggestionsOptOut{
     "ContextualSuggestionsOptOut", base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_features.h b/components/ntp_snippets/contextual/contextual_suggestions_features.h
index 170dca1..18e6417 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_features.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_features.h
@@ -11,6 +11,7 @@
 
 extern const base::Feature kContextualSuggestionsAlternateCardLayout;
 extern const base::Feature kContextualSuggestionsButton;
+extern const base::Feature kContextualSuggestionsIPHReverseScroll;
 extern const base::Feature kContextualSuggestionsOptOut;
 
 }  // namespace contextual_suggestions
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc
index f9dc7d3..10fd9ed 100644
--- a/components/ntp_snippets/pref_names.cc
+++ b/components/ntp_snippets/pref_names.cc
@@ -53,8 +53,6 @@
 
 const char kDismissedAssetDownloadSuggestions[] =
     "ntp_suggestions.downloads.assets.dismissed_ids";
-const char kDismissedForeignSessionsSuggestions[] =
-    "ntp_suggestions.foreign_sessions.dismissed_ids";
 const char kDismissedOfflinePageDownloadSuggestions[] =
     "ntp_suggestions.downloads.offline_pages.dismissed_ids";
 
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h
index 7e26cc8..7fefdf0 100644
--- a/components/ntp_snippets/pref_names.h
+++ b/components/ntp_snippets/pref_names.h
@@ -67,7 +67,6 @@
 extern const char kLastSuccessfulBackgroundFetchTime[];
 
 extern const char kDismissedAssetDownloadSuggestions[];
-extern const char kDismissedForeignSessionsSuggestions[];
 extern const char kDismissedOfflinePageDownloadSuggestions[];
 
 extern const char kDismissedCategories[];
diff --git a/components/ntp_snippets/sessions/DEPS b/components/ntp_snippets/sessions/DEPS
deleted file mode 100644
index e279a07..0000000
--- a/components/ntp_snippets/sessions/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+components/sessions",
-  "+components/sync_sessions",
-]
diff --git a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.cc b/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.cc
deleted file mode 100644
index 82a3f34..0000000
--- a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.cc
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h"
-
-#include <algorithm>
-#include <map>
-#include <tuple>
-#include <utility>
-
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "components/ntp_snippets/category.h"
-#include "components/ntp_snippets/category_info.h"
-#include "components/ntp_snippets/content_suggestion.h"
-#include "components/ntp_snippets/features.h"
-#include "components/ntp_snippets/pref_names.h"
-#include "components/ntp_snippets/pref_util.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/pref_service.h"
-#include "components/sessions/core/session_types.h"
-#include "components/strings/grit/components_strings.h"
-#include "components/sync_sessions/synced_session.h"
-#include "components/variations/variations_associated_data.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/image/image.h"
-#include "url/gurl.h"
-
-using base::Time;
-using base::TimeDelta;
-using sessions::SerializedNavigationEntry;
-using sessions::SessionTab;
-using sessions::SessionWindow;
-using sync_sessions::SyncedSessionWindow;
-using sync_sessions::SyncedSession;
-
-using DismissedFilter = base::Callback<bool(const std::string& id)>;
-
-namespace ntp_snippets {
-namespace {
-
-const int kMaxForeignTabsTotal = 10;
-const int kMaxForeignTabsPerDevice = 3;
-const int kMaxForeignTabAgeInMinutes = 180;
-
-const char* kMaxForeignTabsTotalParamName = "max_foreign_tabs_total";
-const char* kMaxForeignTabsPerDeviceParamName = "max_foreign_tabs_per_device";
-const char* kMaxForeignTabAgeInMinutesParamName =
-    "max_foreign_tabs_age_in_minutes";
-
-int GetMaxForeignTabsTotal() {
-  return variations::GetVariationParamByFeatureAsInt(
-      ntp_snippets::kForeignSessionsSuggestionsFeature,
-      kMaxForeignTabsTotalParamName, kMaxForeignTabsTotal);
-}
-
-int GetMaxForeignTabsPerDevice() {
-  return variations::GetVariationParamByFeatureAsInt(
-      ntp_snippets::kForeignSessionsSuggestionsFeature,
-      kMaxForeignTabsPerDeviceParamName, kMaxForeignTabsPerDevice);
-}
-
-TimeDelta GetMaxForeignTabAge() {
-  return TimeDelta::FromMinutes(variations::GetVariationParamByFeatureAsInt(
-      ntp_snippets::kForeignSessionsSuggestionsFeature,
-      kMaxForeignTabAgeInMinutesParamName, kMaxForeignTabAgeInMinutes));
-}
-
-// This filter does two things. Most importantly it lets through only ids that
-// have not been dismissed. The other responsibility this class has is it tracks
-// all of the ids that fly past it, and it will save the intersection of
-// initially dismissed ids, and seen ids. This will aggressively prune any
-// dismissal that is not currently blocking a recent tab.
-class PrefsPruningDismissedItemFilter {
- public:
-  explicit PrefsPruningDismissedItemFilter(PrefService* pref_service)
-      : pref_service_(pref_service),
-        initial_dismissed_ids_(prefs::ReadDismissedIDsFromPrefs(
-            *pref_service_,
-            prefs::kDismissedForeignSessionsSuggestions)) {}
-
-  ~PrefsPruningDismissedItemFilter() {
-    prefs::StoreDismissedIDsToPrefs(pref_service_,
-                                    prefs::kDismissedForeignSessionsSuggestions,
-                                    active_dismissed_ids_);
-  }
-
-  // Returns a Callback that can be easily used to filter out ids. Should not be
-  // stored anywhere, the filter should always outlive the returned callback.
-  DismissedFilter ToCallback() {
-    return base::Bind(&PrefsPruningDismissedItemFilter::ShouldInclude,
-                      base::Unretained(this));
-  }
-
- private:
-  bool ShouldInclude(const std::string& id) {
-    if (initial_dismissed_ids_.find(id) == initial_dismissed_ids_.end()) {
-      return true;
-    }
-    active_dismissed_ids_.insert(id);
-    return false;
-  }
-
-  PrefService* pref_service_;
-
-  // Ids that we know should be filterd out.
-  std::set<std::string> initial_dismissed_ids_;
-
-  // Ids that we have seen and were filtered out. This will be what is saved to
-  // preferences upon our destructor.
-  std::set<std::string> active_dismissed_ids_;
-
-  DISALLOW_COPY_AND_ASSIGN(PrefsPruningDismissedItemFilter);
-};
-
-// This filter only lets through ids that should normally be filtered out. As
-// such, this filter should only be used when purposely trying to view dismissed
-// content.
-class InverseDismissedItemFilter {
- public:
-  explicit InverseDismissedItemFilter(PrefService* pref_service)
-      : dismissed_ids_(prefs::ReadDismissedIDsFromPrefs(
-            *pref_service,
-            prefs::kDismissedForeignSessionsSuggestions)) {}
-
-  // Returns a Callback that can be easily used to filter out ids. Should not be
-  // stored anywhere, the filter should always outlive the returned callback.
-  DismissedFilter ToCallback() {
-    return base::Bind(&InverseDismissedItemFilter::ShouldInclude,
-                      base::Unretained(this));
-  }
-
- private:
-  bool ShouldInclude(const std::string& id) {
-    return dismissed_ids_.find(id) != dismissed_ids_.end();
-  }
-
-  std::set<std::string> dismissed_ids_;
-
-  DISALLOW_COPY_AND_ASSIGN(InverseDismissedItemFilter);
-};
-
-}  // namespace
-
-// Collection of pointers to various sessions objects that contain a superset of
-// the information needed to create a single suggestion.
-struct ForeignSessionsSuggestionsProvider::SessionData {
-  const sync_sessions::SyncedSession* session;
-  const sessions::SessionTab* tab;
-  const sessions::SerializedNavigationEntry* navigation;
-  bool operator<(const SessionData& other) const {
-    // Note that SerializedNavigationEntry::timestamp() is never set to a
-    // value, so always use SessionTab::timestamp() instead.
-    // TODO(skym): It might be better if we sorted by recency of session, and
-    // only then by recency of the tab. Right now this causes a single
-    // device's tabs to be interleaved with another devices' tabs.
-    return tab->timestamp > other.tab->timestamp;
-  }
-};
-
-ForeignSessionsSuggestionsProvider::ForeignSessionsSuggestionsProvider(
-    ContentSuggestionsProvider::Observer* observer,
-    std::unique_ptr<ForeignSessionsProvider> foreign_sessions_provider,
-    PrefService* pref_service)
-    : ContentSuggestionsProvider(observer),
-      category_status_(CategoryStatus::INITIALIZING),
-      provided_category_(
-          Category::FromKnownCategory(KnownCategories::FOREIGN_TABS)),
-      foreign_sessions_provider_(std::move(foreign_sessions_provider)),
-      pref_service_(pref_service) {
-  foreign_sessions_provider_->SubscribeForForeignTabChange(
-      base::Bind(&ForeignSessionsSuggestionsProvider::OnForeignTabChange,
-                 base::Unretained(this)));
-
-  // If sync is already initialzed, try suggesting now, though this is unlikely.
-  OnForeignTabChange();
-}
-
-ForeignSessionsSuggestionsProvider::~ForeignSessionsSuggestionsProvider() =
-    default;
-
-// static
-void ForeignSessionsSuggestionsProvider::RegisterProfilePrefs(
-    PrefRegistrySimple* registry) {
-  registry->RegisterListPref(prefs::kDismissedForeignSessionsSuggestions);
-}
-
-CategoryStatus ForeignSessionsSuggestionsProvider::GetCategoryStatus(
-    Category category) {
-  DCHECK_EQ(category, provided_category_);
-  return category_status_;
-}
-
-CategoryInfo ForeignSessionsSuggestionsProvider::GetCategoryInfo(
-    Category category) {
-  DCHECK_EQ(category, provided_category_);
-  return CategoryInfo(l10n_util::GetStringUTF16(
-                          IDS_NTP_FOREIGN_SESSIONS_SUGGESTIONS_SECTION_HEADER),
-                      ContentSuggestionsCardLayout::MINIMAL_CARD,
-                      ContentSuggestionsAdditionalAction::VIEW_ALL,
-                      /*show_if_empty=*/false,
-                      l10n_util::GetStringUTF16(
-                          IDS_NTP_FOREIGN_SESSIONS_SUGGESTIONS_SECTION_EMPTY));
-}
-
-void ForeignSessionsSuggestionsProvider::DismissSuggestion(
-    const ContentSuggestion::ID& suggestion_id) {
-  // Assume this suggestion is still valid, and blindly add it to dismissals.
-  // Pruning will happen the next time we are asked to suggest.
-  std::set<std::string> dismissed_ids = prefs::ReadDismissedIDsFromPrefs(
-      *pref_service_, prefs::kDismissedForeignSessionsSuggestions);
-  dismissed_ids.insert(suggestion_id.id_within_category());
-  prefs::StoreDismissedIDsToPrefs(pref_service_,
-                                  prefs::kDismissedForeignSessionsSuggestions,
-                                  dismissed_ids);
-}
-
-void ForeignSessionsSuggestionsProvider::FetchSuggestionImage(
-    const ContentSuggestion::ID& suggestion_id,
-    ImageFetchedCallback callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), gfx::Image()));
-}
-
-void ForeignSessionsSuggestionsProvider::FetchSuggestionImageData(
-    const ContentSuggestion::ID& suggestion_id,
-    ImageDataFetchedCallback callback) {
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), std::string()));
-}
-
-void ForeignSessionsSuggestionsProvider::Fetch(
-    const Category& category,
-    const std::set<std::string>& known_suggestion_ids,
-    FetchDoneCallback callback) {
-  LOG(DFATAL)
-      << "ForeignSessionsSuggestionsProvider has no |Fetch| functionality!";
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback),
-                                Status(StatusCode::PERMANENT_ERROR,
-                                       "ForeignSessionsSuggestionsProvider "
-                                       "has no |Fetch| functionality!"),
-                                std::vector<ContentSuggestion>()));
-}
-
-void ForeignSessionsSuggestionsProvider::ClearHistory(
-    Time begin,
-    Time end,
-    const base::Callback<bool(const GURL& url)>& filter) {
-  std::set<std::string> dismissed_ids = prefs::ReadDismissedIDsFromPrefs(
-      *pref_service_, prefs::kDismissedForeignSessionsSuggestions);
-  for (auto iter = dismissed_ids.begin(); iter != dismissed_ids.end();) {
-    if (filter.Run(GURL(*iter))) {
-      iter = dismissed_ids.erase(iter);
-    } else {
-      ++iter;
-    }
-  }
-  prefs::StoreDismissedIDsToPrefs(pref_service_,
-                                  prefs::kDismissedForeignSessionsSuggestions,
-                                  dismissed_ids);
-}
-
-void ForeignSessionsSuggestionsProvider::ClearCachedSuggestions() {
-  // Ignored.
-}
-
-void ForeignSessionsSuggestionsProvider::GetDismissedSuggestionsForDebugging(
-    Category category,
-    DismissedSuggestionsCallback callback) {
-  DCHECK_EQ(category, provided_category_);
-  InverseDismissedItemFilter filter(pref_service_);
-  // Use GetSuggestionCandidates instead of BuildSuggestions(), to avoid the
-  // size and duplicate filtering. We want to return a complete list of
-  // everything that could potentially be blocked by the not dismissed filter.
-  std::vector<ContentSuggestion> suggestions;
-  for (auto data : GetSuggestionCandidates(filter.ToCallback())) {
-    suggestions.push_back(BuildSuggestion(data));
-  }
-  std::move(callback).Run(std::move(suggestions));
-}
-
-void ForeignSessionsSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
-    Category category) {
-  DCHECK_EQ(category, provided_category_);
-  pref_service_->ClearPref(prefs::kDismissedForeignSessionsSuggestions);
-}
-
-void ForeignSessionsSuggestionsProvider::OnForeignTabChange() {
-  if (!foreign_sessions_provider_->HasSessionsData()) {
-    if (category_status_ == CategoryStatus::AVAILABLE) {
-      // This is to handle the case where the user disabled sync [sessions] or
-      // logs out after we've already provided actual suggestions.
-      category_status_ = CategoryStatus::NOT_PROVIDED;
-      observer()->OnCategoryStatusChanged(this, provided_category_,
-                                          category_status_);
-    }
-    return;
-  }
-
-  if (category_status_ != CategoryStatus::AVAILABLE) {
-    // The further below logic will overwrite any error state. This is
-    // currently okay because no where in the current implementation does the
-    // status get set to an error state. Should this change, reconsider the
-    // overwriting logic.
-    DCHECK(category_status_ == CategoryStatus::INITIALIZING ||
-           category_status_ == CategoryStatus::NOT_PROVIDED);
-
-    // It is difficult to tell if sync simply has not initialized yet or there
-    // will never be data because the user is signed out or has disabled the
-    // sessions data type. Because this provider is hidden when there are no
-    // results, always just update to AVAILABLE once we might have results.
-    category_status_ = CategoryStatus::AVAILABLE;
-    observer()->OnCategoryStatusChanged(this, provided_category_,
-                                        category_status_);
-  }
-
-  // observer()->OnNewSuggestions must be called even when we have no
-  // suggestions to remove previous suggestions that are now filtered out.
-  observer()->OnNewSuggestions(this, provided_category_, BuildSuggestions());
-}
-
-std::vector<ContentSuggestion>
-ForeignSessionsSuggestionsProvider::BuildSuggestions() {
-  const int max_foreign_tabs_total = GetMaxForeignTabsTotal();
-  const int max_foreign_tabs_per_device = GetMaxForeignTabsPerDevice();
-
-  PrefsPruningDismissedItemFilter filter(pref_service_);
-  std::vector<SessionData> suggestion_candidates =
-      GetSuggestionCandidates(filter.ToCallback());
-  // This sorts by recency so that we keep the most recent entries and they
-  // appear as suggestions in reverse chronological order.
-  std::sort(suggestion_candidates.begin(), suggestion_candidates.end());
-
-  std::vector<ContentSuggestion> suggestions;
-  std::set<std::string> included_urls;
-  std::map<std::string, int> suggestions_per_session;
-  for (const SessionData& candidate : suggestion_candidates) {
-    const std::string& session_tag = candidate.session->session_tag;
-    auto duplicates_iter =
-        included_urls.find(candidate.navigation->virtual_url().spec());
-    auto count_iter = suggestions_per_session.find(session_tag);
-    int count =
-        count_iter == suggestions_per_session.end() ? 0 : count_iter->second;
-
-    // Pick up to max (total and per device) tabs, and ensure no duplicates
-    // are selected. This filtering must be done in a second pass because
-    // this can cause newer tabs occluding less recent tabs, requiring more
-    // than |max_foreign_tabs_per_device| to be considered per device.
-    if (static_cast<int>(suggestions.size()) >= max_foreign_tabs_total ||
-        duplicates_iter != included_urls.end() ||
-        count >= max_foreign_tabs_per_device) {
-      continue;
-    }
-    included_urls.insert(candidate.navigation->virtual_url().spec());
-    suggestions_per_session[session_tag] = count + 1;
-    suggestions.push_back(BuildSuggestion(candidate));
-  }
-
-  return suggestions;
-}
-
-std::vector<ForeignSessionsSuggestionsProvider::SessionData>
-ForeignSessionsSuggestionsProvider::GetSuggestionCandidates(
-    const DismissedFilter& suggestions_filter) {
-  const std::vector<const SyncedSession*>& foreign_sessions =
-      foreign_sessions_provider_->GetAllForeignSessions();
-  const TimeDelta max_foreign_tab_age = GetMaxForeignTabAge();
-  std::vector<SessionData> suggestion_candidates;
-  for (const SyncedSession* session : foreign_sessions) {
-    for (const auto& key_value : session->windows) {
-      for (const std::unique_ptr<SessionTab>& tab :
-           key_value.second->wrapped_window.tabs) {
-        if (tab->navigations.empty()) {
-          continue;
-        }
-
-        const SerializedNavigationEntry& navigation = tab->navigations.back();
-        const std::string id = navigation.virtual_url().spec();
-        // TODO(skym): Filter out internal pages. Tabs that contain only
-        // non-syncable content should never reach the local client. However,
-        // sync will let tabs through whose current navigation entry is
-        // internal, as long as a back or forward navigation entry is valid. We
-        // however, are only currently exposing the current entry, and so we
-        // should ideally exclude these.
-        TimeDelta tab_age = Time::Now() - tab->timestamp;
-        if (tab_age < max_foreign_tab_age && suggestions_filter.Run(id)) {
-          suggestion_candidates.push_back(
-              SessionData{session, tab.get(), &navigation});
-        }
-      }
-    }
-  }
-  return suggestion_candidates;
-}
-
-ContentSuggestion ForeignSessionsSuggestionsProvider::BuildSuggestion(
-    const SessionData& data) {
-  ContentSuggestion suggestion(provided_category_,
-                               data.navigation->virtual_url().spec(),
-                               data.navigation->virtual_url());
-  suggestion.set_title(data.navigation->title());
-  suggestion.set_publish_date(data.tab->timestamp);
-  suggestion.set_publisher_name(
-      base::UTF8ToUTF16(data.navigation->virtual_url().host()));
-  return suggestion;
-}
-
-}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h b/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h
deleted file mode 100644
index 0e86c2e8..0000000
--- a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_NTP_SNIPPETS_SESSIONS_FOREIGN_SESSIONS_SUGGESTIONS_PROVIDER_H_
-#define COMPONENTS_NTP_SNIPPETS_SESSIONS_FOREIGN_SESSIONS_SUGGESTIONS_PROVIDER_H_
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "components/ntp_snippets/category.h"
-#include "components/ntp_snippets/category_status.h"
-#include "components/ntp_snippets/content_suggestions_provider.h"
-#include "components/sessions/core/session_types.h"
-#include "components/sync_sessions/synced_session.h"
-
-class PrefRegistrySimple;
-class PrefService;
-
-namespace ntp_snippets {
-
-// Simple interface to get foreign tab data on demand and on change.
-class ForeignSessionsProvider {
- public:
-  virtual ~ForeignSessionsProvider() = default;
-  virtual bool HasSessionsData() = 0;
-  virtual std::vector<const sync_sessions::SyncedSession*>
-  GetAllForeignSessions() = 0;
-  // Should only be called at most once.
-  virtual void SubscribeForForeignTabChange(
-      const base::Closure& change_callback) = 0;
-};
-
-// Provides content suggestions from foreign sessions.
-class ForeignSessionsSuggestionsProvider : public ContentSuggestionsProvider {
- public:
-  ForeignSessionsSuggestionsProvider(
-      ContentSuggestionsProvider::Observer* observer,
-      std::unique_ptr<ForeignSessionsProvider> foreign_sessions_provider,
-      PrefService* pref_service);
-  ~ForeignSessionsSuggestionsProvider() override;
-
-  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
-
- private:
-  friend class ForeignSessionsSuggestionsProviderTest;
-  struct SessionData;
-
-  // ContentSuggestionsProvider implementation.
-  CategoryStatus GetCategoryStatus(Category category) override;
-  CategoryInfo GetCategoryInfo(Category category) override;
-  void DismissSuggestion(const ContentSuggestion::ID& suggestion_id) override;
-  void FetchSuggestionImage(const ContentSuggestion::ID& suggestion_id,
-                            ImageFetchedCallback callback) override;
-  void FetchSuggestionImageData(const ContentSuggestion::ID& suggestion_id,
-                                ImageDataFetchedCallback callback) override;
-  void Fetch(const Category& category,
-             const std::set<std::string>& known_suggestion_ids,
-             FetchDoneCallback callback) override;
-  void ClearHistory(
-      base::Time begin,
-      base::Time end,
-      const base::Callback<bool(const GURL& url)>& filter) override;
-  void ClearCachedSuggestions() override;
-  void GetDismissedSuggestionsForDebugging(
-      Category category,
-      DismissedSuggestionsCallback callback) override;
-  void ClearDismissedSuggestionsForDebugging(Category category) override;
-
-  void OnForeignTabChange();
-  std::vector<ContentSuggestion> BuildSuggestions();
-  std::vector<SessionData> GetSuggestionCandidates(
-      const base::Callback<bool(const std::string& id)>& suggestions_filter);
-  ContentSuggestion BuildSuggestion(const SessionData& data);
-
-  CategoryStatus category_status_;
-  const Category provided_category_;
-  std::unique_ptr<ForeignSessionsProvider> foreign_sessions_provider_;
-  PrefService* pref_service_;
-
-  DISALLOW_COPY_AND_ASSIGN(ForeignSessionsSuggestionsProvider);
-};
-
-}  // namespace ntp_snippets
-
-#endif  // COMPONENTS_NTP_SNIPPETS_SESSIONS_FOREIGN_SESSIONS_SUGGESTIONS_PROVIDER_H_
diff --git a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc b/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc
deleted file mode 100644
index 586aba80..0000000
--- a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h"
-
-#include <map>
-#include <utility>
-
-#include "base/callback_forward.h"
-#include "base/strings/string_number_conversions.h"
-#include "components/ntp_snippets/category.h"
-#include "components/ntp_snippets/content_suggestions_provider.h"
-#include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
-#include "components/prefs/testing_pref_service.h"
-#include "components/sessions/core/serialized_navigation_entry.h"
-#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
-#include "components/sessions/core/session_types.h"
-#include "components/sync_sessions/synced_session.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::Time;
-using base::TimeDelta;
-using sessions::SerializedNavigationEntry;
-using sessions::SessionTab;
-using sessions::SessionWindow;
-using sync_sessions::SyncedSession;
-using sync_sessions::SyncedSessionWindow;
-using testing::ElementsAre;
-using testing::IsEmpty;
-using testing::Property;
-using testing::Test;
-using testing::_;
-
-namespace ntp_snippets {
-namespace {
-
-const char kUrl1[] = "http://www.fake1.com/";
-const char kUrl2[] = "http://www.fake2.com/";
-const char kUrl3[] = "http://www.fake3.com/";
-const char kUrl4[] = "http://www.fake4.com/";
-const char kUrl5[] = "http://www.fake5.com/";
-const char kUrl6[] = "http://www.fake6.com/";
-const char kUrl7[] = "http://www.fake7.com/";
-const char kUrl8[] = "http://www.fake8.com/";
-const char kUrl9[] = "http://www.fake9.com/";
-const char kUrl10[] = "http://www.fake10.com/";
-const char kUrl11[] = "http://www.fake11.com/";
-const char kTitle[] = "title is ignored";
-
-SessionWindow* GetOrCreateWindow(SyncedSession* session, int window_id) {
-  SessionID id = SessionID::FromSerializedValue(window_id);
-  if (session->windows.find(id) == session->windows.end()) {
-    session->windows[id] = std::make_unique<SyncedSessionWindow>();
-  }
-
-  return &session->windows[id]->wrapped_window;
-}
-
-void AddTabToSession(SyncedSession* session,
-                     int window_id,
-                     const std::string& url,
-                     TimeDelta age) {
-  SerializedNavigationEntry navigation =
-      sessions::SerializedNavigationEntryTestHelper::CreateNavigation(url,
-                                                                      kTitle);
-
-  std::unique_ptr<SessionTab> tab = std::make_unique<SessionTab>();
-  tab->timestamp = Time::Now() - age;
-  tab->navigations.push_back(navigation);
-
-  SessionWindow* window = GetOrCreateWindow(session, window_id);
-  // The window deletes the tabs it points at upon destruction.
-  window->tabs.push_back(std::move(tab));
-}
-
-class FakeForeignSessionsProvider : public ForeignSessionsProvider {
- public:
-  ~FakeForeignSessionsProvider() override = default;
-  void SetAllForeignSessions(std::vector<const SyncedSession*> sessions) {
-    sessions_ = std::move(sessions);
-    change_callback_.Run();
-  }
-
-  // ForeignSessionsProvider implementation.
-  void SubscribeForForeignTabChange(
-      const base::Closure& change_callback) override {
-    change_callback_ = change_callback;
-  }
-  bool HasSessionsData() override { return true; }
-  std::vector<const sync_sessions::SyncedSession*> GetAllForeignSessions()
-      override {
-    return sessions_;
-  }
-
- private:
-  std::vector<const SyncedSession*> sessions_;
-  base::Closure change_callback_;
-};
-}  // namespace
-
-class ForeignSessionsSuggestionsProviderTest : public Test {
- public:
-  ForeignSessionsSuggestionsProviderTest() {
-    ForeignSessionsSuggestionsProvider::RegisterProfilePrefs(
-        pref_service_.registry());
-
-    std::unique_ptr<FakeForeignSessionsProvider>
-        fake_foreign_sessions_provider =
-            std::make_unique<FakeForeignSessionsProvider>();
-    fake_foreign_sessions_provider_ = fake_foreign_sessions_provider.get();
-
-    // During the provider's construction the following mock calls occur.
-    EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), IsEmpty()));
-    EXPECT_CALL(*observer(), OnCategoryStatusChanged(
-                                 _, category(), CategoryStatus::AVAILABLE));
-
-    provider_ = std::make_unique<ForeignSessionsSuggestionsProvider>(
-        &observer_, std::move(fake_foreign_sessions_provider), &pref_service_);
-  }
-
- protected:
-  SyncedSession* GetOrCreateSession(int session_id) {
-    if (sessions_map_.find(session_id) == sessions_map_.end()) {
-      std::string id_as_string = base::IntToString(session_id);
-      std::unique_ptr<SyncedSession> owned_session =
-          std::make_unique<SyncedSession>();
-      owned_session->session_tag = id_as_string;
-      owned_session->session_name = id_as_string;
-      sessions_map_[session_id] = std::move(owned_session);
-    }
-    return sessions_map_[session_id].get();
-  }
-
-  void AddTab(int session_id,
-              int window_id,
-              const std::string& url,
-              TimeDelta age) {
-    AddTabToSession(GetOrCreateSession(session_id), window_id, url, age);
-  }
-
-  void ClearSessionData() { sessions_map_.clear(); }
-
-  void TriggerOnChange() {
-    std::vector<const SyncedSession*> sessions;
-    for (const auto& kv : sessions_map_) {
-      sessions.push_back(kv.second.get());
-    }
-    fake_foreign_sessions_provider_->SetAllForeignSessions(std::move(sessions));
-  }
-
-  void Dismiss(const std::string& url) {
-    // The url of a given suggestion is used as the |id_within_category|.
-    provider_->DismissSuggestion(ContentSuggestion::ID(category(), url));
-  }
-
-  Category category() {
-    return Category::FromKnownCategory(KnownCategories::FOREIGN_TABS);
-  }
-
-  MockContentSuggestionsProviderObserver* observer() { return &observer_; }
-
- private:
-  FakeForeignSessionsProvider* fake_foreign_sessions_provider_;
-  MockContentSuggestionsProviderObserver observer_;
-  TestingPrefServiceSimple pref_service_;
-  std::unique_ptr<ForeignSessionsSuggestionsProvider> provider_;
-  std::map<int, std::unique_ptr<SyncedSession>> sessions_map_;
-
-  DISALLOW_COPY_AND_ASSIGN(ForeignSessionsSuggestionsProviderTest);
-};
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, Empty) {
-  // When no sessions data is added, expect no suggestions.
-  EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), IsEmpty()));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, Single) {
-  // Expect a single valid tab because that is what has been added.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, Old) {
-  // The only sessions data is too old to be suggested, so expect empty.
-  EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), IsEmpty()));
-  AddTab(0, 0, kUrl1, TimeDelta::FromHours(4));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, Ordered) {
-  // Suggestions ordering should be in reverse chronological order, or youngest
-  // first.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
-                              Property(&ContentSuggestion::url, GURL(kUrl2)),
-                              Property(&ContentSuggestion::url, GURL(kUrl3)),
-                              Property(&ContentSuggestion::url, GURL(kUrl4)))));
-  AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
-  AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
-  AddTab(0, 1, kUrl3, TimeDelta::FromMinutes(3));
-  AddTab(1, 0, kUrl1, TimeDelta::FromMinutes(1));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, MaxPerDevice) {
-  // Each device, which is to equivalent a unique |session_tag|, has a limit to
-  // the number of suggestions it is allowed to contribute. Here all four
-  // suggestions are within the recency threshold, but only three are allowed
-  // per device. As such, expect that the oldest of the four will not be
-  // suggested.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
-                              Property(&ContentSuggestion::url, GURL(kUrl2)),
-                              Property(&ContentSuggestion::url, GURL(kUrl3)))));
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
-  AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
-  AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, MaxTotal) {
-  // There's a limit to the total nubmer of suggestions that the provider will
-  // ever return, which should be ten. Here there are eleven valid suggestion
-  // entries, spread out over multiple devices/sessions to avoid the per device
-  // cutoff. Expect that the least recent of the eleven to be dropped.
-  EXPECT_CALL(
-      *observer(),
-      OnNewSuggestions(
-          _, category(),
-          ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
-                      Property(&ContentSuggestion::url, GURL(kUrl2)),
-                      Property(&ContentSuggestion::url, GURL(kUrl3)),
-                      Property(&ContentSuggestion::url, GURL(kUrl4)),
-                      Property(&ContentSuggestion::url, GURL(kUrl5)),
-                      Property(&ContentSuggestion::url, GURL(kUrl6)),
-                      Property(&ContentSuggestion::url, GURL(kUrl7)),
-                      Property(&ContentSuggestion::url, GURL(kUrl8)),
-                      Property(&ContentSuggestion::url, GURL(kUrl9)),
-                      Property(&ContentSuggestion::url, GURL(kUrl10)))));
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
-  AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
-  AddTab(1, 0, kUrl4, TimeDelta::FromMinutes(4));
-  AddTab(1, 0, kUrl5, TimeDelta::FromMinutes(5));
-  AddTab(1, 0, kUrl6, TimeDelta::FromMinutes(6));
-  AddTab(2, 0, kUrl7, TimeDelta::FromMinutes(7));
-  AddTab(2, 0, kUrl8, TimeDelta::FromMinutes(8));
-  AddTab(2, 0, kUrl9, TimeDelta::FromMinutes(9));
-  AddTab(3, 0, kUrl10, TimeDelta::FromMinutes(10));
-  AddTab(3, 0, kUrl11, TimeDelta::FromMinutes(11));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, Duplicates) {
-  // The same url is never suggested more than once at a time. All the session
-  // data has the same url so only expect a single suggestion.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  AddTab(0, 1, kUrl1, TimeDelta::FromMinutes(2));
-  AddTab(1, 1, kUrl1, TimeDelta::FromMinutes(3));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, DuplicatesChangingOtherSession) {
-  // Normally |kUrl4| wouldn't show up, because session_id=0 already has 3
-  // younger tabs, but session_id=1 has a younger |kUrl3| which gives |kUrl4| a
-  // spot.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl3)),
-                              Property(&ContentSuggestion::url, GURL(kUrl1)),
-                              Property(&ContentSuggestion::url, GURL(kUrl2)),
-                              Property(&ContentSuggestion::url, GURL(kUrl4)))));
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
-  AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
-  AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
-  AddTab(1, 0, kUrl3, TimeDelta::FromMinutes(0));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, Dismissed) {
-  // Dimissed urls should not be suggested.
-  EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), IsEmpty()));
-  Dismiss(kUrl1);
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, DismissedChangingOwnSession) {
-  // Similar to DuplicatesChangingOtherSession, without dismissals we would
-  // expect urls 1-3. However, because of dismissals we reach all the down to
-  // |kUrl5| before the per device cutoff is hit.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl2)),
-                              Property(&ContentSuggestion::url, GURL(kUrl3)),
-                              Property(&ContentSuggestion::url, GURL(kUrl5)))));
-  Dismiss(kUrl1);
-  Dismiss(kUrl4);
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
-  AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
-  AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
-  AddTab(0, 0, kUrl5, TimeDelta::FromMinutes(5));
-  AddTab(0, 0, kUrl6, TimeDelta::FromMinutes(6));
-  TriggerOnChange();
-}
-
-TEST_F(ForeignSessionsSuggestionsProviderTest, DismissedPruning) {
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
-                              Property(&ContentSuggestion::url, GURL(kUrl2)),
-                              Property(&ContentSuggestion::url, GURL(kUrl3)))));
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
-  AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
-  TriggerOnChange();
-
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
-                              Property(&ContentSuggestion::url, GURL(kUrl3)))));
-  Dismiss(kUrl2);
-  TriggerOnChange();
-
-  // This case is important because it verifies the dismissal of |kUrl2| from
-  // above is still around.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
-  Dismiss(kUrl3);
-  TriggerOnChange();
-
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
-  // kUrl2 is no longer present, which should result in the dismissal being
-  // pruned during the next round of suggestions.
-  ClearSessionData();
-  AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
-  TriggerOnChange();
-
-  // Verify that kUrl2 is now allowed, and the previous dismissal was pruned.
-  EXPECT_CALL(*observer(),
-              OnNewSuggestions(
-                  _, category(),
-                  ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
-                              Property(&ContentSuggestion::url, GURL(kUrl2)))));
-  AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
-  TriggerOnChange();
-}
-
-}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.cc b/components/ntp_snippets/sessions/tab_delegate_sync_adapter.cc
deleted file mode 100644
index 59eda97..0000000
--- a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/ntp_snippets/sessions/tab_delegate_sync_adapter.h"
-
-#include "components/sync/driver/sync_service.h"
-#include "components/sync_sessions/open_tabs_ui_delegate.h"
-
-using syncer::SyncService;
-using sync_sessions::OpenTabsUIDelegate;
-
-namespace ntp_snippets {
-
-TabDelegateSyncAdapter::TabDelegateSyncAdapter(SyncService* sync_service)
-    : sync_service_(sync_service) {
-  sync_service_->AddObserver(this);
-}
-
-TabDelegateSyncAdapter::~TabDelegateSyncAdapter() {
-  sync_service_->RemoveObserver(this);
-}
-
-bool TabDelegateSyncAdapter::HasSessionsData() {
-  // GetOpenTabsUIDelegate will be a nullptr if sync has not started, or if the
-  // sessions data type is not enabled.
-  return sync_service_->GetOpenTabsUIDelegate() != nullptr;
-}
-
-std::vector<const sync_sessions::SyncedSession*>
-TabDelegateSyncAdapter::GetAllForeignSessions() {
-  std::vector<const sync_sessions::SyncedSession*> sessions;
-  OpenTabsUIDelegate* delegate = sync_service_->GetOpenTabsUIDelegate();
-  if (delegate != nullptr) {
-    // The return bool from GetAllForeignSessions(...) is ignored.
-    delegate->GetAllForeignSessions(&sessions);
-  }
-  return sessions;
-}
-
-void TabDelegateSyncAdapter::SubscribeForForeignTabChange(
-    const base::Closure& change_callback) {
-  DCHECK(change_callback_.is_null());
-  change_callback_ = change_callback;
-}
-
-void TabDelegateSyncAdapter::OnStateChanged(syncer::SyncService* sync) {
-  // OnStateChanged gets called very frequently, and usually is not important.
-  // But there are some events, like disabling sync and signing out, that are
-  // only captured through OnStateChange. In an attempt to send as few messages
-  // as possible, track if there was session data, and always/only invoke the
-  // callback when transitioning between states. This will also capture the case
-  // when Open Tab is added/removed from syncing types. Note that this requires
-  // the object behind GetOpenTabsUIDelegate() to have its real data when it
-  // becomes available. Otherwise we might transition to think we have session
-  // data, but invoke our callback while the GetOpenTabsUIDelegate() returns bad
-  // results. Fortunately, this isn't a problem. GetOpenTabsUIDelegate() is
-  // guarded by verifying the data type is RUNNING, which always means the
-  // sessions merge has already happened.
-  if (had_session_data_ != HasSessionsData()) {
-    InvokeCallback();
-  }
-}
-
-void TabDelegateSyncAdapter::OnSyncConfigurationCompleted(
-    syncer::SyncService* sync) {
-  // Ignored. This event can let us know when the set of enabled data types
-  // change. However, we want to avoid useless notifications as much as
-  // possible, and all of the information captured in this event will also be
-  // covered by OnStateChange.
-}
-
-void TabDelegateSyncAdapter::OnForeignSessionUpdated(
-    syncer::SyncService* sync) {
-  // Foreign tab data changed, always invoke the callback to generate new
-  // suggestions. Interestingly, this is only triggered after sync model type
-  // apply, not after merge. The merge case should always be handled by
-  // OnStateChange.
-  InvokeCallback();
-}
-
-void TabDelegateSyncAdapter::InvokeCallback() {
-  had_session_data_ = HasSessionsData();
-  if (!change_callback_.is_null()) {
-    change_callback_.Run();
-  }
-}
-
-}  // namespace ntp_snippets
diff --git a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.h b/components/ntp_snippets/sessions/tab_delegate_sync_adapter.h
deleted file mode 100644
index c14a10a..0000000
--- a/components/ntp_snippets/sessions/tab_delegate_sync_adapter.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_NTP_SNIPPETS_SESSIONS_TAB_DELEGATE_SYNC_ADAPTER_H_
-#define COMPONENTS_NTP_SNIPPETS_SESSIONS_TAB_DELEGATE_SYNC_ADAPTER_H_
-
-#include <vector>
-
-#include "base/callback.h"
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h"
-#include "components/sync/driver/sync_service_observer.h"
-
-namespace syncer {
-class SyncService;
-}  // namespace syncer
-
-namespace ntp_snippets {
-
-// Adapter that sits on top of SyncService and OpenTabsUIDelegate and provides
-// simplified notifications and accessors for foreign tabs data.
-class TabDelegateSyncAdapter : public syncer::SyncServiceObserver,
-                               public ForeignSessionsProvider {
- public:
-  explicit TabDelegateSyncAdapter(syncer::SyncService* sync_service);
-  ~TabDelegateSyncAdapter() override;
-
-  // ForeignSessionsProvider implementation.
-  bool HasSessionsData() override;
-  std::vector<const sync_sessions::SyncedSession*> GetAllForeignSessions()
-      override;
-  void SubscribeForForeignTabChange(
-      const base::Closure& change_callback) override;
-
- private:
-  // syncer::SyncServiceObserver implementation.
-  void OnStateChanged(syncer::SyncService* sync) override;
-  void OnSyncConfigurationCompleted(syncer::SyncService* sync) override;
-  void OnForeignSessionUpdated(syncer::SyncService* sync) override;
-
-  void InvokeCallback();
-
-  syncer::SyncService* sync_service_;
-  base::Closure change_callback_;
-
-  // Represents whether there was session data the last time |change_callback_|
-  // was invoked.
-  bool had_session_data_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(TabDelegateSyncAdapter);
-};
-
-}  // namespace ntp_snippets
-
-#endif  // COMPONENTS_NTP_SNIPPETS_SESSIONS_TAB_DELEGATE_SYNC_ADAPTER_H_
diff --git a/components/ntp_snippets/sessions/tab_delegate_sync_adapter_unittest.cc b/components/ntp_snippets/sessions/tab_delegate_sync_adapter_unittest.cc
deleted file mode 100644
index cf6fe74..0000000
--- a/components/ntp_snippets/sessions/tab_delegate_sync_adapter_unittest.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/ntp_snippets/sessions/tab_delegate_sync_adapter.h"
-
-#include <string>
-
-#include "base/macros.h"
-#include "components/sync/driver/fake_sync_service.h"
-#include "components/sync_sessions/open_tabs_ui_delegate.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::RefCountedMemory;
-using sessions::SessionTab;
-using sessions::SessionWindow;
-using syncer::SyncServiceObserver;
-using sync_sessions::SyncedSession;
-using sync_sessions::OpenTabsUIDelegate;
-using testing::Test;
-
-namespace ntp_snippets {
-namespace {
-
-class TestSyncService : public syncer::FakeSyncService {
- public:
-  TestSyncService() {}
-  OpenTabsUIDelegate* GetOpenTabsUIDelegate() override { return tabs_; }
-  OpenTabsUIDelegate* tabs_ = nullptr;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestSyncService);
-};
-
-class MockOpenTabsUIDelegate : public OpenTabsUIDelegate {
- public:
-  MockOpenTabsUIDelegate() {}
-  MOCK_CONST_METHOD2(GetSyncedFaviconForPageURL,
-                     bool(const std::string&,
-                          scoped_refptr<RefCountedMemory>*));
-  MOCK_METHOD1(GetAllForeignSessions, bool(std::vector<const SyncedSession*>*));
-  MOCK_METHOD3(GetForeignTab,
-               bool(const std::string&, SessionID, const SessionTab**));
-  MOCK_METHOD1(DeleteForeignSession, void(const std::string&));
-  MOCK_METHOD2(GetForeignSession,
-               bool(const std::string&, std::vector<const SessionWindow*>*));
-  MOCK_METHOD2(GetForeignSessionTabs,
-               bool(const std::string&, std::vector<const SessionTab*>*));
-  MOCK_METHOD1(GetLocalSession, bool(const SyncedSession**));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockOpenTabsUIDelegate);
-};
-
-class TabDelegateSyncAdapterTest : public Test {
- public:
-  TabDelegateSyncAdapterTest() : adapter_(service()) {
-    adapter_.SubscribeForForeignTabChange(base::Bind(
-        &TabDelegateSyncAdapterTest::OnChange, base::Unretained(this)));
-  }
-
-  syncer::SyncService* service() { return &service_; }
-  SyncServiceObserver* observer() { return &adapter_; }
-
-  void SetHasOpenTabs(bool is_enabled) {
-    service_.tabs_ = is_enabled ? &tabs_ : nullptr;
-  }
-
-  void OnChange() { ++callback_count_; }
-
-  int CallbackCount() { return callback_count_; }
-
- private:
-  MockOpenTabsUIDelegate tabs_;
-  TestSyncService service_;
-  TabDelegateSyncAdapter adapter_;
-  int callback_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(TabDelegateSyncAdapterTest);
-};
-
-// CallbackCount should only trigger on transitions between having and not
-// having open tabs.
-TEST_F(TabDelegateSyncAdapterTest, CallbackCount) {
-  ASSERT_EQ(0, CallbackCount());
-  observer()->OnStateChanged(service());
-  EXPECT_EQ(0, CallbackCount());
-
-  SetHasOpenTabs(true);
-  observer()->OnStateChanged(service());
-  EXPECT_EQ(1, CallbackCount());
-  observer()->OnStateChanged(service());
-  EXPECT_EQ(1, CallbackCount());
-
-  SetHasOpenTabs(false);
-  observer()->OnStateChanged(service());
-  EXPECT_EQ(2, CallbackCount());
-  observer()->OnStateChanged(service());
-  EXPECT_EQ(2, CallbackCount());
-
-  // OnSyncCycleCompleted should behave like OnStateChanged.
-  observer()->OnSyncCycleCompleted(service());
-  EXPECT_EQ(2, CallbackCount());
-  SetHasOpenTabs(true);
-  observer()->OnSyncCycleCompleted(service());
-  EXPECT_EQ(3, CallbackCount());
-  observer()->OnSyncCycleCompleted(service());
-  EXPECT_EQ(3, CallbackCount());
-}
-
-// No callback should be invoked from OnSyncConfigurationCompleted.
-TEST_F(TabDelegateSyncAdapterTest, OnSyncConfigurationCompleted) {
-  ASSERT_EQ(0, CallbackCount());
-
-  observer()->OnSyncConfigurationCompleted(service());
-  EXPECT_EQ(0, CallbackCount());
-
-  SetHasOpenTabs(true);
-  observer()->OnSyncConfigurationCompleted(service());
-  EXPECT_EQ(0, CallbackCount());
-}
-
-// OnForeignSessionUpdated should always trigger a callback.
-TEST_F(TabDelegateSyncAdapterTest, OnForeignSessionUpdated) {
-  ASSERT_EQ(0, CallbackCount());
-  observer()->OnForeignSessionUpdated(service());
-  EXPECT_EQ(1, CallbackCount());
-  observer()->OnForeignSessionUpdated(service());
-  EXPECT_EQ(2, CallbackCount());
-
-  SetHasOpenTabs(true);
-  observer()->OnForeignSessionUpdated(service());
-  EXPECT_EQ(3, CallbackCount());
-  observer()->OnForeignSessionUpdated(service());
-  EXPECT_EQ(4, CallbackCount());
-}
-
-// If OnForeignSessionUpdated is called before OnStateChanged, then calling
-// OnStateChanged should not trigger a callback.
-TEST_F(TabDelegateSyncAdapterTest, OnForeignSessionUpdatedUpdatesState) {
-  SetHasOpenTabs(true);
-  observer()->OnForeignSessionUpdated(service());
-  EXPECT_EQ(1, CallbackCount());
-
-  observer()->OnStateChanged(service());
-  EXPECT_EQ(1, CallbackCount());
-}
-
-}  // namespace
-}  // namespace ntp_snippets
diff --git a/components/ntp_snippets_strings.grdp b/components/ntp_snippets_strings.grdp
index 8b1c4d7..17dd86b 100644
--- a/components/ntp_snippets_strings.grdp
+++ b/components/ntp_snippets_strings.grdp
@@ -35,14 +35,6 @@
     Your recently visited bookmarks appear here
   </message>
 
-  <message name="IDS_NTP_FOREIGN_SESSIONS_SUGGESTIONS_SECTION_HEADER" desc="Header of the foreign sessions, which is a list of the user's most recently visited tabs on other devices displayed as cards on the New Tab Page.">
-    Tabs from other devices
-  </message>
-
-  <message name="IDS_NTP_FOREIGN_SESSIONS_SUGGESTIONS_SECTION_EMPTY" desc="On the New Tab Page, text of the card explaining to the user that they can expect to see tabs from other devices in this area in the future.">
-    Your recent tabs from other devices appear here
-  </message>
-
   <!-- When you change this string, please change IDS_NTP_PHYSICAL_WEB_PAGE_SUGGESTIONS_SECTION_EMPTY description accordingly. -->
   <message name="IDS_NTP_PHYSICAL_WEB_PAGE_SUGGESTIONS_SECTION_HEADER" desc="Header of the physical web section. The physical web section shows a list of physical web pages available near the user. A physical web page is a URL transmitted over bluetooth by a low power device (a beacon). The user must be at most 100 meters (generally even closer) away from the beacon to receive the URL. This allows the URL to be context based (e.g. one is at a train station and the schedule is available as a physical web page).">
     Nearby
diff --git a/components/omnibox/browser/history_quick_provider_performance_unittest.cc b/components/omnibox/browser/history_quick_provider_performance_unittest.cc
index 5fda86c..000a610 100644
--- a/components/omnibox/browser/history_quick_provider_performance_unittest.cc
+++ b/components/omnibox/browser/history_quick_provider_performance_unittest.cc
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/no_destructor.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_task_environment.h"
@@ -30,7 +31,7 @@
 std::string GenerateFakeHashedString(size_t sym_count) {
   static constexpr char kSyms[] =
       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,/=+?#";
-  CR_DEFINE_STATIC_LOCAL(std::mt19937, engine, ());
+  static base::NoDestructor<std::mt19937> engine;
   std::uniform_int_distribution<size_t> index_distribution(
       0, arraysize(kSyms) - 2 /* trailing \0 */);
 
@@ -38,7 +39,7 @@
   res.reserve(sym_count);
 
   std::generate_n(std::back_inserter(res), sym_count, [&index_distribution] {
-    return kSyms[index_distribution(engine)];
+    return kSyms[index_distribution(*engine)];
   });
 
   return res;
diff --git a/components/omnibox/browser/scored_history_match.cc b/components/omnibox/browser/scored_history_match.cc
index 59c5c144..5e5874a 100644
--- a/components/omnibox/browser/scored_history_match.cc
+++ b/components/omnibox/browser/scored_history_match.cc
@@ -12,6 +12,7 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/no_destructor.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
@@ -641,12 +642,11 @@
     size_t num_matching_pages) const {
   // A mapping from the number of matching pages to their associated document
   // specificity scores.  See omnibox_field_trial.h for more details.
-  CR_DEFINE_STATIC_LOCAL(OmniboxFieldTrial::NumMatchesScores,
-                         default_matches_to_specificity,
-                         (OmniboxFieldTrial::HQPNumMatchesScores()));
+  static base::NoDestructor<OmniboxFieldTrial::NumMatchesScores>
+      default_matches_to_specificity(OmniboxFieldTrial::HQPNumMatchesScores());
   OmniboxFieldTrial::NumMatchesScores* matches_to_specificity =
       matches_to_specificity_override_ ? matches_to_specificity_override_
-                                       : &default_matches_to_specificity;
+                                       : default_matches_to_specificity.get();
 
   // The floating point value below must be less than the lowest score the
   // server would send down.
@@ -662,11 +662,11 @@
                                                  float specificity_score) {
   // |relevance_buckets| gives a mapping from intemerdiate score to the final
   // relevance score.
-  CR_DEFINE_STATIC_LOCAL(ScoreMaxRelevances, default_relevance_buckets,
-                         (GetHQPBuckets()));
+  static base::NoDestructor<ScoreMaxRelevances> default_relevance_buckets(
+      GetHQPBuckets());
   ScoreMaxRelevances* relevance_buckets = relevance_buckets_override_
                                               ? relevance_buckets_override_
-                                              : &default_relevance_buckets;
+                                              : default_relevance_buckets.get();
   DCHECK(!relevance_buckets->empty());
   DCHECK_EQ(0.0, (*relevance_buckets)[0].first);
 
diff --git a/components/omnibox/browser/url_prefix.cc b/components/omnibox/browser/url_prefix.cc
index d4b2137..9136c7e6 100644
--- a/components/omnibox/browser/url_prefix.cc
+++ b/components/omnibox/browser/url_prefix.cc
@@ -5,6 +5,7 @@
 #include "components/omnibox/browser/url_prefix.h"
 
 #include "base/i18n/case_conversion.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 
@@ -28,15 +29,15 @@
 const URLPrefix* BestURLPrefixWithWWWCase(
     const base::string16& lower_text,
     const base::string16& lower_prefix_suffix) {
-  CR_DEFINE_STATIC_LOCAL(URLPrefix, www_prefix,
-                         (base::ASCIIToUTF16("www."), 1));
+  static base::NoDestructor<URLPrefix> www_prefix(base::ASCIIToUTF16("www."),
+                                                  1);
   const URLPrefix* best_prefix =
       BestURLPrefixInternal(lower_text, lower_prefix_suffix);
   if ((best_prefix == nullptr ||
-       best_prefix->num_components < www_prefix.num_components) &&
-      base::StartsWith(lower_text, www_prefix.prefix + lower_prefix_suffix,
+       best_prefix->num_components < www_prefix->num_components) &&
+      base::StartsWith(lower_text, www_prefix->prefix + lower_prefix_suffix,
                        base::CompareCase::SENSITIVE))
-    best_prefix = &www_prefix;
+    best_prefix = www_prefix.get();
   return best_prefix;
 }
 
@@ -50,8 +51,9 @@
 
 // static
 const URLPrefixes& URLPrefix::GetURLPrefixes() {
-  CR_DEFINE_STATIC_LOCAL(URLPrefixes, prefixes, ());
-  if (prefixes.empty()) {
+  static base::NoDestructor<URLPrefixes> prefixes([]() {
+    URLPrefixes prefixes;
+
     // Keep this list in descending number of components.
     prefixes.push_back(URLPrefix(base::ASCIIToUTF16("http://www."), 2));
     prefixes.push_back(URLPrefix(base::ASCIIToUTF16("https://www."), 2));
@@ -60,8 +62,10 @@
     prefixes.push_back(URLPrefix(base::ASCIIToUTF16("https://"), 1));
     prefixes.push_back(URLPrefix(base::ASCIIToUTF16("ftp://"), 1));
     prefixes.push_back(URLPrefix(base::string16(), 0));
-  }
-  return prefixes;
+
+    return prefixes;
+  }());
+  return *prefixes;
 }
 
 // static
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index baafe13..302e1b6 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -52,12 +52,13 @@
   // client has been registered properly.  For example, a client must
   // register with type DEVICE in order to retrieve device policies.
   enum Type {
+    reserved 5;
+
     TT   = 0;             // Register for TT release.
     USER = 1;             // Register for Chrome OS user polices.
     DEVICE = 2;           // Register for Chrome OS device policies.
     BROWSER = 3;          // Register for desktop Chrome browser user policies.
     ANDROID_BROWSER = 4;  // Register for Android Chrome browser user policies.
-    IOS_BROWSER = 5;      // Register for iOS Chrome browser user policies.
   }
   // NOTE: we also use this field to detect client version.  If this
   // field is missing, then the request comes from TT.  We will remove
@@ -273,7 +274,6 @@
   //   google/chrome/machine-level-extension => ExternalPolicyData
   //   google/chromeos/signinextension => ExternalPolicyData
   //   google/android/user => ChromeSettingsProto
-  //   google/ios/user => ChromeSettingsProto
   optional string policy_type = 1;
 
   // This is the last policy timestamp that client received from server. The
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 26b88c1d..71731e9 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -69,9 +69,11 @@
 
 namespace {
 
+#ifndef STATIC_ASSERT_ENUM
 #define STATIC_ASSERT_ENUM(a, b)                            \
   static_assert(static_cast<int>(a) == static_cast<int>(b), \
                 "mismatching enums: " #a)
+#endif
 
 // Check blink and printing enums are kept in sync.
 STATIC_ASSERT_ENUM(blink::kWebUnknownDuplexMode, UNKNOWN_DUPLEX_MODE);
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index 0f0767f..d60dd80 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -233,6 +233,7 @@
     "signin_manager_unittest.cc",
     "signin_metrics_unittest.cc",
     "signin_status_metrics_provider_unittest.cc",
+    "signin_tracker_unittest.cc",
     "webdata/token_service_table_unittest.cc",
   ]
 
diff --git a/components/signin/core/browser/signin_tracker_unittest.cc b/components/signin/core/browser/signin_tracker_unittest.cc
new file mode 100644
index 0000000..279933ed
--- /dev/null
+++ b/components/signin/core/browser/signin_tracker_unittest.cc
@@ -0,0 +1,128 @@
+// Copyright (c) 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.
+
+#include "components/signin/core/browser/signin_tracker.h"
+
+#include "base/compiler_specific.h"
+#include "base/message_loop/message_loop.h"
+#include "build/build_config.h"
+#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/fake_gaia_cookie_manager_service.h"
+#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/fake_signin_manager.h"
+#include "components/signin/core/browser/profile_management_switches.h"
+#include "components/signin/core/browser/signin_switches.h"
+#include "components/signin/core/browser/test_signin_client.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Mock;
+using ::testing::Return;
+using ::testing::ReturnRef;
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+using FakeSigninManagerForTesting = FakeSigninManagerBase;
+#else
+using FakeSigninManagerForTesting = FakeSigninManager;
+#endif  // OS_CHROMEOS
+
+class MockObserver : public SigninTracker::Observer {
+ public:
+  MockObserver() {}
+  ~MockObserver() {}
+
+  MOCK_METHOD1(SigninFailed, void(const GoogleServiceAuthError&));
+  MOCK_METHOD0(SigninSuccess, void(void));
+  MOCK_METHOD1(AccountAddedToCookie, void(const GoogleServiceAuthError&));
+};
+
+}  // namespace
+
+class SigninTrackerTest : public testing::Test {
+ public:
+  SigninTrackerTest()
+      : signin_client_(&pref_service_),
+        fake_oauth2_token_service_(&pref_service_),
+        fake_gaia_cookie_manager_service_(&fake_oauth2_token_service_,
+                                          "signin_tracker_unittest",
+                                          &signin_client_),
+#if defined(OS_CHROMEOS)
+        fake_signin_manager_(&signin_client_, &account_tracker_) {
+#else
+        fake_signin_manager_(&signin_client_,
+                             &fake_oauth2_token_service_,
+                             &account_tracker_,
+                             &fake_gaia_cookie_manager_service_) {
+#endif
+
+    AccountTrackerService::RegisterPrefs(pref_service_.registry());
+    SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
+    SigninManagerBase::RegisterPrefs(pref_service_.registry());
+
+    account_tracker_.Initialize(&pref_service_, base::FilePath());
+  }
+
+  void SetUp() override {
+    tracker_ = std::make_unique<SigninTracker>(
+        &fake_oauth2_token_service_, &fake_signin_manager_,
+        &fake_gaia_cookie_manager_service_, &observer_);
+  }
+
+  void TearDown() override { tracker_.reset(); }
+
+  base::MessageLoop message_loop_;
+  std::unique_ptr<SigninTracker> tracker_;
+  sync_preferences::TestingPrefServiceSyncable pref_service_;
+  AccountTrackerService account_tracker_;
+  TestSigninClient signin_client_;
+  FakeProfileOAuth2TokenService fake_oauth2_token_service_;
+  FakeGaiaCookieManagerService fake_gaia_cookie_manager_service_;
+  FakeSigninManagerForTesting fake_signin_manager_;
+  MockObserver observer_;
+};
+
+#if !defined(OS_CHROMEOS)
+TEST_F(SigninTrackerTest, SignInFails) {
+  const GoogleServiceAuthError error(
+      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+
+  // Signin failure should result in a SigninFailed callback.
+  EXPECT_CALL(observer_, SigninSuccess()).Times(0);
+  EXPECT_CALL(observer_, SigninFailed(error));
+
+  fake_signin_manager_.FailSignin(error);
+}
+#endif  // !defined(OS_CHROMEOS)
+
+TEST_F(SigninTrackerTest, SignInSucceeds) {
+  EXPECT_CALL(observer_, SigninSuccess());
+  EXPECT_CALL(observer_, SigninFailed(_)).Times(0);
+
+  std::string gaia_id = "gaia_id";
+  std::string email = "user@gmail.com";
+  std::string account_id = account_tracker_.SeedAccountInfo(gaia_id, email);
+  fake_signin_manager_.SetAuthenticatedAccountInfo(gaia_id, email);
+  fake_oauth2_token_service_.UpdateCredentials(account_id, "refresh_token");
+}
+
+#if !defined(OS_CHROMEOS)
+TEST_F(SigninTrackerTest, SignInSucceedsWithExistingAccount) {
+  EXPECT_CALL(observer_, SigninSuccess());
+  EXPECT_CALL(observer_, SigninFailed(_)).Times(0);
+
+  std::string gaia_id = "gaia_id";
+  std::string email = "user@gmail.com";
+  std::string account_id = account_tracker_.SeedAccountInfo(gaia_id, email);
+  fake_oauth2_token_service_.UpdateCredentials(account_id, "refresh_token");
+  fake_signin_manager_.SignIn(gaia_id, email, std::string());
+}
+#endif
diff --git a/components/sync/driver/data_type_manager.h b/components/sync/driver/data_type_manager.h
index 5b4866c..c2c68df 100644
--- a/components/sync/driver/data_type_manager.h
+++ b/components/sync/driver/data_type_manager.h
@@ -77,6 +77,12 @@
   // necessary.
   virtual void ReenableType(ModelType type) = 0;
 
+  // Informs the data type manager that the ready-for-start status of a
+  // controller has changed. If the controller is not ready any more, it will
+  // stop |type|. Otherwise, it will trigger reconfiguration so that |type| gets
+  // started again.
+  virtual void ReadyForStartChanged(ModelType type) = 0;
+
   // Resets all data type error state.
   virtual void ResetDataTypeErrors() = 0;
 
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index aa3141f..c6882f6 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -112,6 +112,23 @@
     return;
 
   DVLOG(1) << "Reenabling " << ModelTypeToString(type);
+  ForceReconfiguration();
+}
+
+void DataTypeManagerImpl::ReadyForStartChanged(ModelType type) {
+  const auto& dtc_iter = controllers_->find(type);
+  if (dtc_iter == controllers_->end())
+    return;
+
+  if (dtc_iter->second->ReadyForStart()) {
+    ForceReconfiguration();
+  } else {
+    // Stop the datatype
+    model_association_manager_.StopDatatype(type, DISABLE_SYNC, SyncError());
+  }
+}
+
+void DataTypeManagerImpl::ForceReconfiguration() {
   needs_reconfigure_ = true;
   last_requested_context_.reason = CONFIGURE_REASON_PROGRAMMATIC;
   ProcessReconfigure();
diff --git a/components/sync/driver/data_type_manager_impl.h b/components/sync/driver/data_type_manager_impl.h
index c9614c3..7ad2a47e 100644
--- a/components/sync/driver/data_type_manager_impl.h
+++ b/components/sync/driver/data_type_manager_impl.h
@@ -51,6 +51,7 @@
   void Configure(ModelTypeSet desired_types,
                  const ConfigureContext& context) override;
   void ReenableType(ModelType type) override;
+  void ReadyForStartChanged(ModelType type) override;
   void ResetDataTypeErrors() override;
 
   // Needed only for backend migration.
@@ -145,6 +146,9 @@
   // Post a task to reconfigure when no downloading or association are running.
   void ProcessReconfigure();
 
+  // Programmatically force reconfiguration of data type (if needed).
+  void ForceReconfiguration();
+
   void Restart();
   void DownloadReady(ModelTypeSet types_to_download,
                      ModelTypeSet first_sync_types,
diff --git a/components/sync/driver/data_type_manager_mock.h b/components/sync/driver/data_type_manager_mock.h
index 5f3dc29..4e9779a 100644
--- a/components/sync/driver/data_type_manager_mock.h
+++ b/components/sync/driver/data_type_manager_mock.h
@@ -18,6 +18,7 @@
 
   MOCK_METHOD2(Configure, void(ModelTypeSet, const ConfigureContext&));
   MOCK_METHOD1(ReenableType, void(ModelType));
+  MOCK_METHOD1(ReadyForStartChanged, void(ModelType));
   MOCK_METHOD0(ResetDataTypeErrors, void());
   MOCK_METHOD1(PurgeForMigration, void(ModelTypeSet));
   MOCK_METHOD1(Stop, void(ShutdownReason));
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc
index 53641a9..ac57db9 100644
--- a/components/sync/driver/fake_sync_service.cc
+++ b/components/sync/driver/fake_sync_service.cc
@@ -155,6 +155,8 @@
 
 void FakeSyncService::ReenableDatatype(ModelType type) {}
 
+void FakeSyncService::ReadyForStartChanged(ModelType type) {}
+
 syncer::SyncTokenStatus FakeSyncService::GetSyncTokenStatus() const {
   return syncer::SyncTokenStatus();
 }
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h
index 5bb5898..3b648c2 100644
--- a/components/sync/driver/fake_sync_service.h
+++ b/components/sync/driver/fake_sync_service.h
@@ -73,6 +73,7 @@
   bool IsCryptographerReady(const BaseTransaction* trans) const override;
   UserShare* GetUserShare() const override;
   void ReenableDatatype(ModelType type) override;
+  void ReadyForStartChanged(syncer::ModelType type) override;
   SyncTokenStatus GetSyncTokenStatus() const override;
   bool QueryDetailedSyncStatus(SyncStatus* result) const override;
   base::Time GetLastSyncedTime() const override;
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index 1166697..2826cff8 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -171,11 +171,18 @@
     const ShutdownReason reason = dtc_and_reason.second;
     DVLOG(1) << "ModelAssociationManager: stop " << dtc->name() << " due to "
              << ShutdownReasonToString(reason);
-    StopDatatype(SyncError(), reason, dtc, barrier_closure);
+    StopDatatypeImpl(SyncError(), reason, dtc, barrier_closure);
   }
 }
 
-void ModelAssociationManager::StopDatatype(
+void ModelAssociationManager::StopDatatype(ModelType type,
+                                           ShutdownReason shutdown_reason,
+                                           SyncError error) {
+  DataTypeController* dtc = controllers_->find(type)->second.get();
+  StopDatatypeImpl(error, shutdown_reason, dtc, base::DoNothing());
+}
+
+void ModelAssociationManager::StopDatatypeImpl(
     const SyncError& error,
     ShutdownReason shutdown_reason,
     DataTypeController* dtc,
@@ -286,7 +293,7 @@
         dtc->state() != DataTypeController::STOPPING) {
       // We don't really wait until all datatypes have been fully stopped, which
       // is only required (and in fact waited for) when Initialize() is called.
-      StopDatatype(SyncError(), shutdown_reason, dtc, base::DoNothing());
+      StopDatatypeImpl(SyncError(), shutdown_reason, dtc, base::DoNothing());
       DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name();
     }
   }
@@ -356,7 +363,8 @@
     DVLOG(1) << "ModelAssociationManager: Type encountered an error.";
     desired_types_.Remove(type);
     DataTypeController* dtc = controllers_->find(type)->second.get();
-    StopDatatype(local_merge_result.error(), STOP_SYNC, dtc, base::DoNothing());
+    StopDatatypeImpl(local_merge_result.error(), STOP_SYNC, dtc,
+                     base::DoNothing());
     NotifyDelegateIfReadyForConfigure();
 
     // Update configuration result.
@@ -428,9 +436,9 @@
       UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed",
                                 ModelTypeToHistogramInt(dtc->type()),
                                 static_cast<int>(MODEL_TYPE_COUNT));
-      StopDatatype(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR,
-                             "Association timed out.", dtc->type()),
-                   STOP_SYNC, dtc, base::DoNothing());
+      StopDatatypeImpl(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR,
+                                 "Association timed out.", dtc->type()),
+                       STOP_SYNC, dtc, base::DoNothing());
     }
   }
 
diff --git a/components/sync/driver/model_association_manager.h b/components/sync/driver/model_association_manager.h
index aada6fee..830413e 100644
--- a/components/sync/driver/model_association_manager.h
+++ b/components/sync/driver/model_association_manager.h
@@ -101,6 +101,11 @@
   // When this is completed, |OnModelAssociationDone| will be invoked.
   void StartAssociationAsync(const ModelTypeSet& types_to_associate);
 
+  // Stops an individual datatype |type| for |shutdown_reason|.
+  void StopDatatype(ModelType type,
+                    ShutdownReason shutdown_reason,
+                    SyncError error);
+
   // This is used for TESTING PURPOSE ONLY. The test case can inspect
   // and modify the timer.
   // TODO(sync) : This would go away if we made this class be able to do
@@ -135,10 +140,10 @@
   void ModelAssociationDone(State new_state);
 
   // A helper to stop an individual datatype.
-  void StopDatatype(const SyncError& error,
-                    ShutdownReason shutdown_reason,
-                    DataTypeController* dtc,
-                    DataTypeController::StopCallback callback);
+  void StopDatatypeImpl(const SyncError& error,
+                        ShutdownReason shutdown_reason,
+                        DataTypeController* dtc,
+                        DataTypeController::StopCallback callback);
 
   // Calls delegate's OnAllDataTypesReadyForConfigure when all datatypes from
   // desired_types_ are ready for configure. Ensures that for every call to
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index 0277215..d8fda9f0 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -311,6 +311,12 @@
   // preferred state of a datatype, and is not persisted across restarts.
   virtual void ReenableDatatype(ModelType type) = 0;
 
+  // Informs the data type manager that the ready-for-start status of a
+  // controller has changed. If the controller is not ready any more, it will
+  // stop |type|. Otherwise, it will trigger reconfiguration so that |type| gets
+  // started again.
+  virtual void ReadyForStartChanged(ModelType type) = 0;
+
   //////////////////////////////////////////////////////////////////////////////
   // OBSERVERS
   //////////////////////////////////////////////////////////////////////////////
diff --git a/components/sync/model/entity_data.cc b/components/sync/model/entity_data.cc
index 090f264..e82bbc08 100644
--- a/components/sync/model/entity_data.cc
+++ b/components/sync/model/entity_data.cc
@@ -10,6 +10,7 @@
 
 #include "base/json/json_writer.h"
 #include "base/logging.h"
+#include "base/no_destructor.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/trace_event/memory_usage_estimator.h"
@@ -146,8 +147,8 @@
 }
 
 const EntityData& EntityDataTraits::DefaultValue() {
-  CR_DEFINE_STATIC_LOCAL(EntityData, default_instance, ());
-  return default_instance;
+  static base::NoDestructor<EntityData> default_instance;
+  return *default_instance;
 }
 
 void PrintTo(const EntityData& entity_data, std::ostream* os) {
diff --git a/components/sync_ui_strings.grdp b/components/sync_ui_strings.grdp
index e3f3d49..4247f22 100644
--- a/components/sync_ui_strings.grdp
+++ b/components/sync_ui_strings.grdp
@@ -38,7 +38,7 @@
       You already have data that is encrypted using a different version of your Google Account password. Please enter it below.
     </message>
     <message name="IDS_SYNC_FULL_ENCRYPTION_DATA" desc="Text of the radio that when selected enables full encryption.">
-      Encrypt all synced data with your own sync passphrase
+      Encrypt synced data with your own sync passphrase
     </message>
     <message name="IDS_SYNC_LOGIN_SETTING_UP" desc="A progress message">
       Setting up...
diff --git a/components/ukm/observers/sync_disable_observer.cc b/components/ukm/observers/sync_disable_observer.cc
index beb5dac7..824463a 100644
--- a/components/ukm/observers/sync_disable_observer.cc
+++ b/components/ukm/observers/sync_disable_observer.cc
@@ -4,16 +4,25 @@
 
 #include "components/ukm/observers/sync_disable_observer.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
 #include "components/sync/driver/sync_token_status.h"
 #include "components/sync/engine/connection_status.h"
+#include "components/unified_consent/feature.h"
+#include "components/unified_consent/url_keyed_data_collection_consent_helper.h"
+
+using unified_consent::UrlKeyedDataCollectionConsentHelper;
 
 namespace ukm {
 
 const base::Feature kUkmCheckAuthErrorFeature{"UkmCheckAuthError",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kUkmPurgingOnConnection{"UkmPurgingOnConnection",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
 
 namespace {
 
@@ -34,6 +43,7 @@
   DISABLED_BY_HISTORY_CONNECTED_PASSPHRASE,
   DISABLED_BY_INITIALIZED_CONNECTED_PASSPHRASE,
   DISABLED_BY_HISTORY_INITIALIZED_CONNECTED_PASSPHRASE,
+  DISABLED_BY_ANONYMIZED_DATA_COLLECTION,
   MAX_DISABLE_INFO
 };
 
@@ -43,16 +53,30 @@
 
 }  // namespace
 
-SyncDisableObserver::SyncDisableObserver()
-    : sync_observer_(this),
-      all_histories_enabled_(false),
-      all_extensions_enabled_(false) {}
+SyncDisableObserver::SyncDisableObserver() : sync_observer_(this) {}
 
-SyncDisableObserver::~SyncDisableObserver() {}
+SyncDisableObserver::~SyncDisableObserver() {
+  for (const auto& entry : consent_helpers_) {
+    entry.second->RemoveObserver(this);
+  }
+}
+
+bool SyncDisableObserver::SyncState::AllowsUkm() const {
+  if (anonymized_data_collection_state == DataCollectionState::kIgnored)
+    return history_enabled && initialized && connected && !passphrase_protected;
+  else
+    return anonymized_data_collection_state == DataCollectionState::kEnabled;
+}
+
+bool SyncDisableObserver::SyncState::AllowsUkmWithExtension() const {
+  return AllowsUkm() && extensions_enabled && initialized && connected &&
+         !passphrase_protected;
+}
 
 // static
 SyncDisableObserver::SyncState SyncDisableObserver::GetSyncState(
-    syncer::SyncService* sync_service) {
+    syncer::SyncService* sync_service,
+    UrlKeyedDataCollectionConsentHelper* consent_helper) {
   syncer::SyncTokenStatus status = sync_service->GetSyncTokenStatus();
   SyncState state;
   state.history_enabled = sync_service->GetPreferredDataTypes().Has(
@@ -64,27 +88,45 @@
                     status.connection_status == syncer::CONNECTION_OK;
   state.passphrase_protected =
       state.initialized && sync_service->IsUsingSecondaryPassphrase();
+  if (consent_helper) {
+    state.anonymized_data_collection_state =
+        consent_helper->IsEnabled() ? DataCollectionState::kEnabled
+                                    : DataCollectionState::kDisabled;
+  }
   return state;
 }
 
 void SyncDisableObserver::ObserveServiceForSyncDisables(
     syncer::SyncService* sync_service,
-    PrefService* pref_service) {
-  previous_states_[sync_service] = GetSyncState(sync_service);
+    PrefService* prefs) {
+  std::unique_ptr<UrlKeyedDataCollectionConsentHelper> consent_helper;
+  if (unified_consent::IsUnifiedConsentFeatureEnabled()) {
+    consent_helper = UrlKeyedDataCollectionConsentHelper::
+        NewAnonymizedDataCollectionConsentHelper(prefs, sync_service);
+  }
+
+  SyncState state = GetSyncState(sync_service, consent_helper.get());
+  previous_states_[sync_service] = state;
+
+  if (consent_helper) {
+    consent_helper->AddObserver(this);
+    consent_helpers_[sync_service] = std::move(consent_helper);
+  }
   sync_observer_.Add(sync_service);
   UpdateAllProfileEnabled(false);
 }
 
 void SyncDisableObserver::UpdateAllProfileEnabled(bool must_purge) {
-  bool all_enabled = CheckSyncStateOnAllProfiles();
-  bool all_extensions_enabled =
-      all_enabled && CheckSyncStateForExtensionsOnAllProfiles();
+  bool all_sync_states_allow_ukm = CheckSyncStateOnAllProfiles();
+  bool all_sync_states_allow_extension_ukm =
+      all_sync_states_allow_ukm && CheckSyncStateForExtensionsOnAllProfiles();
   // Any change in sync settings needs to call OnSyncPrefsChanged so that the
   // new settings take effect.
-  if (must_purge || (all_enabled != all_histories_enabled_) ||
-      (all_extensions_enabled != all_extensions_enabled_)) {
-    all_histories_enabled_ = all_enabled;
-    all_extensions_enabled_ = all_extensions_enabled;
+  if (must_purge || (all_sync_states_allow_ukm != all_sync_states_allow_ukm_) ||
+      (all_sync_states_allow_extension_ukm !=
+       all_sync_states_allow_extension_ukm_)) {
+    all_sync_states_allow_ukm_ = all_sync_states_allow_ukm;
+    all_sync_states_allow_extension_ukm_ = all_sync_states_allow_extension_ukm;
     OnSyncPrefsChanged(must_purge);
   }
 }
@@ -94,17 +136,23 @@
     return false;
   for (const auto& kv : previous_states_) {
     const SyncDisableObserver::SyncState& state = kv.second;
-    if (!state.history_enabled || !state.initialized || !state.connected ||
-        state.passphrase_protected) {
+    if (!state.AllowsUkm()) {
       int disabled_by = 0;
-      if (!state.history_enabled)
-        disabled_by |= 1 << 0;
-      if (!state.initialized)
-        disabled_by |= 1 << 1;
-      if (!state.connected)
-        disabled_by |= 1 << 2;
-      if (state.passphrase_protected)
-        disabled_by |= 1 << 3;
+      if (state.anonymized_data_collection_state ==
+          DataCollectionState::kIgnored) {
+        if (!state.history_enabled)
+          disabled_by |= 1 << 0;
+        if (!state.initialized)
+          disabled_by |= 1 << 1;
+        if (!state.connected)
+          disabled_by |= 1 << 2;
+        if (state.passphrase_protected)
+          disabled_by |= 1 << 3;
+      } else {
+        DCHECK_EQ(DataCollectionState::kDisabled,
+                  state.anonymized_data_collection_state);
+        disabled_by |= 1 << 4;
+      }
       RecordDisableInfo(DisableInfo(disabled_by));
       return false;
     }
@@ -125,36 +173,87 @@
 }
 
 void SyncDisableObserver::OnStateChanged(syncer::SyncService* sync) {
+  UrlKeyedDataCollectionConsentHelper* consent_helper = nullptr;
+  auto found = consent_helpers_.find(sync);
+  if (found != consent_helpers_.end())
+    consent_helper = found->second.get();
+  UpdateSyncState(sync, consent_helper);
+}
+
+void SyncDisableObserver::OnUrlKeyedDataCollectionConsentStateChanged(
+    unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper) {
+  DCHECK(consent_helper);
+  syncer::SyncService* sync_service = nullptr;
+  for (const auto& entry : consent_helpers_) {
+    if (consent_helper == entry.second.get()) {
+      sync_service = entry.first;
+      break;
+    }
+  }
+  DCHECK(sync_service);
+  UpdateSyncState(sync_service, consent_helper);
+}
+
+void SyncDisableObserver::UpdateSyncState(
+    syncer::SyncService* sync,
+    UrlKeyedDataCollectionConsentHelper* consent_helper) {
   DCHECK(base::ContainsKey(previous_states_, sync));
-  SyncDisableObserver::SyncState state = GetSyncState(sync);
   const SyncDisableObserver::SyncState& previous_state = previous_states_[sync];
-  bool must_purge =
-      // Trigger a purge if history sync was disabled.
-      (previous_state.history_enabled && !state.history_enabled) ||
-      // Trigger a purge if engine has become disabled.
-      (previous_state.initialized && !state.initialized) ||
-      // Trigger a purge if the user added a passphrase.  Since we can't detect
-      // the use of a passphrase while the engine is not initialized, we may
-      // miss the transition if the user adds a passphrase in this state.
-      (previous_state.initialized && state.initialized &&
-       !previous_state.passphrase_protected && state.passphrase_protected);
+  DCHECK(previous_state.anonymized_data_collection_state ==
+             DataCollectionState::kIgnored ||
+         consent_helper);
+  SyncDisableObserver::SyncState state = GetSyncState(sync, consent_helper);
+
+  // Trigger a purge if sync state no longer allows UKM.
+  // TODO(rkaplow): Clean this up once crbug.com/891777 is resolved.
+  bool must_purge;
+
+  // If unified_consent is used, we keep the logic introduced in
+  // http://crrev.com/c/1152744. Otherwise, if the kUkmPurgingOnConnection
+  // feature is enabled, we still use that logic.
+  if (unified_consent::IsUnifiedConsentFeatureEnabled() ||
+      base::FeatureList::IsEnabled(kUkmPurgingOnConnection)) {
+    // Purge using AllowsUkm which includes connected status.
+    must_purge = previous_state.AllowsUkm() && !state.AllowsUkm();
+  } else {
+    // Use the previous logic to investigate crbug.com/891777.
+    must_purge =
+        // Trigger a purge if history sync was disabled.
+        (previous_state.history_enabled && !state.history_enabled) ||
+        // Trigger a purge if engine has become disabled.
+        (previous_state.initialized && !state.initialized) ||
+        // Trigger a purge if the user added a passphrase.  Since we can't
+        // detect the use of a passphrase while the engine is not initialized,
+        // we may miss the transition if the user adds a passphrase in this
+        // state.
+        (previous_state.initialized && state.initialized &&
+         !previous_state.passphrase_protected && state.passphrase_protected);
+  }
+
+  UMA_HISTOGRAM_BOOLEAN("UKM.SyncDisable.Purge", must_purge);
+
   previous_states_[sync] = state;
   UpdateAllProfileEnabled(must_purge);
 }
 
 void SyncDisableObserver::OnSyncShutdown(syncer::SyncService* sync) {
   DCHECK(base::ContainsKey(previous_states_, sync));
+  auto found = consent_helpers_.find(sync);
+  if (found != consent_helpers_.end()) {
+    found->second->RemoveObserver(this);
+    consent_helpers_.erase(found);
+  }
   sync_observer_.Remove(sync);
   previous_states_.erase(sync);
   UpdateAllProfileEnabled(false);
 }
 
 bool SyncDisableObserver::SyncStateAllowsUkm() {
-  return all_histories_enabled_;
+  return all_sync_states_allow_ukm_;
 }
 
 bool SyncDisableObserver::SyncStateAllowsExtensionUkm() {
-  return all_extensions_enabled_;
+  return all_sync_states_allow_extension_ukm_;
 }
 
 }  // namespace ukm
diff --git a/components/ukm/observers/sync_disable_observer.h b/components/ukm/observers/sync_disable_observer.h
index 2b89842..e70f25a 100644
--- a/components/ukm/observers/sync_disable_observer.h
+++ b/components/ukm/observers/sync_disable_observer.h
@@ -10,16 +10,22 @@
 #include "base/scoped_observer.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_service_observer.h"
+#include "components/unified_consent/url_keyed_data_collection_consent_helper.h"
 
 class PrefService;
 
 namespace ukm {
 
-// Observes the state of a set of SyncServices for changes to history sync
-// preferences.  This is for used to trigger purging of local state when
-// sync is disabled on a profile and disabling recording when any non-syncing
-// profiles are active.
-class SyncDisableObserver : public syncer::SyncServiceObserver {
+// Observer that monitors whether UKM is allowed for all profiles.
+//
+// For one profile, UKM is allowed under the following conditions:
+// * If unified consent is disabled, then UKM is allowed for the profile iff
+//   sync history is active;
+// * If unified consent is enabled, then UKM is allowed for the profile iff
+//   URL-keyed anonymized data collectiion is enabled.
+class SyncDisableObserver
+    : public syncer::SyncServiceObserver,
+      public unified_consent::UrlKeyedDataCollectionConsentHelper::Observer {
  public:
   SyncDisableObserver();
   ~SyncDisableObserver() override;
@@ -28,10 +34,13 @@
   void ObserveServiceForSyncDisables(syncer::SyncService* sync_service,
                                      PrefService* pref_service);
 
-  // Returns true iff sync is in a state that allows UKM to be enabled.
-  // This means that for all profiles, sync is initialized, connected, has the
-  // HISTORY_DELETE_DIRECTIVES data type enabled, and does not have a secondary
-  // passphrase enabled.
+  // Returns true iff all sync states alllow UKM to be enabled. This means that
+  // for all profiles:
+  // * If unified consent is disabled, then sync is initialized, connected, has
+  //   the HISTORY_DELETE_DIRECTIVES data type enabled, and does not have a
+  //   secondary passphrase enabled.
+  // * If unified consent is enabled, then URL-keyed anonymized data collection
+  //   is enabled for that profile.
   virtual bool SyncStateAllowsUkm();
 
   // Returns true iff sync is in a state that allows UKM to capture extensions.
@@ -49,6 +58,11 @@
   void OnStateChanged(syncer::SyncService* sync) override;
   void OnSyncShutdown(syncer::SyncService* sync) override;
 
+  // unified_consent::UrlKeyedDataCollectionConsentHelper::Observer:
+  void OnUrlKeyedDataCollectionConsentStateChanged(
+      unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper)
+      override;
+
   // Recomputes all_profiles_enabled_ state from previous_states_;
   void UpdateAllProfileEnabled(bool must_purge);
 
@@ -64,8 +78,29 @@
   ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
       sync_observer_;
 
+  enum class DataCollectionState {
+    // Matches the case when unified consent feature is disabled
+    kIgnored,
+    // Unified consent feature is enabled and the user has disabled URL-keyed
+    // anonymized data collection.
+    kDisabled,
+    // Unified consent feature is enabled and the user has enabled URL-keyed
+    // anonymized data collection.
+    kEnabled
+  };
+
   // State data about sync services that we need to remember.
   struct SyncState {
+    // Returns true if this sync state allows UKM:
+    // * If unified consent is disabled, then sync is initialized, connected,
+    //   has history data type enabled, and does not have a secondary passphrase
+    //   enabled.
+    // * If unified consent is enabled, then URL-keyed anonymized data
+    //   collection is enabled.
+    bool AllowsUkm() const;
+    // Returns true if |AllowUkm| and if sync extensions are enabled.
+    bool AllowsUkmWithExtension() const;
+
     // If the user has history sync enabled.
     bool history_enabled = false;
     // If the user has extension sync enabled.
@@ -77,21 +112,45 @@
     // Whether user data is hidden by a secondary passphrase.
     // This is not valid if the state is not initialized.
     bool passphrase_protected = false;
+
+    // Whether anonymized data collection is enabled.
+    // Note: This is not managed by sync service. It was added in this enum
+    // for convenience.
+    DataCollectionState anonymized_data_collection_state =
+        DataCollectionState::kIgnored;
   };
 
-  // Gets the current state of a SyncService.
-  static SyncState GetSyncState(syncer::SyncService* sync);
+  // Updates the sync state for |sync| service. Updates all profiles if needed.
+  void UpdateSyncState(
+      syncer::SyncService* sync,
+      unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper);
 
-  // The list of services that had sync enabled when we last checked.
+  // Gets the current state of a SyncService.
+  // A non-null |consent_helper| implies that Unified Consent is enabled.
+  static SyncState GetSyncState(
+      syncer::SyncService* sync,
+      unified_consent::UrlKeyedDataCollectionConsentHelper* consent_helper);
+
+  // The state of the sync services being observed.
   std::map<syncer::SyncService*, SyncState> previous_states_;
 
-  // Tracks if history sync was enabled on all profiles after the last state
-  // change.
-  bool all_histories_enabled_;
+  // The list of URL-keyed anonymized data collection consent helpers.
+  //
+  // Note: UrlKeyedDataCollectionConsentHelper do not rely on sync when
+  // unified consent feature is enabled but there must be exactly one per
+  // Chromium profile. As there is a single sync service per profile, it is safe
+  // to key them by sync service instead of introducing an additional map.
+  std::map<
+      syncer::SyncService*,
+      std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper>>
+      consent_helpers_;
+
+  // Tracks if UKM is allowed on all profiles after the last state change.
+  bool all_sync_states_allow_ukm_ = false;
 
   // Tracks if extension sync was enabled on all profiles after the last state
   // change.
-  bool all_extensions_enabled_;
+  bool all_sync_states_allow_extension_ukm_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(SyncDisableObserver);
 };
diff --git a/components/ukm/observers/sync_disable_observer_unittest.cc b/components/ukm/observers/sync_disable_observer_unittest.cc
index 043c751..cf26268 100644
--- a/components/ukm/observers/sync_disable_observer_unittest.cc
+++ b/components/ukm/observers/sync_disable_observer_unittest.cc
@@ -154,7 +154,7 @@
   EXPECT_FALSE(observer.ResetPurged());
 }
 
-TEST_F(SyncDisableObserverTest, DISABLED_OneEnabled_UnifiedConsentEnabled) {
+TEST_F(SyncDisableObserverTest, OneEnabled_UnifiedConsentEnabled) {
   ScopedUnifiedConsent scoped_unified_consent(
       UnifiedConsentFeatureState::kEnabledNoBump);
   sync_preferences::TestingPrefServiceSyncable prefs;
@@ -247,7 +247,7 @@
   EXPECT_FALSE(observer.ResetPurged());
 }
 
-TEST_F(SyncDisableObserverTest, DISABLED_MixedProfiles_UnifiedConsentEnabled) {
+TEST_F(SyncDisableObserverTest, MixedProfiles_UnifiedConsentEnabled) {
   ScopedUnifiedConsent scoped_unified_consent(
       UnifiedConsentFeatureState::kEnabledNoBump);
   sync_preferences::TestingPrefServiceSyncable prefs1;
@@ -283,7 +283,7 @@
   EXPECT_FALSE(observer.ResetPurged());
 }
 
-TEST_F(SyncDisableObserverTest, DISABLED_TwoEnabled_UnifiedConsentEnabled) {
+TEST_F(SyncDisableObserverTest, TwoEnabled_UnifiedConsentEnabled) {
   ScopedUnifiedConsent scoped_unified_consent(
       UnifiedConsentFeatureState::kEnabledNoBump);
   sync_preferences::TestingPrefServiceSyncable prefs1;
@@ -323,7 +323,7 @@
   EXPECT_FALSE(observer.ResetPurged());
 }
 
-TEST_F(SyncDisableObserverTest, DISABLED_OneAddRemove_UnifiedConsentEnabled) {
+TEST_F(SyncDisableObserverTest, OneAddRemove_UnifiedConsentEnabled) {
   ScopedUnifiedConsent scoped_unified_consent(
       UnifiedConsentFeatureState::kEnabledNoBump);
   sync_preferences::TestingPrefServiceSyncable prefs;
@@ -364,7 +364,7 @@
   EXPECT_FALSE(observer.ResetPurged());
 }
 
-TEST_F(SyncDisableObserverTest, DISABLED_PurgeOnDisable_UnifiedConsentEnabled) {
+TEST_F(SyncDisableObserverTest, PurgeOnDisable_UnifiedConsentEnabled) {
   ScopedUnifiedConsent scoped_unified_consent(
       UnifiedConsentFeatureState::kEnabledNoBump);
 
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc
index 7ec8caf..f6ab459 100644
--- a/components/url_pattern_index/url_pattern_index.cc
+++ b/components/url_pattern_index/url_pattern_index.cc
@@ -11,6 +11,7 @@
 #include "base/containers/flat_map.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/no_destructor.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
 #include "base/strings/string_piece.h"
@@ -36,49 +37,45 @@
 
 // Maps proto::ActivationType to flat::ActivationType.
 const ActivationTypeMap& GetActivationTypeMap() {
-  CR_DEFINE_STATIC_LOCAL(
-      ActivationTypeMap, activation_type_map,
-      (
-          {
-              {proto::ACTIVATION_TYPE_UNSPECIFIED, flat::ActivationType_NONE},
-              {proto::ACTIVATION_TYPE_DOCUMENT, flat::ActivationType_DOCUMENT},
-              // ELEMHIDE is not supported.
-              {proto::ACTIVATION_TYPE_ELEMHIDE, flat::ActivationType_NONE},
-              // GENERICHIDE is not supported.
-              {proto::ACTIVATION_TYPE_GENERICHIDE, flat::ActivationType_NONE},
-              {proto::ACTIVATION_TYPE_GENERICBLOCK,
-               flat::ActivationType_GENERIC_BLOCK},
-          },
-          base::KEEP_FIRST_OF_DUPES));
-  return activation_type_map;
+  static base::NoDestructor<ActivationTypeMap> activation_type_map(
+      std::initializer_list<ActivationTypeMap::value_type>{
+          {proto::ACTIVATION_TYPE_UNSPECIFIED, flat::ActivationType_NONE},
+          {proto::ACTIVATION_TYPE_DOCUMENT, flat::ActivationType_DOCUMENT},
+          // ELEMHIDE is not supported.
+          {proto::ACTIVATION_TYPE_ELEMHIDE, flat::ActivationType_NONE},
+          // GENERICHIDE is not supported.
+          {proto::ACTIVATION_TYPE_GENERICHIDE, flat::ActivationType_NONE},
+          {proto::ACTIVATION_TYPE_GENERICBLOCK,
+           flat::ActivationType_GENERIC_BLOCK},
+      },
+      base::KEEP_FIRST_OF_DUPES);
+  return *activation_type_map;
 }
 
 // Maps proto::ElementType to flat::ElementType.
 const ElementTypeMap& GetElementTypeMap() {
-  CR_DEFINE_STATIC_LOCAL(
-      ElementTypeMap, element_type_map,
-      (
-          {
-              {proto::ELEMENT_TYPE_UNSPECIFIED, flat::ElementType_NONE},
-              {proto::ELEMENT_TYPE_OTHER, flat::ElementType_OTHER},
-              {proto::ELEMENT_TYPE_SCRIPT, flat::ElementType_SCRIPT},
-              {proto::ELEMENT_TYPE_IMAGE, flat::ElementType_IMAGE},
-              {proto::ELEMENT_TYPE_STYLESHEET, flat::ElementType_STYLESHEET},
-              {proto::ELEMENT_TYPE_OBJECT, flat::ElementType_OBJECT},
-              {proto::ELEMENT_TYPE_XMLHTTPREQUEST,
-               flat::ElementType_XMLHTTPREQUEST},
-              {proto::ELEMENT_TYPE_OBJECT_SUBREQUEST,
-               flat::ElementType_OBJECT_SUBREQUEST},
-              {proto::ELEMENT_TYPE_SUBDOCUMENT, flat::ElementType_SUBDOCUMENT},
-              {proto::ELEMENT_TYPE_PING, flat::ElementType_PING},
-              {proto::ELEMENT_TYPE_MEDIA, flat::ElementType_MEDIA},
-              {proto::ELEMENT_TYPE_FONT, flat::ElementType_FONT},
-              // Filtering popups is not supported.
-              {proto::ELEMENT_TYPE_POPUP, flat::ElementType_NONE},
-              {proto::ELEMENT_TYPE_WEBSOCKET, flat::ElementType_WEBSOCKET},
-          },
-          base::KEEP_FIRST_OF_DUPES));
-  return element_type_map;
+  static base::NoDestructor<ElementTypeMap> element_type_map(
+      std::initializer_list<ElementTypeMap::value_type>{
+          {proto::ELEMENT_TYPE_UNSPECIFIED, flat::ElementType_NONE},
+          {proto::ELEMENT_TYPE_OTHER, flat::ElementType_OTHER},
+          {proto::ELEMENT_TYPE_SCRIPT, flat::ElementType_SCRIPT},
+          {proto::ELEMENT_TYPE_IMAGE, flat::ElementType_IMAGE},
+          {proto::ELEMENT_TYPE_STYLESHEET, flat::ElementType_STYLESHEET},
+          {proto::ELEMENT_TYPE_OBJECT, flat::ElementType_OBJECT},
+          {proto::ELEMENT_TYPE_XMLHTTPREQUEST,
+           flat::ElementType_XMLHTTPREQUEST},
+          {proto::ELEMENT_TYPE_OBJECT_SUBREQUEST,
+           flat::ElementType_OBJECT_SUBREQUEST},
+          {proto::ELEMENT_TYPE_SUBDOCUMENT, flat::ElementType_SUBDOCUMENT},
+          {proto::ELEMENT_TYPE_PING, flat::ElementType_PING},
+          {proto::ELEMENT_TYPE_MEDIA, flat::ElementType_MEDIA},
+          {proto::ELEMENT_TYPE_FONT, flat::ElementType_FONT},
+          // Filtering popups is not supported.
+          {proto::ELEMENT_TYPE_POPUP, flat::ElementType_NONE},
+          {proto::ELEMENT_TYPE_WEBSOCKET, flat::ElementType_WEBSOCKET},
+      },
+      base::KEEP_FIRST_OF_DUPES);
+  return *element_type_map;
 }
 
 flat::ActivationType ProtoToFlatActivationType(proto::ActivationType type) {
diff --git a/components/zucchini/abs32_utils.cc b/components/zucchini/abs32_utils.cc
index bf6526b..91bdb61 100644
--- a/components/zucchini/abs32_utils.cc
+++ b/components/zucchini/abs32_utils.cc
@@ -94,11 +94,11 @@
     offset_t hi)
     : image_(image), addr_(std::move(addr)) {
   CHECK_LE(lo, hi);
-  auto find_and_check = [&addr](const std::vector<offset_t>& locations,
-                                offset_t offset) {
+  auto find_and_check = [this](const std::vector<offset_t>& locations,
+                               offset_t offset) {
     auto it = std::lower_bound(locations.begin(), locations.end(), offset);
-    // Ensure |offset| does not straddle a reference body.
-    CHECK(it == locations.begin() || offset - *(it - 1) >= addr.width());
+    // Ensure that |offset| does not straddle a reference body.
+    CHECK(it == locations.begin() || offset - *(it - 1) >= addr_.width());
     return it;
   };
   cur_abs32_ = find_and_check(abs32_locations, lo);
@@ -136,11 +136,8 @@
   for (auto unit = abs32_rva_extractor_.GetNext(); unit.has_value();
        unit = abs32_rva_extractor_.GetNext()) {
     offset_t location = unit->location;
-    // |target| will not be dereferenced, so we don't worry about it
-    // exceeding |image_.size()| (in fact, there are valid cases where it
-    // does).
     offset_t unsafe_target = target_rva_to_offset_.Convert(unit->target_rva);
-    if (unsafe_target < kOffsetBound)
+    if (unsafe_target != kInvalidOffset)
       return Reference{location, unsafe_target};
   }
   return base::nullopt;
@@ -167,6 +164,25 @@
 
 /******** Exported Functions ********/
 
+size_t RemoveUntranslatableAbs32(ConstBufferView image,
+                                 AbsoluteAddress&& addr,
+                                 const AddressTranslator& translator,
+                                 std::vector<offset_t>* locations) {
+  AddressTranslator::RvaToOffsetCache target_rva_checker(translator);
+  Abs32RvaExtractorWin32 extractor(image, std::move(addr), *locations, 0,
+                                   image.size());
+  Abs32ReaderWin32 reader(std::move(extractor), translator);
+  std::vector<offset_t>::iterator write_it = locations->begin();
+  // |reader| reads |locations| while |write_it| modifies it. However, there's
+  // no conflict since read occurs before write, and can skip ahead.
+  for (auto ref = reader.GetNext(); ref.has_value(); ref = reader.GetNext())
+    *(write_it++) = ref->location;
+  DCHECK(write_it <= locations->end());
+  size_t num_removed = locations->end() - write_it;
+  locations->erase(write_it, locations->end());
+  return num_removed;
+}
+
 size_t RemoveOverlappingAbs32Locations(uint32_t width,
                                        std::vector<offset_t>* locations) {
   if (locations->size() <= 1)
diff --git a/components/zucchini/abs32_utils.h b/components/zucchini/abs32_utils.h
index a97aa38..5bc9cf21 100644
--- a/components/zucchini/abs32_utils.h
+++ b/components/zucchini/abs32_utils.h
@@ -45,7 +45,7 @@
   // the write and returns true. On failure (invalid |offset|), returns false.
   bool Write(offset_t offset, MutableBufferView* image);
 
-  size_t width() const { return WidthOf(bitness_); }
+  uint32_t width() const { return WidthOf(bitness_); }
 
   // Exposing |value_| for testing.
   uint64_t* mutable_value() { return &value_; }
@@ -126,6 +126,13 @@
   DISALLOW_COPY_AND_ASSIGN(Abs32WriterWin32);
 };
 
+// Given a list of abs32 |locations|, removes all elements whose targets cannot
+// be translated. Returns the number of elements removed.
+size_t RemoveUntranslatableAbs32(ConstBufferView image,
+                                 AbsoluteAddress&& addr,
+                                 const AddressTranslator& translator,
+                                 std::vector<offset_t>* locations);
+
 // Given a sorted list of abs32 |locations|, removes all elements whose body
 // (with |width| given) overlaps with the body of a previous element.
 size_t RemoveOverlappingAbs32Locations(uint32_t width,
diff --git a/components/zucchini/abs32_utils_unittest.cc b/components/zucchini/abs32_utils_unittest.cc
index a8f6917e..77a2599 100644
--- a/components/zucchini/abs32_utils_unittest.cc
+++ b/components/zucchini/abs32_utils_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/numerics/safe_conversions.h"
+#include "components/zucchini/address_translator.h"
 #include "components/zucchini/image_utils.h"
 #include "components/zucchini/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -52,7 +53,7 @@
   EXPECT_TRUE(addr32.Read(0x8U, image32));
   EXPECT_EQ(kInvalidRva, addr32.ToRva());  // Underflow.
   EXPECT_TRUE(addr32.Read(0xCU, image32));
-  EXPECT_EQ(kInvalidRva, addr32.ToRva());  // Translated RVA would be to large.
+  EXPECT_EQ(kInvalidRva, addr32.ToRva());  // Translated RVA would be too large.
   EXPECT_TRUE(addr32.Read(0x10U, image32));
   EXPECT_EQ(kInvalidRva, addr32.ToRva());  // Underflow (boundary case).
 
@@ -432,6 +433,52 @@
   EXPECT_EQ(expected_data64, data64);
 }
 
+TEST(Abs32UtilsTest, RemoveUntranslatableAbs32) {
+  Bitness kBitness = kBit32;
+  uint64_t kImageBase = 0x2BCD0000;
+
+  // Valid RVAs: [0x00001A00, 0x00001A28) and [0x00003A00, 0x00004000).
+  // Valid AVAs: [0x2BCD1A00, 0x2BCD1A28) and [0x2BCD3A00, 0x2BCD4000).
+  // Notice that the second section has has dangling RVA.
+  AddressTranslator translator;
+  ASSERT_EQ(AddressTranslator::kSuccess,
+            translator.Initialize(
+                {{0x04, +0x28, 0x1A00, +0x28}, {0x30, +0x30, 0x3A00, +0x600}}));
+
+  std::vector<uint8_t> data = ParseHexString(
+      "FF FF FF FF  0B 3A CD 2B  00 00 00  04 3A CD 2B  00 "
+      "FC 3F CD 2B  14 1A CD 2B  44 00 00 00  CC 00 00 00 "
+      "00 00 55 00  00 00  1E 1A CD 2B  00 99  FF FF FF FF "
+      "10 3A CD 2B  22 00 00 00  00 00 00 11  00 00 00 00 "
+      "66 00 00 00  28 1A CD 2B  00 00 CD 2B  27 1A CD 2B "
+      "FF 39 CD 2B  00 00 00 00  18 1A CD 2B  00 00 00 00 "
+      "FF FF FF FF  FF FF FF FF");
+  MutableBufferView image(data.data(), data.size());
+
+  const offset_t kAbs1 = 0x04;  // a:2BCD3A0B = r:3A0B = o:3B
+  const offset_t kAbs2 = 0x0B;  // a:2BCD3A04 = r:3A04 = o:34
+  const offset_t kAbs3 = 0x10;  // a:2BCD3FFF = r:3FFF (dangling)
+  const offset_t kAbs4 = 0x14;  // a:2BCD1A14 = r:1A14 = o:18
+  const offset_t kAbs5 = 0x26;  // a:2BCD1A1E = r:1A1E = o:22
+  const offset_t kAbs6 = 0x30;  // a:2BCD3A10 = r:3A10 = 0x40
+  const offset_t kAbs7 = 0x44;  // a:2BCD1A28 = r:1A28 (bad: sentinel)
+  const offset_t kAbs8 = 0x48;  // a:2BCD0000 = r:0000 (bad: not covered)
+  const offset_t kAbs9 = 0x4C;  // a:2BCD1A27 = r:1A27 = 0x2B
+  const offset_t kAbsA = 0x50;  // a:2BCD39FF (bad: not covered)
+  const offset_t kAbsB = 0x54;  // a:00000000 (bad: underflow)
+  const offset_t kAbsC = 0x58;  // a:2BCD1A18 = r:1A18 = 0x1C
+
+  std::vector<offset_t> locations = {kAbs1, kAbs2, kAbs3, kAbs4, kAbs5, kAbs6,
+                                     kAbs7, kAbs8, kAbs9, kAbsA, kAbsB, kAbsC};
+  std::vector<offset_t> exp_locations = {kAbs1, kAbs2, kAbs3, kAbs4,
+                                         kAbs5, kAbs6, kAbs9, kAbsC};
+  size_t exp_num_removed = locations.size() - exp_locations.size();
+  size_t num_removed = RemoveUntranslatableAbs32(image, {kBitness, kImageBase},
+                                                 translator, &locations);
+  EXPECT_EQ(exp_num_removed, num_removed);
+  EXPECT_EQ(exp_locations, locations);
+}
+
 TEST(Abs32UtilsTest, RemoveOverlappingAbs32Locations) {
   // Make |width| a state to reduce repetition.
   uint32_t width = WidthOf(kBit32);
diff --git a/components/zucchini/address_translator.cc b/components/zucchini/address_translator.cc
index 5b388da..20f19b2d 100644
--- a/components/zucchini/address_translator.cc
+++ b/components/zucchini/address_translator.cc
@@ -38,6 +38,8 @@
     : translator_(translator) {}
 
 bool AddressTranslator::RvaToOffsetCache::IsValid(rva_t rva) const {
+  if (rva == kInvalidRva)
+    return false;
   if (!cached_unit_ || !cached_unit_->CoversRva(rva)) {
     const AddressTranslator::Unit* unit = translator_.RvaToUnit(rva);
     if (!unit)
diff --git a/components/zucchini/address_translator.h b/components/zucchini/address_translator.h
index 821b9ade..5666b99b 100644
--- a/components/zucchini/address_translator.h
+++ b/components/zucchini/address_translator.h
@@ -59,7 +59,7 @@
 using rva_t = uint32_t;
 // Divide by 2 to match |kOffsetBound|.
 constexpr rva_t kRvaBound = static_cast<rva_t>(-1) / 2;
-constexpr rva_t kInvalidRva = static_cast<rva_t>(-1);
+constexpr rva_t kInvalidRva = static_cast<rva_t>(-2);
 
 // A utility to translate between offsets and RVAs in an image.
 class AddressTranslator {
@@ -133,6 +133,7 @@
     explicit RvaToOffsetCache(const AddressTranslator& translator);
 
     bool IsValid(rva_t rva) const;
+
     offset_t Convert(rva_t rva) const;
 
    private:
diff --git a/components/zucchini/address_translator_unittest.cc b/components/zucchini/address_translator_unittest.cc
index 0aeff777..efa2f14 100644
--- a/components/zucchini/address_translator_unittest.cc
+++ b/components/zucchini/address_translator_unittest.cc
@@ -553,4 +553,34 @@
   } while (std::next_permutation(test_case2.begin(), test_case2.end()));
 }
 
+TEST(AddressTranslatorTest, RvaToOffsetCache_IsValid) {
+  AddressTranslator translator;
+  // Notice that the second section has dangling RVA.
+  ASSERT_EQ(AddressTranslator::kSuccess,
+            translator.Initialize(
+                {{0x04, +0x28, 0x1A00, +0x28}, {0x30, +0x10, 0x3A00, +0x30}}));
+  AddressTranslator::RvaToOffsetCache rva_checker(translator);
+
+  EXPECT_FALSE(rva_checker.IsValid(kInvalidRva));
+
+  for (int i = 0; i < 0x28; ++i)
+    EXPECT_TRUE(rva_checker.IsValid(0x1A00 + i));
+  EXPECT_FALSE(rva_checker.IsValid(0x1A00 + 0x28));
+  EXPECT_FALSE(rva_checker.IsValid(0x1A00 + 0x29));
+  EXPECT_FALSE(rva_checker.IsValid(0x1A00 - 1));
+  EXPECT_FALSE(rva_checker.IsValid(0x1A00 - 2));
+
+  for (int i = 0; i < 0x30; ++i)
+    EXPECT_TRUE(rva_checker.IsValid(0x3A00 + i));
+  EXPECT_FALSE(rva_checker.IsValid(0x3A00 + 0x30));
+  EXPECT_FALSE(rva_checker.IsValid(0x3A00 + 0x31));
+  EXPECT_FALSE(rva_checker.IsValid(0x3A00 - 1));
+  EXPECT_FALSE(rva_checker.IsValid(0x3A00 - 2));
+
+  EXPECT_FALSE(rva_checker.IsValid(0));
+  EXPECT_FALSE(rva_checker.IsValid(0x10));
+  EXPECT_FALSE(rva_checker.IsValid(0x7FFFFFFFU));
+  EXPECT_FALSE(rva_checker.IsValid(0xFFFFFFFFU));
+}
+
 }  // namespace zucchini
diff --git a/components/zucchini/disassembler_elf.cc b/components/zucchini/disassembler_elf.cc
index 0f6d3a08..be01c4c 100644
--- a/components/zucchini/disassembler_elf.cc
+++ b/components/zucchini/disassembler_elf.cc
@@ -19,6 +19,8 @@
 
 namespace {
 
+constexpr uint64_t kElfImageBase = 0;
+
 // Determines whether |section| is a reloc section.
 template <class Traits>
 bool IsRelocSection(const typename Traits::Elf_Shdr& section) {
@@ -288,23 +290,33 @@
 void DisassemblerElf<Traits>::GetAbs32FromRelocSections() {
   constexpr int kAbs32Width = Traits::kVAWidth;
   DCHECK(abs32_locations_.empty());
-  auto relocs = MakeReadRelocs(0, offset_t(size()));
-  for (auto ref = relocs->GetNext(); ref; ref = relocs->GetNext()) {
-    // Reject null targets and targets outside |image_|. Note that here we
-    // assume abs32 targets are never "fake offsets".
-    if (ref->target > 0 && image_.covers({ref->target, kAbs32Width}))
-      abs32_locations_.push_back(ref->target);
-  }
-  abs32_locations_.shrink_to_fit();
+
+  // Read reloc targets as preliminary abs32 locations.
+  std::unique_ptr<ReferenceReader> relocs = MakeReadRelocs(0, offset_t(size()));
+  for (auto ref = relocs->GetNext(); ref.has_value(); ref = relocs->GetNext())
+    abs32_locations_.push_back(ref->target);
+
   std::sort(abs32_locations_.begin(), abs32_locations_.end());
 
+  // Abs32 references must have targets translatable to offsets. Remove those
+  // that are unable to do so.
+  // TODO(huangs): Investigate whether passing |Traits::kBitness| is correct:
+  // Some architectures using ELF might have 4-byte long abs32 body regardless
+  // of bitness.
+  size_t num_untranslatable =
+      RemoveUntranslatableAbs32(image_, {Traits::kBitness, kElfImageBase},
+                                translator_, &abs32_locations_);
+  LOG_IF(WARNING, num_untranslatable) << "Removed " << num_untranslatable
+                                      << " untranslatable abs32 references.";
+
   // Abs32 reference bodies must not overlap. If found, simply remove them.
-  size_t num_removed =
+  size_t num_overlapping =
       RemoveOverlappingAbs32Locations(kAbs32Width, &abs32_locations_);
-  if (num_removed) {
-    LOG(WARNING) << "Warning: Found and removed " << num_removed
-                 << " abs32 locations with overlapping bodies.";
-  }
+  LOG_IF(WARNING, num_overlapping)
+      << "Removed " << num_overlapping
+      << " abs32 references with overlapping bodies.";
+
+  abs32_locations_.shrink_to_fit();
 }
 
 template <class Traits>
@@ -392,9 +404,12 @@
 std::unique_ptr<ReferenceReader> DisassemblerElfIntel<Traits>::MakeReadAbs32(
     offset_t lo,
     offset_t hi) {
-  Abs32RvaExtractorWin32 abs_rva_extractor(this->image_,
-                                           AbsoluteAddress(Traits::kBitness, 0),
-                                           this->abs32_locations_, lo, hi);
+  // TODO(huangs): Don't use Abs32RvaExtractorWin32 here; use new class that
+  // caters to different ELF architectures (e.g., abs32 in AArch64 are 4 bytes
+  // long, not 8 bytes long).
+  Abs32RvaExtractorWin32 abs_rva_extractor(
+      this->image_, AbsoluteAddress(Traits::kBitness, kElfImageBase),
+      this->abs32_locations_, lo, hi);
   return std::make_unique<Abs32ReaderWin32>(std::move(abs_rva_extractor),
                                             this->translator_);
 }
@@ -402,8 +417,10 @@
 template <class Traits>
 std::unique_ptr<ReferenceWriter> DisassemblerElfIntel<Traits>::MakeWriteAbs32(
     MutableBufferView image) {
+  // TODO(huangs): For AArch64, see if |Traits::kBitness| should be used here?
   return std::make_unique<Abs32WriterWin32>(
-      image, AbsoluteAddress(Traits::kBitness, 0), this->translator_);
+      image, AbsoluteAddress(Traits::kBitness, kElfImageBase),
+      this->translator_);
 }
 
 template <class Traits>
diff --git a/components/zucchini/disassembler_win32.cc b/components/zucchini/disassembler_win32.cc
index b3f568bd..9067ad7 100644
--- a/components/zucchini/disassembler_win32.cc
+++ b/components/zucchini/disassembler_win32.cc
@@ -316,20 +316,28 @@
     return true;
   has_parsed_abs32_ = true;
 
-  ParseAndStoreRelocBlocks();
-
+  // Read reloc targets as preliminary abs32 locations.
   std::unique_ptr<ReferenceReader> relocs = MakeReadRelocs(0, offset_t(size()));
   for (auto ref = relocs->GetNext(); ref.has_value(); ref = relocs->GetNext())
     abs32_locations_.push_back(ref->target);
 
-  abs32_locations_.shrink_to_fit();
   std::sort(abs32_locations_.begin(), abs32_locations_.end());
 
+  // Abs32 references must have targets translatable to offsets. Remove those
+  // that are unable to do so.
+  size_t num_untranslatable = RemoveUntranslatableAbs32(
+      image_, {Traits::kBitness, image_base_}, translator_, &abs32_locations_);
+  LOG_IF(WARNING, num_untranslatable) << "Removed " << num_untranslatable
+                                      << " untranslatable abs32 references.";
+
   // Abs32 reference bodies must not overlap. If found, simply remove them.
-  size_t num_removed =
+  size_t num_overlapping =
       RemoveOverlappingAbs32Locations(Traits::kVAWidth, &abs32_locations_);
-  LOG_IF(WARNING, num_removed) << "Found and removed " << num_removed
-                               << " abs32 locations with overlapping bodies.";
+  LOG_IF(WARNING, num_overlapping)
+      << "Removed " << num_overlapping
+      << " abs32 references with overlapping bodies.";
+
+  abs32_locations_.shrink_to_fit();
   return true;
 }
 
diff --git a/components/zucchini/reloc_win32.cc b/components/zucchini/reloc_win32.cc
index dcf40bb..6da48f2 100644
--- a/components/zucchini/reloc_win32.cc
+++ b/components/zucchini/reloc_win32.cc
@@ -152,7 +152,7 @@
     offset_t target = entry_rva_to_offset_.Convert(unit->target_rva);
     if (target == kInvalidOffset)
       continue;
-    // Ensures the target (abs32 reference) lies entirely within the image.
+    // Ensure that |target| (abs32 reference) lies entirely within the image.
     if (target >= offset_bound_)
       continue;
     offset_t location = unit->location;
diff --git a/content/browser/code_cache/generated_code_cache.cc b/content/browser/code_cache/generated_code_cache.cc
index b7094c1c..90028a3 100644
--- a/content/browser/code_cache/generated_code_cache.cc
+++ b/content/browser/code_cache/generated_code_cache.cc
@@ -53,12 +53,20 @@
   key.append(requesting_origin.Serialize());
   return key;
 }
-
-void CollectStatistics(GeneratedCodeCache::CacheEntryStatus status) {
-  UMA_HISTOGRAM_ENUMERATION("SiteIsolatedCodeCache.Behaviour", status);
-}
 }  // namespace
 
+void GeneratedCodeCache::CollectStatistics(
+    GeneratedCodeCache::CacheEntryStatus status) {
+  switch (cache_type_) {
+    case GeneratedCodeCache::CodeCacheType::kJavaScript:
+      UMA_HISTOGRAM_ENUMERATION("SiteIsolatedCodeCache.JS.Behaviour", status);
+      break;
+    case GeneratedCodeCache::CodeCacheType::kWebAssembly:
+      UMA_HISTOGRAM_ENUMERATION("SiteIsolatedCodeCache.WASM.Behaviour", status);
+      break;
+  }
+}
+
 // Stores the information about a pending request while disk backend is
 // being initialized.
 class GeneratedCodeCache::PendingOperation {
@@ -146,10 +154,12 @@
 GeneratedCodeCache::PendingOperation::~PendingOperation() = default;
 
 GeneratedCodeCache::GeneratedCodeCache(const base::FilePath& path,
-                                       int max_size_bytes)
+                                       int max_size_bytes,
+                                       CodeCacheType cache_type)
     : backend_state_(kUnInitialized),
       path_(path),
       max_size_bytes_(max_size_bytes),
+      cache_type_(cache_type),
       weak_ptr_factory_(this) {
   CreateBackend();
 }
diff --git a/content/browser/code_cache/generated_code_cache.h b/content/browser/code_cache/generated_code_cache.h
index dee6fcd..2ad53ff0 100644
--- a/content/browser/code_cache/generated_code_cache.h
+++ b/content/browser/code_cache/generated_code_cache.h
@@ -36,6 +36,10 @@
                                    const std::vector<uint8_t>&)>;
   static const int kResponseTimeSizeInBytes = sizeof(int64_t);
 
+  // Cache type. Used for collecting statistics for JS and Wasm in separate
+  // buckets.
+  enum CodeCacheType { kJavaScript, kWebAssembly };
+
   // Used for collecting statistics about cache behaviour.
   enum CacheEntryStatus {
     kHit,
@@ -51,7 +55,9 @@
   // Creates a GeneratedCodeCache with the specified path and the maximum size.
   // If |max_size_bytes| is 0, then disk_cache picks a default size based on
   // some heuristics.
-  GeneratedCodeCache(const base::FilePath& path, int max_size_bytes);
+  GeneratedCodeCache(const base::FilePath& path,
+                     int max_size_bytes,
+                     CodeCacheType cache_type);
 
   ~GeneratedCodeCache();
 
@@ -132,6 +138,8 @@
   void DoPendingClearCache(net::CompletionCallback callback);
   void PendingClearComplete(net::CompletionCallback callback, int rv);
 
+  void CollectStatistics(GeneratedCodeCache::CacheEntryStatus status);
+
   std::unique_ptr<disk_cache::Backend> backend_;
   BackendState backend_state_;
 
@@ -139,6 +147,7 @@
 
   base::FilePath path_;
   int max_size_bytes_;
+  CodeCacheType cache_type_;
 
   base::WeakPtrFactory<GeneratedCodeCache> weak_ptr_factory_;
 
diff --git a/content/browser/code_cache/generated_code_cache_context.cc b/content/browser/code_cache/generated_code_cache_context.cc
index 719087c..b119832 100644
--- a/content/browser/code_cache/generated_code_cache_context.cc
+++ b/content/browser/code_cache/generated_code_cache_context.cc
@@ -27,9 +27,11 @@
 void GeneratedCodeCacheContext::InitializeOnIO(const base::FilePath& path,
                                                int max_bytes) {
   generated_js_code_cache_.reset(
-      new GeneratedCodeCache(path.AppendASCII("js"), max_bytes));
+      new GeneratedCodeCache(path.AppendASCII("js"), max_bytes,
+                             GeneratedCodeCache::CodeCacheType::kJavaScript));
   generated_wasm_code_cache_.reset(
-      new GeneratedCodeCache(path.AppendASCII("wasm"), max_bytes));
+      new GeneratedCodeCache(path.AppendASCII("wasm"), max_bytes,
+                             GeneratedCodeCache::CodeCacheType::kWebAssembly));
 }
 
 GeneratedCodeCache* GeneratedCodeCacheContext::generated_js_code_cache() const {
diff --git a/content/browser/code_cache/generated_code_cache_unittest.cc b/content/browser/code_cache/generated_code_cache_unittest.cc
index 4c9b2ab..3a2e4ca 100644
--- a/content/browser/code_cache/generated_code_cache_unittest.cc
+++ b/content/browser/code_cache/generated_code_cache_unittest.cc
@@ -25,8 +25,6 @@
   void SetUp() override {
     ASSERT_TRUE(cache_dir_.CreateUniqueTempDir());
     cache_path_ = cache_dir_.GetPath();
-    generated_code_cache_ =
-        std::make_unique<GeneratedCodeCache>(cache_path_, kMaxSizeInBytes);
   }
 
   void TearDown() override {
@@ -36,7 +34,11 @@
 
   // This function initializes the cache and waits till the transaction is
   // finished. When this function returns, the backend is already initialized.
-  void InitializeCache() {
+  void InitializeCache(GeneratedCodeCache::CodeCacheType cache_type) {
+    // Create code cache
+    generated_code_cache_ = std::make_unique<GeneratedCodeCache>(
+        cache_path_, kMaxSizeInBytes, cache_type);
+
     GURL url(kInitialUrl);
     url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
     WriteToCache(url, origin, kInitialData, base::Time::Now());
@@ -46,10 +48,10 @@
   // This function initializes the cache and reopens it. When this function
   // returns, the backend initialization is not complete yet. This is used
   // to test the pending operaions path.
-  void InitializeCacheAndReOpen() {
-    InitializeCache();
+  void InitializeCacheAndReOpen(GeneratedCodeCache::CodeCacheType cache_type) {
+    InitializeCache(cache_type);
     generated_code_cache_.reset(
-        new GeneratedCodeCache(cache_path_, kMaxSizeInBytes));
+        new GeneratedCodeCache(cache_path_, kMaxSizeInBytes, cache_type));
   }
 
   void WriteToCache(const GURL& url,
@@ -113,6 +115,7 @@
   GURL url(kInitialUrl);
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data = "SerializedCodeForScript";
   base::Time response_time = base::Time::Now();
   WriteToCache(url, origin, data, response_time);
@@ -129,7 +132,7 @@
   GURL url(kInitialUrl);
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   FetchFromCache(url, origin);
   scoped_task_environment_.RunUntilIdle();
 
@@ -141,7 +144,7 @@
   GURL new_url("http://example1.com/script.js");
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data = "SerializedCodeForScript";
   base::Time response_time = base::Time::Now();
   WriteToCache(new_url, origin, data, response_time);
@@ -158,7 +161,7 @@
   GURL url(kInitialUrl);
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   DeleteFromCache(url, origin);
   FetchFromCache(url, origin);
   scoped_task_environment_.RunUntilIdle();
@@ -171,7 +174,7 @@
   GURL url(kInitialUrl);
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   base::Time response_time = base::Time::Now();
   WriteToCache(url, origin, std::string(), response_time);
   scoped_task_environment_.RunUntilIdle();
@@ -187,7 +190,7 @@
   GURL url(kInitialUrl);
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCacheAndReOpen();
+  InitializeCacheAndReOpen(GeneratedCodeCache::CodeCacheType::kJavaScript);
   FetchFromCache(url, origin);
   scoped_task_environment_.RunUntilIdle();
 
@@ -199,7 +202,7 @@
   GURL new_url("http://example1.com/script1.js");
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data = "SerializedCodeForScript";
   base::Time response_time = base::Time::Now();
   WriteToCache(new_url, origin, data, response_time);
@@ -216,7 +219,7 @@
   GURL url(kInitialUrl);
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCacheAndReOpen();
+  InitializeCacheAndReOpen(GeneratedCodeCache::CodeCacheType::kJavaScript);
   DeleteFromCache(url, origin);
   FetchFromCache(url, origin);
   scoped_task_environment_.RunUntilIdle();
@@ -229,7 +232,7 @@
   GURL url(kInitialUrl);
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string new_data = "SerializedCodeForScriptOverwrite";
   base::Time response_time = base::Time::Now();
   WriteToCache(url, origin, new_data, response_time);
@@ -243,7 +246,7 @@
 }
 
 TEST_F(GeneratedCodeCacheTest, FetchFailsForNonexistingOrigin) {
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   url::Origin new_origin = url::Origin::Create(GURL("http://not-example.com"));
   FetchFromCache(GURL(kInitialUrl), new_origin);
   scoped_task_environment_.RunUntilIdle();
@@ -257,6 +260,7 @@
   GURL second_url("http://script.com/one.js");
   url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
 
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data_first_resource = "SerializedCodeForFirstResource";
   WriteToCache(url, origin, data_first_resource, base::Time());
 
@@ -280,6 +284,7 @@
   url::Origin origin = url::Origin::Create(GURL("http://example.com"));
   url::Origin origin1 = url::Origin::Create(GURL("http://example1.com"));
 
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data_origin = "SerializedCodeForFirstOrigin";
   WriteToCache(url, origin, data_origin, base::Time());
 
@@ -303,6 +308,7 @@
   url::Origin origin =
       url::Origin::Create(GURL("data:text/html,<script></script>"));
 
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data = "SerializedCodeForUniqueOrigin";
   WriteToCache(url, origin, data, base::Time());
   scoped_task_environment_.RunUntilIdle();
@@ -317,6 +323,7 @@
   GURL url("http://example.com/script.js");
   url::Origin origin = url::Origin::Create(GURL("invalidURL"));
 
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data = "SerializedCodeForInvalidOrigin";
   WriteToCache(url, origin, data, base::Time());
   scoped_task_environment_.RunUntilIdle();
@@ -332,6 +339,7 @@
   GURL url("InvalidURL");
   url::Origin origin = url::Origin::Create(GURL("http://example.com"));
 
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   std::string data = "SerializedCodeForInvalidURL";
   WriteToCache(url, origin, data, base::Time());
   scoped_task_environment_.RunUntilIdle();
@@ -346,7 +354,7 @@
   GURL url("http://example.com/script.js");
   url::Origin origin = url::Origin::Create(GURL("http://example.com"));
 
-  InitializeCache();
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kJavaScript);
   ClearCache();
   scoped_task_environment_.RunUntilIdle();
   FetchFromCache(url, origin);
@@ -355,4 +363,16 @@
   ASSERT_TRUE(received_);
   ASSERT_TRUE(received_null_);
 }
+
+TEST_F(GeneratedCodeCacheTest, WasmCache) {
+  GURL url(kInitialUrl);
+  url::Origin origin = url::Origin::Create(GURL(kInitialOrigin));
+
+  InitializeCache(GeneratedCodeCache::CodeCacheType::kWebAssembly);
+  FetchFromCache(url, origin);
+  scoped_task_environment_.RunUntilIdle();
+
+  ASSERT_TRUE(received_);
+  EXPECT_EQ(kInitialData, received_data_);
+}
 }  // namespace content
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 4bed355..a0220133 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -150,11 +150,13 @@
           nullptr, params->callback()));
 }
 
-void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params,
-                   std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
-                   content::ResourceContext* resource_context,
-                   bool is_new_download,
-                   base::WeakPtr<DownloadManagerImpl> download_manager) {
+void BeginDownload(
+    std::unique_ptr<download::DownloadUrlParameters> params,
+    std::unique_ptr<storage::BlobDataHandle> blob_data_handle,
+    content::ResourceContext* resource_context,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+    bool is_new_download,
+    base::WeakPtr<DownloadManagerImpl> download_manager) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
@@ -163,8 +165,8 @@
   params->set_blob_storage_context_getter(
       base::BindOnce(&BlobStorageContextGetter, resource_context));
   std::unique_ptr<net::URLRequest> url_request =
-      DownloadRequestCore::CreateRequestOnIOThread(is_new_download,
-                                                   params.get());
+      DownloadRequestCore::CreateRequestOnIOThread(
+          is_new_download, params.get(), std::move(url_request_context_getter));
   if (blob_data_handle) {
     storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
         url_request.get(), std::move(blob_data_handle));
@@ -1258,14 +1260,13 @@
   } else {
     StoragePartition* storage_partition =
         BrowserContext::GetStoragePartitionForSite(browser_context_, site_url);
-    params->set_url_request_context_getter(
-        storage_partition->GetURLRequestContext());
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::IO},
-        base::BindOnce(&BeginDownload, std::move(params),
-                       std::move(blob_data_handle),
-                       browser_context_->GetResourceContext(), is_new_download,
-                       weak_factory_.GetWeakPtr()));
+        base::BindOnce(
+            &BeginDownload, std::move(params), std::move(blob_data_handle),
+            browser_context_->GetResourceContext(),
+            base::WrapRefCounted(storage_partition->GetURLRequestContext()),
+            is_new_download, weak_factory_.GetWeakPtr()));
   }
 }
 
diff --git a/content/browser/download/download_request_core.cc b/content/browser/download/download_request_core.cc
index 4b21201b..2a707e8 100644
--- a/content/browser/download/download_request_core.cc
+++ b/content/browser/download/download_request_core.cc
@@ -40,6 +40,7 @@
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
+#include "net/url_request/url_request_context_getter.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
@@ -126,12 +127,14 @@
 // static
 std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread(
     bool is_new_download,
-    download::DownloadUrlParameters* params) {
+    download::DownloadUrlParameters* params,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(is_new_download || !params->content_initiated())
       << "Content initiated downloads should be a new download";
 
-  std::unique_ptr<net::URLRequest> request = CreateURLRequestOnIOThread(params);
+  std::unique_ptr<net::URLRequest> request =
+      CreateURLRequestOnIOThread(params, std::move(url_request_context_getter));
 
   DownloadRequestData::Attach(request.get(), params, is_new_download);
   return request;
diff --git a/content/browser/download/download_request_core.h b/content/browser/download/download_request_core.h
index ce8969ab..93d4391 100644
--- a/content/browser/download/download_request_core.h
+++ b/content/browser/download/download_request_core.h
@@ -13,6 +13,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "components/download/public/common/download_interrupt_reasons.h"
 #include "components/download/public/common/download_save_info.h"
@@ -27,6 +28,7 @@
 namespace net {
 class HttpResponseHeaders;
 class URLRequest;
+class URLRequestContextGetter;
 class URLRequestStatus;
 }  // namespace net
 
@@ -110,7 +112,8 @@
 
   static std::unique_ptr<net::URLRequest> CreateRequestOnIOThread(
       bool is_new_download,
-      download::DownloadUrlParameters* params);
+      download::DownloadUrlParameters* params,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
 
   // Size of the buffer used between the DownloadRequestCore and the
   // downstream receiver of its output.
diff --git a/content/browser/download/download_request_core_unittest.cc b/content/browser/download/download_request_core_unittest.cc
index 06bc74f2..6a07198 100644
--- a/content/browser/download/download_request_core_unittest.cc
+++ b/content/browser/download/download_request_core_unittest.cc
@@ -31,7 +31,7 @@
       const std::string& url) const {
     GURL gurl(url);
     return std::make_unique<download::DownloadUrlParameters>(
-        gurl, request_context_getter_.get(), TRAFFIC_ANNOTATION_FOR_TESTS);
+        gurl, TRAFFIC_ANNOTATION_FOR_TESTS);
   }
 
   void CheckRequestHeaders(const std::string& name,
@@ -48,7 +48,8 @@
   }
 
   void CreateRequestOnIOThread(download::DownloadUrlParameters* params) {
-    url_request_ = DownloadRequestCore::CreateRequestOnIOThread(true, params);
+    url_request_ = DownloadRequestCore::CreateRequestOnIOThread(
+        true, params, request_context_getter_);
     DCHECK(url_request_.get());
   }
 
diff --git a/content/browser/download/download_request_utils.cc b/content/browser/download/download_request_utils.cc
index 2c2a292..86de66d1 100644
--- a/content/browser/download/download_request_utils.cc
+++ b/content/browser/download/download_request_utils.cc
@@ -8,7 +8,6 @@
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 
 namespace content {
@@ -20,14 +19,11 @@
     const GURL& url,
     const net::NetworkTrafficAnnotationTag& traffic_annotation) {
   RenderFrameHost* render_frame_host = web_contents->GetMainFrame();
-  StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
-      web_contents->GetBrowserContext(), render_frame_host->GetSiteInstance());
   return std::unique_ptr<download::DownloadUrlParameters>(
       new download::DownloadUrlParameters(
           url, render_frame_host->GetProcess()->GetID(),
           render_frame_host->GetRenderViewHost()->GetRoutingID(),
-          render_frame_host->GetRoutingID(),
-          storage_partition->GetURLRequestContext(), traffic_annotation));
+          render_frame_host->GetRoutingID(), traffic_annotation));
 }
 
 }  // namespace content
diff --git a/content/browser/download/download_utils.cc b/content/browser/download/download_utils.cc
index 0fd90091..89d3af0 100644
--- a/content/browser/download/download_utils.cc
+++ b/content/browser/download/download_utils.cc
@@ -28,6 +28,7 @@
 #include "net/base/upload_bytes_element_reader.h"
 #include "net/http/http_request_headers.h"
 #include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
 
 namespace content {
 
@@ -40,7 +41,8 @@
 }
 
 std::unique_ptr<net::URLRequest> CreateURLRequestOnIOThread(
-    download::DownloadUrlParameters* params) {
+    download::DownloadUrlParameters* params,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(params->offset() >= 0);
 
@@ -49,10 +51,9 @@
   // resource_dispatcher_host_impl.h, so we must down cast. RDHI is the only
   // subclass of RDH as of 2012 May 4.
   std::unique_ptr<net::URLRequest> request(
-      params->url_request_context_getter()
-          ->GetURLRequestContext()
-          ->CreateRequest(params->url(), net::DEFAULT_PRIORITY, nullptr,
-                          params->GetNetworkTrafficAnnotation()));
+      url_request_context_getter->GetURLRequestContext()->CreateRequest(
+          params->url(), net::DEFAULT_PRIORITY, nullptr,
+          params->GetNetworkTrafficAnnotation()));
   request->set_method(params->method());
 
   if (params->post_body()) {
diff --git a/content/browser/download/download_utils.h b/content/browser/download/download_utils.h
index df86cad..a032894 100644
--- a/content/browser/download/download_utils.h
+++ b/content/browser/download/download_utils.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 
+#include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "content/common/content_export.h"
 
@@ -16,6 +17,7 @@
 
 namespace net {
 class URLRequest;
+class URLRequestContextGetter;
 }  // namespace net
 
 namespace storage {
@@ -26,9 +28,11 @@
 
 class ResourceContext;
 
-// Create a URLRequest from |params|.
-std::unique_ptr<net::URLRequest> CONTENT_EXPORT
-CreateURLRequestOnIOThread(download::DownloadUrlParameters* params);
+// Create a URLRequest from |params| using the specified
+// URLRequestContextGetter.
+std::unique_ptr<net::URLRequest> CONTENT_EXPORT CreateURLRequestOnIOThread(
+    download::DownloadUrlParameters* params,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
 
 storage::BlobStorageContext* BlobStorageContextGetter(
     ResourceContext* resource_context);
diff --git a/content/browser/download/url_downloader_factory.cc b/content/browser/download/url_downloader_factory.cc
index 5a66bd2b..c6a9154 100644
--- a/content/browser/download/url_downloader_factory.cc
+++ b/content/browser/download/url_downloader_factory.cc
@@ -8,6 +8,7 @@
 #include "components/download/public/common/download_url_loader_factory_getter.h"
 #include "content/browser/download/download_request_core.h"
 #include "content/browser/download/url_downloader.h"
+#include "net/url_request/url_request_context_getter.h"
 
 namespace content {
 
@@ -21,9 +22,11 @@
     base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
     scoped_refptr<download::DownloadURLLoaderFactoryGetter>
         url_loader_factory_getter,
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
   std::unique_ptr<net::URLRequest> url_request =
-      DownloadRequestCore::CreateRequestOnIOThread(true, params.get());
+      DownloadRequestCore::CreateRequestOnIOThread(
+          true, params.get(), std::move(url_request_context_getter));
 
   return download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
       UrlDownloader::BeginDownload(delegate, std::move(url_request),
diff --git a/content/browser/download/url_downloader_factory.h b/content/browser/download/url_downloader_factory.h
index ae908ec..bda9973 100644
--- a/content/browser/download/url_downloader_factory.h
+++ b/content/browser/download/url_downloader_factory.h
@@ -5,11 +5,16 @@
 #ifndef CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_
 #define CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_
 
+#include "base/memory/ref_counted.h"
 #include "components/download/public/common/url_download_handler_factory.h"
 
 namespace download {
 class DownloadURLLoaderFactoryGetter;
-};
+}
+
+namespace net {
+class URLRequestContextGetter;
+}
 
 namespace content {
 
@@ -27,6 +32,7 @@
       base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
       scoped_refptr<download::DownloadURLLoaderFactoryGetter>
           shared_url_loader_factory,
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override;
 };
 
diff --git a/content/browser/frame_host/form_submission_throttle.cc b/content/browser/frame_host/form_submission_throttle.cc
index d50a20b..46c737ac 100644
--- a/content/browser/frame_host/form_submission_throttle.cc
+++ b/content/browser/frame_host/form_submission_throttle.cc
@@ -30,12 +30,12 @@
 
 NavigationThrottle::ThrottleCheckResult
 FormSubmissionThrottle::WillStartRequest() {
-  return CheckContentSecurityPolicyFormAction(false /* is_redirect */);
+  return CheckContentSecurityPolicyFormAction(false /* was_server_redirect */);
 }
 
 NavigationThrottle::ThrottleCheckResult
 FormSubmissionThrottle::WillRedirectRequest() {
-  return CheckContentSecurityPolicyFormAction(true /* is_redirect */);
+  return CheckContentSecurityPolicyFormAction(true /* was_server_redirect */);
 }
 
 const char* FormSubmissionThrottle::GetNameForLogging() {
@@ -43,7 +43,8 @@
 }
 
 NavigationThrottle::ThrottleCheckResult
-FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(bool is_redirect) {
+FormSubmissionThrottle::CheckContentSecurityPolicyFormAction(
+    bool was_server_redirect) {
   // TODO(arthursonzogni): form-action is enforced on the wrong RenderFrameHost.
   // The navigating one is used instead of the one that has initiated the form
   // submission. The renderer side checks are still in place and are used for
@@ -59,7 +60,7 @@
   // compromised) renderer being responsible for enforcing the CSP of another
   // (victim) renderer. Therefore it is okay to return early and do no further
   // browser-side checks.
-  if (!is_redirect)
+  if (!was_server_redirect)
     return NavigationThrottle::PROCEED;
 
   NavigationHandleImpl* handle =
@@ -80,7 +81,7 @@
   // check report-only CSP, (2) upgrade request if needed, (3) check enforced
   // CSP to match how frame-src works. https://crbug.com/713388
   if (render_frame->IsAllowedByCsp(
-          CSPDirective::FormAction, url, is_redirect,
+          CSPDirective::FormAction, url, was_server_redirect,
           false /* is_response_check */, handle->source_location(),
           CSPContext::CHECK_ALL_CSP, true /* is_form_submission */)) {
     return NavigationThrottle::PROCEED;
diff --git a/content/browser/frame_host/form_submission_throttle.h b/content/browser/frame_host/form_submission_throttle.h
index 9c11df3..eb95c84 100644
--- a/content/browser/frame_host/form_submission_throttle.h
+++ b/content/browser/frame_host/form_submission_throttle.h
@@ -36,7 +36,7 @@
  private:
   explicit FormSubmissionThrottle(NavigationHandle* handle);
   NavigationThrottle::ThrottleCheckResult CheckContentSecurityPolicyFormAction(
-      bool is_redirect);
+      bool was_server_redirect);
 
   DISALLOW_COPY_AND_ASSIGN(FormSubmissionThrottle);
 };
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc
index ff776ee..bece944 100644
--- a/content/browser/frame_host/navigation_entry_impl.cc
+++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -692,11 +692,8 @@
       !IsViewSourceMode(), should_replace_entry(), GetBaseURLForDataURL(),
       GetHistoryURLForDataURL(), previews_state, navigation_start,
       frame_entry.method(), post_body ? post_body : post_data_,
-      base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
-      has_started_from_context_menu(), has_user_gesture(),
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */, input_start);
+      base::Optional<SourceLocation>(), has_started_from_context_menu(),
+      has_user_gesture(), InitiatorCSPInfo(), input_start);
 }
 
 RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams(
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index bdb0819..b86fa9fc 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -353,7 +353,7 @@
           GURL() /* client_side_redirect_url */,
           base::nullopt /* devtools_initiator_info */),
       request_params, browser_initiated, false /* from_begin_navigation */,
-      &frame_entry, &entry, std::move(navigation_ui_data), nullptr));
+      &frame_entry, &entry, std::move(navigation_ui_data), nullptr, nullptr));
   navigation_request->blob_url_loader_factory_ =
       frame_entry.blob_url_loader_factory();
   return navigation_request;
@@ -369,7 +369,8 @@
     int current_history_list_length,
     bool override_user_agent,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {
   // Only normal navigations to a different document or reloads are expected.
   // - Renderer-initiated fragment-navigations never take place in the browser,
   //   even with PlzNavigate.
@@ -404,7 +405,7 @@
       true,   // from_begin_navigation
       nullptr, entry,
       nullptr,  // navigation_ui_data
-      std::move(navigation_client)));
+      std::move(navigation_client), std::move(navigation_initiator)));
   navigation_request->blob_url_loader_factory_ =
       std::move(blob_url_loader_factory);
   return navigation_request;
@@ -420,7 +421,8 @@
     const FrameNavigationEntry* frame_entry,
     const NavigationEntryImpl* entry,
     std::unique_ptr<NavigationUIData> navigation_ui_data,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client)
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator)
     : frame_tree_node_(frame_tree_node),
       common_params_(common_params),
       begin_params_(std::move(begin_params)),
@@ -541,7 +543,9 @@
   begin_params_->headers = headers.ToString();
 
   initiator_csp_context_.reset(new InitiatorCSPContext(
-      common_params_.initiator_csp, common_params_.initiator_self_source));
+      common_params_.initiator_csp_info.initiator_csp,
+      common_params_.initiator_csp_info.initiator_self_source,
+      std::move(navigation_initiator)));
 }
 
 NavigationRequest::~NavigationRequest() {
@@ -599,8 +603,8 @@
   // otherwise block. Similarly, the NavigationHandle is created afterwards, so
   // that it gets the request URL after potentially being modified by CSP.
   net::Error net_error = CheckContentSecurityPolicy(
-      false /* is redirect */, false /* url_upgraded_after_redirect */,
-      false /* is_response_check */);
+      false /* has_followed redirect */,
+      false /* url_upgraded_after_redirect */, false /* is_response_check */);
   if (net_error != net::OK) {
     // Create a navigation handle so that the correct error code can be set on
     // it by OnRequestFailedInternal().
@@ -693,7 +697,7 @@
               common_params_.navigation_type),
           common_params_.navigation_start, nav_entry_id_,
           common_params_.started_from_context_menu,
-          common_params_.should_check_main_world_csp,
+          common_params_.initiator_csp_info.should_check_main_world_csp,
           begin_params_->is_form_submission, std::move(navigation_ui_data_),
           common_params_.method, std::move(headers), common_params_.post_data,
           Referrer::SanitizeForRequest(common_params_.url,
@@ -859,9 +863,10 @@
   // Check Content Security Policy before the NavigationThrottles run. This
   // gives CSP a chance to modify requests that NavigationThrottles would
   // otherwise block.
-  net::Error net_error = CheckContentSecurityPolicy(
-      true /* is redirect */, redirect_info.insecure_scheme_was_upgraded,
-      false /* is_response_check */);
+  net::Error net_error =
+      CheckContentSecurityPolicy(true /* has_followed_redirect */,
+                                 redirect_info.insecure_scheme_was_upgraded,
+                                 false /* is_response_check */);
   if (net_error != net::OK) {
     OnRequestFailedInternal(
         network::URLLoaderCompletionStatus(net_error), false /*skip_throttles*/,
@@ -1110,7 +1115,7 @@
   // redirect or not in order to perform its checks. This is the reason
   // why we need to check the CSP both on request and response.
   net::Error net_error = CheckContentSecurityPolicy(
-      navigation_handle_->WasServerRedirect(),
+      navigation_handle_->WasServerRedirect() /* has_followed_redirect */,
       false /* url_upgraded_after_redirect */, true /* is_response_check */);
   if (net_error != net::OK) {
     OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
@@ -1685,7 +1690,7 @@
 bool NavigationRequest::IsAllowedByCSPDirective(
     CSPContext* context,
     CSPDirective::Name directive,
-    bool is_redirect,
+    bool has_followed_redirect,
     bool url_upgraded_after_redirect,
     bool is_response_check,
     CSPContext::CheckCSPDisposition disposition) {
@@ -1702,25 +1707,26 @@
     url = common_params_.url;
   }
   return context->IsAllowedByCsp(
-      directive, url, is_redirect, is_response_check,
+      directive, url, has_followed_redirect, is_response_check,
       common_params_.source_location.value_or(SourceLocation()), disposition,
       begin_params_->is_form_submission);
 }
 
 net::Error NavigationRequest::CheckCSPDirectives(
     RenderFrameHostImpl* parent,
-    bool is_redirect,
+    bool has_followed_redirect,
     bool url_upgraded_after_redirect,
     bool is_response_check,
     CSPContext::CheckCSPDisposition disposition) {
   bool navigate_to_allowed = IsAllowedByCSPDirective(
-      initiator_csp_context_.get(), CSPDirective::NavigateTo, is_redirect,
-      url_upgraded_after_redirect, is_response_check, disposition);
+      initiator_csp_context_.get(), CSPDirective::NavigateTo,
+      has_followed_redirect, url_upgraded_after_redirect, is_response_check,
+      disposition);
 
   bool frame_src_allowed = true;
   if (parent) {
     frame_src_allowed = IsAllowedByCSPDirective(
-        parent, CSPDirective::FrameSrc, is_redirect,
+        parent, CSPDirective::FrameSrc, has_followed_redirect,
         url_upgraded_after_redirect, is_response_check, disposition);
   }
 
@@ -1740,13 +1746,13 @@
 }
 
 net::Error NavigationRequest::CheckContentSecurityPolicy(
-    bool is_redirect,
+    bool has_followed_redirect,
     bool url_upgraded_after_redirect,
     bool is_response_check) {
   if (common_params_.url.SchemeIs(url::kAboutScheme))
     return net::OK;
 
-  if (common_params_.should_check_main_world_csp ==
+  if (common_params_.initiator_csp_info.should_check_main_world_csp ==
       CSPDisposition::DO_NOT_CHECK) {
     return net::OK;
   }
@@ -1772,13 +1778,13 @@
   // This sequence of events allows site owners to learn about (via step 1) any
   // requests that are upgraded in step 2.
 
-  net::Error report_only_csp_status =
-      CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
-                         is_response_check, CSPContext::CHECK_REPORT_ONLY_CSP);
+  net::Error report_only_csp_status = CheckCSPDirectives(
+      parent, has_followed_redirect, url_upgraded_after_redirect,
+      is_response_check, CSPContext::CHECK_REPORT_ONLY_CSP);
 
   // upgrade-insecure-requests is handled in the network code for redirects,
   // only do the upgrade here if this is not a redirect.
-  if (!is_redirect && !frame_tree_node()->IsMainFrame()) {
+  if (!has_followed_redirect && !frame_tree_node()->IsMainFrame()) {
     if (parent &&
         parent->ShouldModifyRequestUrlForCsp(true /* is subresource */)) {
       upgrade_if_insecure_ = true;
@@ -1787,9 +1793,9 @@
     }
   }
 
-  net::Error enforced_csp_status =
-      CheckCSPDirectives(parent, is_redirect, url_upgraded_after_redirect,
-                         is_response_check, CSPContext::CHECK_ENFORCED_CSP);
+  net::Error enforced_csp_status = CheckCSPDirectives(
+      parent, has_followed_redirect, url_upgraded_after_redirect,
+      is_response_check, CSPContext::CHECK_ENFORCED_CSP);
   if (enforced_csp_status != net::OK)
     return enforced_csp_status;
   return report_only_csp_status;
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h
index 44fae3f..7d37652 100644
--- a/content/browser/frame_host/navigation_request.h
+++ b/content/browser/frame_host/navigation_request.h
@@ -111,7 +111,8 @@
       int current_history_list_length,
       bool override_user_agent,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client);
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
 
   ~NavigationRequest() override;
 
@@ -226,7 +227,8 @@
                     const FrameNavigationEntry* frame_navigation_entry,
                     const NavigationEntryImpl* navitation_entry,
                     std::unique_ptr<NavigationUIData> navigation_ui_data,
-                    mojom::NavigationClientAssociatedPtrInfo navigation_client);
+                    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+                    blink::mojom::NavigationInitiatorPtr navigation_initiator);
 
   // NavigationURLLoaderDelegate implementation.
   void OnRequestRedirected(
@@ -286,7 +288,7 @@
   // and navigate-to checks.
   bool IsAllowedByCSPDirective(CSPContext* context,
                                CSPDirective::Name directive,
-                               bool is_redirect,
+                               bool has_followed_redirect,
                                bool url_upgraded_after_redirect,
                                bool is_response_check,
                                CSPContext::CheckCSPDisposition disposition);
@@ -296,7 +298,7 @@
   // Returns net::OK if the checks pass, and net::ERR_ABORTED or
   // net::ERR_BLOCKED_BY_CLIENT depending on which checks fail.
   net::Error CheckCSPDirectives(RenderFrameHostImpl* parent,
-                                bool is_redirect,
+                                bool has_followed_redirect,
                                 bool url_upgraded_after_redirect,
                                 bool is_response_check,
                                 CSPContext::CheckCSPDisposition disposition);
@@ -307,7 +309,7 @@
   //   a report will be sent.
   // - The navigation request may be upgraded from HTTP to HTTPS if a CSP is
   //   configured to upgrade insecure requests.
-  net::Error CheckContentSecurityPolicy(bool is_redirect,
+  net::Error CheckContentSecurityPolicy(bool has_followed_redirect,
                                         bool url_upgraded_after_redirect,
                                         bool is_response_check);
 
diff --git a/content/browser/frame_host/navigator.cc b/content/browser/frame_host/navigator.cc
index 59cea6f..7cce6d2 100644
--- a/content/browser/frame_host/navigator.cc
+++ b/content/browser/frame_host/navigator.cc
@@ -32,6 +32,7 @@
     const CommonNavigationParams& common_params,
     mojom::BeginNavigationParamsPtr begin_params,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {}
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {}
 
 }  // namespace content
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
index a57db61..a02d2e9 100644
--- a/content/browser/frame_host/navigator.h
+++ b/content/browser/frame_host/navigator.h
@@ -144,7 +144,8 @@
       const CommonNavigationParams& common_params,
       mojom::BeginNavigationParamsPtr begin_params,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client);
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
 
   // Used to restart a navigation that was thought to be same-document in
   // cross-document mode.
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 201a8526..7d7544d 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -582,7 +582,8 @@
     const CommonNavigationParams& common_params,
     mojom::BeginNavigationParamsPtr begin_params,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {
   // TODO(clamy): the url sent by the renderer should be validated with
   // FilterURL.
   // This is a renderer-initiated navigation.
@@ -645,7 +646,8 @@
           frame_tree_node, pending_entry, common_params,
           std::move(begin_params), controller_->GetLastCommittedEntryIndex(),
           controller_->GetEntryCount(), override_user_agent,
-          std::move(blob_url_loader_factory), std::move(navigation_client)));
+          std::move(blob_url_loader_factory), std::move(navigation_client),
+          std::move(navigation_initiator)));
   NavigationRequest* navigation_request = frame_tree_node->navigation_request();
 
   // This frame has already run beforeunload before it sent this IPC.  See if
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index 5efb8da..cfc5634 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -90,7 +90,8 @@
       const CommonNavigationParams& common_params,
       mojom::BeginNavigationParamsPtr begin_params,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator) override;
   void RestartNavigationAsCrossDocument(
       std::unique_ptr<NavigationRequest> navigation_request) override;
   void OnAbortNavigation(FrameTreeNode* frame_tree_node) override;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 9d82fe28..b71ff538 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -487,23 +487,27 @@
   mojom::BeginNavigationParamsPtr begin_navigation_params;
   scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
   mojom::NavigationClientAssociatedPtrInfo navigation_client;
+  blink::mojom::NavigationInitiatorPtr navigation_initiator;
 
   PendingNavigation(
       CommonNavigationParams common_params,
       mojom::BeginNavigationParamsPtr begin_navigation_params,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client);
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
 };
 
 PendingNavigation::PendingNavigation(
     CommonNavigationParams common_params,
     mojom::BeginNavigationParamsPtr begin_navigation_params,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client)
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator)
     : common_params(common_params),
       begin_navigation_params(std::move(begin_navigation_params)),
       blob_url_loader_factory(std::move(blob_url_loader_factory)),
-      navigation_client(std::move(navigation_client)) {}
+      navigation_client(std::move(navigation_client)),
+      navigation_initiator(std::move(navigation_initiator)) {}
 
 class FileChooserImpl : public content::FileSelectListener,
                         private content::WebContentsObserver {
@@ -1594,7 +1598,8 @@
         frame_tree_node(), pending_navigate_->common_params,
         std::move(pending_navigate_->begin_navigation_params),
         std::move(pending_navigate_->blob_url_loader_factory),
-        std::move(pending_navigate_->navigation_client));
+        std::move(pending_navigate_->navigation_client),
+        std::move(pending_navigate_->navigation_initiator));
     pending_navigate_.reset();
   }
 }
@@ -3483,7 +3488,8 @@
     const CommonNavigationParams& common_params,
     mojom::BeginNavigationParamsPtr begin_params,
     blink::mojom::BlobURLTokenPtr blob_url_token,
-    mojom::NavigationClientAssociatedPtrInfo navigation_client) {
+    mojom::NavigationClientAssociatedPtrInfo navigation_client,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator) {
   if (!is_active())
     return;
 
@@ -3547,13 +3553,15 @@
   if (waiting_for_init_) {
     pending_navigate_ = std::make_unique<PendingNavigation>(
         validated_params, std::move(begin_params),
-        std::move(blob_url_loader_factory), std::move(navigation_client));
+        std::move(blob_url_loader_factory), std::move(navigation_client),
+        std::move(navigation_initiator));
     return;
   }
 
   frame_tree_node()->navigator()->OnBeginNavigation(
       frame_tree_node(), validated_params, std::move(begin_params),
-      std::move(blob_url_loader_factory), std::move(navigation_client));
+      std::move(blob_url_loader_factory), std::move(navigation_client),
+      std::move(navigation_initiator));
 }
 
 void RenderFrameHostImpl::SubresourceResponseStarted(
@@ -3833,13 +3841,10 @@
   DCHECK(data_url.SchemeIs(url::kDataScheme));
   CommonNavigationParams common_params(
       data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
-      FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false,
-      GURL(), GURL(), PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
-      base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
-      false /* started_from_context_menu */, false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT, false, false, GURL(), GURL(),
+      PREVIEWS_OFF, base::TimeTicks::Now(), "GET", nullptr,
+      base::Optional<SourceLocation>(), false /* started_from_context_menu */,
+      false /* has_user_gesture */, InitiatorCSPInfo());
   CommitNavigation(0, nullptr, network::mojom::URLLoaderClientEndpointsPtr(),
                    common_params, RequestNavigationParams(), false,
                    base::nullopt, base::nullopt /* subresource_overrides */,
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 00563fa..b75cf70 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -67,6 +67,7 @@
 #include "third_party/blink/public/common/frame/user_activation_update_type.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
 #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h"
 #include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
 #include "third_party/blink/public/platform/dedicated_worker_factory.mojom.h"
 #include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
@@ -996,7 +997,8 @@
       const CommonNavigationParams& common_params,
       mojom::BeginNavigationParamsPtr begin_params,
       blink::mojom::BlobURLTokenPtr blob_url_token,
-      mojom::NavigationClientAssociatedPtrInfo navigation_client) override;
+      mojom::NavigationClientAssociatedPtrInfo navigation_client,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator) override;
   void SubresourceResponseStarted(const GURL& url,
                                   net::CertStatus cert_status) override;
   void ResourceLoadComplete(
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc
index b657fa5..3310e9b 100644
--- a/content/browser/frame_host/render_frame_message_filter.cc
+++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -375,9 +375,9 @@
           }
         })");
   std::unique_ptr<download::DownloadUrlParameters> parameters(
-      new download::DownloadUrlParameters(
-          url, render_process_id_, render_view_id, render_frame_id,
-          request_context_.get(), traffic_annotation));
+      new download::DownloadUrlParameters(url, render_process_id_,
+                                          render_view_id, render_frame_id,
+                                          traffic_annotation));
   parameters->set_content_initiated(true);
   parameters->set_suggested_name(suggested_name);
   parameters->set_prompt(use_prompt);
diff --git a/content/browser/initiator_csp_context.cc b/content/browser/initiator_csp_context.cc
index a29e02d..2529f9e 100644
--- a/content/browser/initiator_csp_context.cc
+++ b/content/browser/initiator_csp_context.cc
@@ -8,8 +8,10 @@
 
 InitiatorCSPContext::InitiatorCSPContext(
     const std::vector<ContentSecurityPolicy>& policies,
-    base::Optional<CSPSource>& self_source)
-    : reporting_render_frame_host_impl_(nullptr) {
+    base::Optional<CSPSource>& self_source,
+    blink::mojom::NavigationInitiatorPtr navigation_initiator)
+    : reporting_render_frame_host_impl_(nullptr),
+      initiator_ptr(std::move(navigation_initiator)) {
   for (const auto& policy : policies)
     AddContentSecurityPolicy(policy);
 
@@ -17,6 +19,8 @@
     SetSelf(self_source.value());
 }
 
+InitiatorCSPContext::~InitiatorCSPContext() {}
+
 void InitiatorCSPContext::SetReportingRenderFrameHost(
     RenderFrameHostImpl* rfh) {
   reporting_render_frame_host_impl_ = rfh;
@@ -24,9 +28,19 @@
 
 void InitiatorCSPContext::ReportContentSecurityPolicyViolation(
     const CSPViolationParams& violation_params) {
-  if (reporting_render_frame_host_impl_) {
-    reporting_render_frame_host_impl_->ReportContentSecurityPolicyViolation(
-        violation_params);
+  if (initiator_ptr.is_bound()) {
+    initiator_ptr->SendViolationReport(blink::mojom::CSPViolationParams::New(
+        violation_params.directive, violation_params.effective_directive,
+        violation_params.console_message, violation_params.blocked_url.spec(),
+        violation_params.report_endpoints, violation_params.use_reporting_api,
+        violation_params.header,
+        (blink::mojom::WebContentSecurityPolicyType)
+            violation_params.disposition,
+        violation_params.after_redirect,
+        blink::mojom::SourceLocation::New(
+            violation_params.source_location.url,
+            violation_params.source_location.column_number,
+            violation_params.source_location.line_number)));
   }
 }
 
diff --git a/content/browser/initiator_csp_context.h b/content/browser/initiator_csp_context.h
index e370eee3..097e228 100644
--- a/content/browser/initiator_csp_context.h
+++ b/content/browser/initiator_csp_context.h
@@ -20,8 +20,11 @@
 // `navigate-to` and `form-action` (in the case of form submissions).
 class InitiatorCSPContext : public CSPContext {
  public:
-  InitiatorCSPContext(const std::vector<ContentSecurityPolicy>& policies,
-                      base::Optional<CSPSource>& self_source);
+  InitiatorCSPContext(
+      const std::vector<ContentSecurityPolicy>& policies,
+      base::Optional<CSPSource>& self_source,
+      blink::mojom::NavigationInitiatorPtr navigation_initiator);
+  ~InitiatorCSPContext() override;
 
   void ReportContentSecurityPolicyViolation(
       const CSPViolationParams& violation_params) override;
@@ -35,6 +38,9 @@
 
  private:
   RenderFrameHostImpl* reporting_render_frame_host_impl_;
+  blink::mojom::NavigationInitiatorPtr initiator_ptr;
+
+  DISALLOW_COPY_AND_ASSIGN(InitiatorCSPContext);
 };
 
 }  // namespace content
diff --git a/content/browser/loader/cross_site_document_blocking_browsertest.cc b/content/browser/loader/cross_site_document_blocking_browsertest.cc
index c16b4cc..b811e6d9 100644
--- a/content/browser/loader/cross_site_document_blocking_browsertest.cc
+++ b/content/browser/loader/cross_site_document_blocking_browsertest.cc
@@ -332,10 +332,10 @@
 // Note that this BaseTest class does not specify an isolation mode via
 // command-line flags.  Most of the tests are in the --site-per-process subclass
 // below.
-class CrossSiteDocumentBlockingTest : public ContentBrowserTest {
+class CrossSiteDocumentBlockingTestBase : public ContentBrowserTest {
  public:
-  CrossSiteDocumentBlockingTest() {}
-  ~CrossSiteDocumentBlockingTest() override {}
+  CrossSiteDocumentBlockingTestBase() = default;
+  ~CrossSiteDocumentBlockingTestBase() override = default;
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     // EmbeddedTestServer::InitializeAndListen() initializes its |base_url_|
@@ -369,10 +369,38 @@
   DisableWebSecurityContentBrowserClient new_client;
   ContentBrowserClient* old_client = nullptr;
 
+  DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingTestBase);
+};
+
+enum class TestMode {
+  kWithoutOutOfBlinkCors,
+  kWithOutOfBlinkCors,
+};
+class CrossSiteDocumentBlockingTest
+    : public CrossSiteDocumentBlockingTestBase,
+      public testing::WithParamInterface<TestMode> {
+ public:
+  CrossSiteDocumentBlockingTest() {
+    switch (GetParam()) {
+      case TestMode::kWithoutOutOfBlinkCors:
+        scoped_feature_list_.InitAndDisableFeature(
+            network::features::kOutOfBlinkCORS);
+        break;
+      case TestMode::kWithOutOfBlinkCors:
+        scoped_feature_list_.InitAndEnableFeature(
+            network::features::kOutOfBlinkCORS);
+        break;
+    }
+  }
+  ~CrossSiteDocumentBlockingTest() override = default;
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   DISALLOW_COPY_AND_ASSIGN(CrossSiteDocumentBlockingTest);
 };
 
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockDocuments) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockDocuments) {
   // Load a page that issues illegal cross-site document requests to bar.com.
   // The page uses XHR to request HTML/XML/JSON documents from bar.com, and
   // inspects if any of them were successfully received. This test is only
@@ -380,6 +408,15 @@
   // it to see the response body if it makes it to the renderer (even if the
   // renderer would normally block access to it).
   embedded_test_server()->StartAcceptingConnections();
+
+  // This test does not work and won't make much sense if kOutOfBlinkCORS is
+  // enabled. We need to rewrite this test once the feature is shipped. We would
+  // like to add other tests for verifying behavior for fetch mode "no-cors".
+  // See crbug.com/736308, and discussion at http://crrev.com/c/1253623.
+  // The test server should be started before to shutdown tests safely.
+  if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
+    return;
+
   GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
   EXPECT_TRUE(NavigateToURL(shell(), foo_url));
 
@@ -494,8 +531,14 @@
 // can't cause sniffing to fail to force a response to be allowed.  This won't
 // be a problem for script files mislabeled as HTML/XML/JSON/text (i.e., the
 // reason for sniffing), since script tags won't send Range headers.
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, RangeRequest) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, RangeRequest) {
   embedded_test_server()->StartAcceptingConnections();
+
+  // This test does not work and won't make much sense if kOutOfBlinkCORS is
+  // enabled. See detailed comments on BlockDocuments above.
+  if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
+    return;
+
   GURL foo_url("http://foo.com/cross_site_document_blocking/request.html");
   EXPECT_TRUE(NavigateToURL(shell(), foo_url));
 
@@ -536,7 +579,7 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockForVariousTargets) {
   // This webpage loads a cross-site HTML page in different targets such as
   // <img>,<link>,<embed>, etc. Since the requested document is blocked, and one
   // character string (' ') is returned instead, this tests that the renderer
@@ -556,7 +599,7 @@
 
 // Checks to see that CORB blocking applies to processes hosting error pages.
 // Regression test for https://crbug.com/814913.
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest,
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest,
                        BlockRequestFromErrorPage) {
   embedded_test_server()->StartAcceptingConnections();
   GURL error_url = embedded_test_server()->GetURL("bar.com", "/close-socket");
@@ -588,9 +631,14 @@
   EXPECT_EQ("CORB WORKED", result);
 }
 
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, BlockHeaders) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, BlockHeaders) {
   embedded_test_server()->StartAcceptingConnections();
 
+  // This test does not work and won't make much sense if kOutOfBlinkCORS is
+  // enabled. See detailed comments on BlockDocuments above.
+  if (base::FeatureList::IsEnabled(network::features::kOutOfBlinkCORS))
+    return;
+
   // Prepare to intercept the network request at the IPC layer.
   // This has to be done before the RenderFrameHostImpl is created.
   //
@@ -639,7 +687,7 @@
   EXPECT_EQ(0u, interceptor.response_head().content_length);
 }
 
-IN_PROC_BROWSER_TEST_F(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
+IN_PROC_BROWSER_TEST_P(CrossSiteDocumentBlockingTest, PrefetchIsNotImpacted) {
   // Prepare for intercepting the resource request for testing prefetching.
   const char* kPrefetchResourcePath = "/prefetch-test";
   net::test_server::ControllableHttpResponse response(embedded_test_server(),
@@ -746,6 +794,14 @@
   EXPECT_EQ("<p>contents of the response</p>", response_body);
 }
 
+INSTANTIATE_TEST_CASE_P(WithoutOutOfBlinkCors,
+                        CrossSiteDocumentBlockingTest,
+                        ::testing::Values(TestMode::kWithoutOutOfBlinkCors));
+
+INSTANTIATE_TEST_CASE_P(WithOutOfBlinkCors,
+                        CrossSiteDocumentBlockingTest,
+                        ::testing::Values(TestMode::kWithOutOfBlinkCors));
+
 // This test class sets up a service worker that can be used to try to respond
 // to same-origin requests with cross-origin responses.
 class CrossSiteDocumentBlockingServiceWorkerTest : public ContentBrowserTest {
@@ -939,14 +995,14 @@
 // Test class to verify that --disable-web-security turns off CORB.  This
 // inherits from CrossSiteDocumentBlockingTest, so it runs in SitePerProcess.
 class CrossSiteDocumentBlockingDisableWebSecurityTest
-    : public CrossSiteDocumentBlockingTest {
+    : public CrossSiteDocumentBlockingTestBase {
  public:
   CrossSiteDocumentBlockingDisableWebSecurityTest() {}
   ~CrossSiteDocumentBlockingDisableWebSecurityTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kDisableWebSecurity);
-    CrossSiteDocumentBlockingTest::SetUpCommandLine(command_line);
+    CrossSiteDocumentBlockingTestBase::SetUpCommandLine(command_line);
   }
 
  private:
@@ -968,7 +1024,7 @@
 
 // Test class to verify that documents are blocked for isolated origins as well.
 class CrossSiteDocumentBlockingIsolatedOriginTest
-    : public CrossSiteDocumentBlockingTest {
+    : public CrossSiteDocumentBlockingTestBase {
  public:
   CrossSiteDocumentBlockingIsolatedOriginTest() {}
   ~CrossSiteDocumentBlockingIsolatedOriginTest() override {}
@@ -976,7 +1032,7 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitchASCII(switches::kIsolateOrigins,
                                     "http://bar.com");
-    CrossSiteDocumentBlockingTest::SetUpCommandLine(command_line);
+    CrossSiteDocumentBlockingTestBase::SetUpCommandLine(command_line);
   }
 
  private:
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index c101d5f..64be3e15 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -585,10 +585,8 @@
       GURL() /* history_url_for_data_url */, PREVIEWS_UNSPECIFIED,
       base::TimeTicks::Now() /* navigation_start */, "GET",
       nullptr /* post_data */, base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK, false /* started_from_context_menu */,
-      false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      false /* started_from_context_menu */, false /* has_user_gesture */,
+      InitiatorCSPInfo());
   mojom::BeginNavigationParamsPtr begin_params =
       mojom::BeginNavigationParams::New(
           std::string() /* headers */, net::LOAD_NORMAL,
@@ -610,10 +608,10 @@
         mojo::MakeRequestAssociatedWithDedicatedPipe(&navigation_client);
     rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
         common_params, std::move(begin_params), nullptr,
-        navigation_client.PassInterface());
+        navigation_client.PassInterface(), nullptr);
   } else {
     rfh->frame_host_binding_for_testing().impl()->BeginNavigation(
-        common_params, std::move(begin_params), nullptr, nullptr);
+        common_params, std::move(begin_params), nullptr, nullptr, nullptr);
   }
   EXPECT_EQ(bad_message::RFH_BASE_URL_FOR_DATA_URL_SPECIFIED,
             process_kill_waiter.Wait());
diff --git a/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm b/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
index bad8454..b0a397f 100644
--- a/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
+++ b/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
@@ -434,7 +434,7 @@
 }
 
 // Test conversion from key combination with Control to DomKey.
-// TODO(chongz): Move DomKey tests for all platforms into one place.
+// TODO(input-dev): Move DomKey tests for all platforms into one place.
 // http://crbug.com/587589
 // This test case only works for U.S. layout.
 TEST(WebInputEventBuilderMacTest, DomKeyCtrlShift) {
@@ -781,4 +781,4 @@
   EXPECT_EQ(60, touch_event.touches[0].twist);
   EXPECT_FLOAT_EQ(60.0, touch_event.touches[0].rotation_angle);
 }
-#endif  // MAC_OS_X_VERSION_10_12
\ No newline at end of file
+#endif  // MAC_OS_X_VERSION_10_12
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
index b74462f..f0aadfcb 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
@@ -68,7 +68,8 @@
       external_plugin_(host->external_plugin()),
       private_api_(private_api),
       render_process_id_(0),
-      render_frame_id_(0) {
+      render_frame_id_(0),
+      weak_ptr_factory_(this) {
   ++g_num_instances;
   DCHECK(factory_);
   DCHECK(ppapi_host_);
@@ -178,7 +179,7 @@
       mojo::MakeRequest(&socket_),
       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
           base::BindOnce(&PepperTCPServerSocketMessageFilter::OnListenCompleted,
-                         base::Unretained(this), reply_context),
+                         weak_ptr_factory_.GetWeakPtr(), reply_context),
           net::ERR_FAILED, base::nullopt /* local_addr_out */));
 
   return PP_OK_COMPLETIONPENDING;
@@ -371,8 +372,9 @@
 void PepperTCPServerSocketMessageFilter::Close() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  // This needs to be the first line, so if closing Mojo pipes results in
-  // invoking any callbacks, they can exit early.
+  // Need to do these first, as destroying Mojo pipes may invoke some of the
+  // callbacks with failure messages.
+  weak_ptr_factory_.InvalidateWeakPtrs();
   state_ = STATE_CLOSED;
 
   socket_.reset();
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h b/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
index 482d7450..96456ab0 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
+++ b/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h
@@ -13,6 +13,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
@@ -163,6 +164,10 @@
   // Used in place of the StoragePartition's NetworkContext when non-null.
   static network::mojom::NetworkContext* network_context_for_testing;
 
+  // Vends weak pointers on the UI thread, for callbacks passed through Mojo
+  // pipes not owned by |this|. All weak pointers released in Close().
+  base::WeakPtrFactory<PepperTCPServerSocketMessageFilter> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(PepperTCPServerSocketMessageFilter);
 };
 
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
index 044e303..2e6b9ce1 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -88,7 +88,8 @@
       pending_write_bytes_written_(0),
       pending_write_pp_error_(PP_OK_COMPLETIONPENDING),
       is_potentially_secure_plugin_context_(
-          host->IsPotentiallySecurePluginContext(instance)) {
+          host->IsPotentiallySecurePluginContext(instance)),
+      weak_ptr_factory_(this) {
   DCHECK(host);
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
@@ -360,7 +361,7 @@
       mojo::MakeRequest(&bound_socket_),
       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
           base::BindOnce(&PepperTCPSocketMessageFilter::OnBindCompleted,
-                         base::Unretained(this),
+                         weak_ptr_factory_.GetWeakPtr(),
                          context->MakeReplyMessageContext()),
           net::ERR_FAILED, base::nullopt /* local_addr */));
 
@@ -880,7 +881,7 @@
   network::mojom::NetworkContext::CreateTCPConnectedSocketCallback callback =
       mojo::WrapCallbackWithDefaultInvokeIfNotRun(
           base::BindOnce(&PepperTCPSocketMessageFilter::OnConnectCompleted,
-                         base::Unretained(this), context),
+                         weak_ptr_factory_.GetWeakPtr(), context),
           net::ERR_FAILED, base::nullopt, base::nullopt,
           mojo::ScopedDataPipeConsumerHandle(),
           mojo::ScopedDataPipeProducerHandle());
@@ -1335,8 +1336,9 @@
 void PepperTCPSocketMessageFilter::Close() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  // Need to do this first, as destroying Mojo pipes may invoke some of the
+  // Need to do these first, as destroying Mojo pipes may invoke some of the
   // callbacks with failure messages.
+  weak_ptr_factory_.InvalidateWeakPtrs();
   state_.DoTransition(TCPSocketState::CLOSE, true);
 
 #if defined(OS_CHROMEOS)
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
index ecd25e9..8c49f6c 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
+++ b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h
@@ -15,6 +15,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "build/build_config.h"
 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
@@ -363,6 +364,10 @@
   // Used in place of the StoragePartition's NetworkContext when non-null.
   static network::mojom::NetworkContext* network_context_for_testing;
 
+  // Vends weak pointers on the UI thread, for callbacks passed through Mojo
+  // pipes not owned by |this|. All weak pointers released in Close().
+  base::WeakPtrFactory<PepperTCPSocketMessageFilter> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(PepperTCPSocketMessageFilter);
 };
 
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index 2e2865b..c7bec6f 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -219,7 +219,7 @@
       // If the waiting worker is ready and the active worker needs to be
       // swapped out, ask the active worker to trigger idle timer as soon as
       // possible.
-      active_version()->endpoint()->SetIdleTimerDelayToZero();
+      active_version()->TriggerIdleTerminationAsap();
     }
     StartLameDuckTimer();
   }
@@ -302,7 +302,7 @@
       // If the waiting worker is ready and the active worker needs to be
       // swapped out, ask the active worker to trigger idle timer as soon as
       // possible.
-      active_version()->endpoint()->SetIdleTimerDelayToZero();
+      active_version()->TriggerIdleTerminationAsap();
     }
     StartLameDuckTimer();
   }
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc
index 05369bda..4c9120a 100644
--- a/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -373,9 +373,8 @@
 
 // Sets up a registration with a waiting worker, and an active worker
 // with a controllee and an inflight request.
-class ServiceWorkerActivationTest
-    : public ServiceWorkerRegistrationTest,
-      public testing::WithParamInterface<bool /* attach_devtools */> {
+class ServiceWorkerActivationTest : public ServiceWorkerRegistrationTest,
+                                    public testing::WithParamInterface<bool> {
  public:
   ServiceWorkerActivationTest() : ServiceWorkerRegistrationTest() {}
 
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 6e50697..24838249 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -466,6 +466,11 @@
   NOTREACHED();
 }
 
+void ServiceWorkerVersion::TriggerIdleTerminationAsap() {
+  needs_to_be_terminated_asap_ = true;
+  endpoint()->SetIdleTimerDelayToZero();
+}
+
 bool ServiceWorkerVersion::OnRequestTermination() {
   if (running_status() == EmbeddedWorkerStatus::STOPPING)
     return true;
@@ -477,12 +482,9 @@
   bool will_be_terminated = HasNoWork();
   if (embedded_worker_->devtools_attached()) {
     // Basically the service worker won't be terminated if DevTools is attached.
-    will_be_terminated = false;
-
     // But when activation is happening and this worker needs to be terminated
     // asap, it'll be terminated.
-    // TODO(shimazu): implement it to make activation progress, otherwise
-    // activation won't be triggered until DevTools is closed.
+    will_be_terminated = needs_to_be_terminated_asap_;
   }
 
   if (will_be_terminated) {
@@ -1558,6 +1560,7 @@
 
   StartTimeoutTimer();
   worker_is_idle_on_renderer_ = false;
+  needs_to_be_terminated_asap_ = false;
 
   auto provider_info = mojom::ServiceWorkerProviderInfoForStartWorker::New();
   provider_host_ = ServiceWorkerProviderHost::PreCreateForController(
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 4ce8ba3..014c8eaa 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -252,6 +252,12 @@
   // Stops an embedded worker for this version.
   void StopWorker(base::OnceClosure callback);
 
+  // Asks the renderer to notify the browser that it becomes idle as soon as
+  // possible, and it results in letting idle termination occur earlier. This is
+  // typically used for activation. An active worker needs to be swapped out
+  // soon after the service worker becomes idle if a waiting worker exists.
+  void TriggerIdleTerminationAsap();
+
   // S13nServiceWorker:
   // Called when the renderer notifies the browser that the worker is now idle.
   // Returns true if the worker will be terminated and the worker should not
@@ -862,6 +868,10 @@
   // is no longer idle.
   bool worker_is_idle_on_renderer_ = true;
 
+  // S13nServiceWorker: Set to true when the worker needs to be terminated as
+  // soon as possible (e.g. activation).
+  bool needs_to_be_terminated_asap_ = false;
+
   // Keeps track of the provider hosting this running service worker for this
   // version. |provider_host_| is always valid as long as this version is
   // running.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 7e93694a..ea38ab7 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3764,8 +3764,6 @@
   bool is_main_frame = (url == GetLastCommittedURL());
   RenderFrameHost* frame_host = GetMainFrame();
 
-  StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
-      GetBrowserContext(), frame_host->GetSiteInstance());
   int64_t post_id = -1;
   if (is_main_frame) {
     const NavigationEntry* entry = controller_.GetLastCommittedEntry();
@@ -3795,8 +3793,7 @@
   auto params = std::make_unique<download::DownloadUrlParameters>(
       url, frame_host->GetProcess()->GetID(),
       frame_host->GetRenderViewHost()->GetRoutingID(),
-      frame_host->GetRoutingID(), storage_partition->GetURLRequestContext(),
-      traffic_annotation);
+      frame_host->GetRoutingID(), traffic_annotation);
   params->set_referrer(referrer.url);
   params->set_referrer_policy(
       Referrer::ReferrerPolicyForUrlRequest(referrer.policy));
diff --git a/content/common/content_security_policy/content_security_policy.cc b/content/common/content_security_policy/content_security_policy.cc
index 0a5565c5..d024d30 100644
--- a/content/common/content_security_policy/content_security_policy.cc
+++ b/content/common/content_security_policy/content_security_policy.cc
@@ -57,7 +57,7 @@
                      const CSPDirective& directive,
                      const CSPDirective::Name directive_name,
                      const GURL& url,
-                     bool is_redirect,
+                     bool has_followed_redirect,
                      const SourceLocation& source_location) {
   // We should never have a violation against `child-src` or `default-src`
   // directly; the effective directive should always be one of the explicit
@@ -71,8 +71,8 @@
   // renderers.
   GURL safe_url = url;
   SourceLocation safe_source_location = source_location;
-  context->SanitizeDataForUseInCspViolation(is_redirect, directive_name,
-                                            &safe_url, &safe_source_location);
+  context->SanitizeDataForUseInCspViolation(
+      has_followed_redirect, directive_name, &safe_url, &safe_source_location);
 
   std::stringstream message;
 
@@ -103,7 +103,7 @@
       CSPDirective::NameToString(directive.name),
       CSPDirective::NameToString(directive_name), message.str(), safe_url,
       policy.report_endpoints, policy.use_reporting_api,
-      policy.header.header_value, policy.header.type, is_redirect,
+      policy.header.header_value, policy.header.type, has_followed_redirect,
       safe_source_location));
 }
 
@@ -112,16 +112,16 @@
                     const CSPDirective& directive,
                     CSPDirective::Name directive_name,
                     const GURL& url,
-                    bool is_redirect,
+                    bool has_followed_redirect,
                     bool is_response_check,
                     const SourceLocation& source_location) {
-  if (CSPSourceList::Allow(directive.source_list, url, context, is_redirect,
-                           is_response_check)) {
+  if (CSPSourceList::Allow(directive.source_list, url, context,
+                           has_followed_redirect, is_response_check)) {
     return true;
   }
 
-  ReportViolation(context, policy, directive, directive_name, url, is_redirect,
-                  source_location);
+  ReportViolation(context, policy, directive, directive_name, url,
+                  has_followed_redirect, source_location);
   return false;
 }
 
@@ -164,7 +164,7 @@
 bool ContentSecurityPolicy::Allow(const ContentSecurityPolicy& policy,
                                   CSPDirective::Name directive_name,
                                   const GURL& url,
-                                  bool is_redirect,
+                                  bool has_followed_redirect,
                                   bool is_response_check,
                                   CSPContext* context,
                                   const SourceLocation& source_location,
@@ -184,9 +184,9 @@
     const CSPDirective* current_directive =
         FindDirective(current_directive_name, policy.directives);
     if (current_directive) {
-      bool allowed =
-          AllowDirective(context, policy, *current_directive, directive_name,
-                         url, is_redirect, is_response_check, source_location);
+      bool allowed = AllowDirective(context, policy, *current_directive,
+                                    directive_name, url, has_followed_redirect,
+                                    is_response_check, source_location);
       return allowed ||
              policy.header.type == blink::kWebContentSecurityPolicyTypeReport;
     }
diff --git a/content/common/content_security_policy/content_security_policy.h b/content/common/content_security_policy/content_security_policy.h
index abac1de..70113da 100644
--- a/content/common/content_security_policy/content_security_policy.h
+++ b/content/common/content_security_policy/content_security_policy.h
@@ -44,7 +44,7 @@
   static bool Allow(const ContentSecurityPolicy& policy,
                     CSPDirective::Name directive,
                     const GURL& url,
-                    bool is_redirect,
+                    bool has_followed_redirect,
                     bool is_response_check,
                     CSPContext* context,
                     const SourceLocation& source_location,
diff --git a/content/common/content_security_policy/content_security_policy_unittest.cc b/content/common/content_security_policy/content_security_policy_unittest.cc
index a7e57115..a8b5be93 100644
--- a/content/common/content_security_policy/content_security_policy_unittest.cc
+++ b/content/common/content_security_policy/content_security_policy_unittest.cc
@@ -269,7 +269,6 @@
   struct TestCase {
     const CSPSourceList& navigate_to_list;
     const GURL& url;
-    bool is_redirect;
     bool is_response_check;
     bool expected;
     bool is_form_submission;
@@ -277,48 +276,45 @@
   } cases[] = {
       // Basic source matching.
       {none_source_list, GURL("https://example.test"), false, false, false,
-       false, nullptr},
-      {example_source_list, GURL("https://example.test"), false, false, true,
-       false, nullptr},
+       nullptr},
+      {example_source_list, GURL("https://example.test"), false, true, false,
+       nullptr},
       {example_source_list, GURL("https://not-example.test"), false, false,
-       false, false, nullptr},
-      {self_source_list, GURL("https://example.test"), false, false, true,
        false, nullptr},
+      {self_source_list, GURL("https://example.test"), false, true, false,
+       nullptr},
 
       // Checking allow_redirect flag interactions.
-      {redirects_source_list, GURL("https://example.test"), false, false, true,
-       false, nullptr},
-      {redirects_source_list, GURL("https://example.test"), true, false, true,
-       false, nullptr},
-      {redirects_source_list, GURL("https://example.test"), true, true, true,
-       false, nullptr},
       {redirects_source_list, GURL("https://example.test"), false, true, false,
-       false, nullptr},
+       nullptr},
+      {redirects_source_list, GURL("https://example.test"), true, false, false,
+       nullptr},
       {redirects_example_source_list, GURL("https://example.test"), false, true,
-       true, false, nullptr},
+       false, nullptr},
+      {redirects_example_source_list, GURL("https://example.test"), true, true,
+       false, nullptr},
 
       // Interaction with form-action
 
       // Form submission without form-action present
-      {none_source_list, GURL("https://example.test"), false, false, false,
-       true, nullptr},
-      {example_source_list, GURL("https://example.test"), false, false, true,
-       true, nullptr},
+      {none_source_list, GURL("https://example.test"), false, false, true,
+       nullptr},
+      {example_source_list, GURL("https://example.test"), false, true, true,
+       nullptr},
       {example_source_list, GURL("https://not-example.test"), false, false,
-       false, true, nullptr},
-      {self_source_list, GURL("https://example.test"), false, false, true, true,
+       true, nullptr},
+      {self_source_list, GURL("https://example.test"), false, true, true,
        nullptr},
 
       // Form submission with form-action present
-      {none_source_list, GURL("https://example.test"), false, false, true, true,
+      {none_source_list, GURL("https://example.test"), false, true, true,
        &example_source_list},
-      {example_source_list, GURL("https://example.test"), false, false, true,
-       true, &example_source_list},
-      {example_source_list, GURL("https://not-example.test"), false, false,
-       true, true, &example_source_list},
-      {self_source_list, GURL("https://example.test"), false, false, true, true,
+      {example_source_list, GURL("https://example.test"), false, true, true,
        &example_source_list},
-
+      {example_source_list, GURL("https://not-example.test"), false, true, true,
+       &example_source_list},
+      {self_source_list, GURL("https://example.test"), false, true, true,
+       &example_source_list},
   };
 
   for (const auto& test : cases) {
@@ -333,11 +329,14 @@
     ContentSecurityPolicy policy(EmptyCspHeader(), directives,
                                  report_end_points, false);
 
-    EXPECT_EQ(test.expected,
-              ContentSecurityPolicy::Allow(
-                  policy, CSPDirective::NavigateTo, test.url, test.is_redirect,
-                  test.is_response_check, &context, SourceLocation(),
-                  test.is_form_submission));
+    EXPECT_EQ(test.expected, ContentSecurityPolicy::Allow(
+                                 policy, CSPDirective::NavigateTo, test.url,
+                                 true, test.is_response_check, &context,
+                                 SourceLocation(), test.is_form_submission));
+    EXPECT_EQ(test.expected, ContentSecurityPolicy::Allow(
+                                 policy, CSPDirective::NavigateTo, test.url,
+                                 false, test.is_response_check, &context,
+                                 SourceLocation(), test.is_form_submission));
   }
 }
 
diff --git a/content/common/content_security_policy/csp_context.cc b/content/common/content_security_policy/csp_context.cc
index 5e52b72..f83e316 100644
--- a/content/common/content_security_policy/csp_context.cc
+++ b/content/common/content_security_policy/csp_context.cc
@@ -32,7 +32,7 @@
 
 bool CSPContext::IsAllowedByCsp(CSPDirective::Name directive_name,
                                 const GURL& url,
-                                bool is_redirect,
+                                bool has_followed_redirect,
                                 bool is_response_check,
                                 const SourceLocation& source_location,
                                 CheckCSPDisposition check_csp_disposition,
@@ -44,8 +44,8 @@
   for (const auto& policy : policies_) {
     if (ShouldCheckPolicy(policy, check_csp_disposition)) {
       allow &= ContentSecurityPolicy::Allow(
-          policy, directive_name, url, is_redirect, is_response_check, this,
-          source_location, is_form_submission);
+          policy, directive_name, url, has_followed_redirect, is_response_check,
+          this, source_location, is_form_submission);
     }
   }
 
@@ -105,7 +105,7 @@
 }
 
 void CSPContext::SanitizeDataForUseInCspViolation(
-    bool is_redirect,
+    bool has_followed_redirect,
     CSPDirective::Name directive,
     GURL* blocked_url,
     SourceLocation* source_location) const {
diff --git a/content/common/content_security_policy/csp_context.h b/content/common/content_security_policy/csp_context.h
index e7f1cee..fb86c02 100644
--- a/content/common/content_security_policy/csp_context.h
+++ b/content/common/content_security_policy/csp_context.h
@@ -48,7 +48,7 @@
   // Returns true when the request can proceed, false otherwise.
   bool IsAllowedByCsp(CSPDirective::Name directive_name,
                       const GURL& url,
-                      bool is_redirect,
+                      bool has_followed_redirect,
                       bool is_response_check,
                       const SourceLocation& source_location,
                       CheckCSPDisposition check_csp_disposition,
@@ -92,7 +92,7 @@
   // without the round trip in the renderer process.
   // See https://crbug.com/721329
   virtual void SanitizeDataForUseInCspViolation(
-      bool is_redirect,
+      bool has_followed_redirect,
       CSPDirective::Name directive,
       GURL* blocked_url,
       SourceLocation* source_location) const;
diff --git a/content/common/content_security_policy/csp_source.cc b/content/common/content_security_policy/csp_source.cc
index 69b7db2..9ada01e 100644
--- a/content/common/content_security_policy/csp_source.cc
+++ b/content/common/content_security_policy/csp_source.cc
@@ -103,8 +103,8 @@
 
 bool SourceAllowPath(const CSPSource& source,
                      const GURL& url,
-                     bool is_redirect) {
-  if (is_redirect)
+                     bool has_followed_redirect) {
+  if (has_followed_redirect)
     return true;
 
   if (source.path.empty() || url.path().empty())
@@ -174,7 +174,7 @@
 bool CSPSource::Allow(const CSPSource& source,
                       const GURL& url,
                       CSPContext* context,
-                      bool is_redirect) {
+                      bool has_followed_redirect) {
   if (source.IsSchemeOnly())
     return SourceAllowScheme(source, url, context) !=
            SchemeMatchingResult::NotMatching;
@@ -190,7 +190,7 @@
   return schemeResult != SchemeMatchingResult::NotMatching &&
          SourceAllowHost(source, url) &&
          portResult != PortMatchingResult::NotMatching &&
-         SourceAllowPath(source, url, is_redirect);
+         SourceAllowPath(source, url, has_followed_redirect);
 }
 
 std::string CSPSource::ToString() const {
diff --git a/content/common/content_security_policy/csp_source.h b/content/common/content_security_policy/csp_source.h
index 62670ed..de2c051 100644
--- a/content/common/content_security_policy/csp_source.h
+++ b/content/common/content_security_policy/csp_source.h
@@ -59,7 +59,7 @@
   static bool Allow(const CSPSource& source,
                     const GURL& url,
                     CSPContext* context,
-                    bool is_redirect = false);
+                    bool has_followed_redirect = false);
 };
 
 }  // namespace content
diff --git a/content/common/content_security_policy/csp_source_list.cc b/content/common/content_security_policy/csp_source_list.cc
index 4bf358daa1..343c4c1 100644
--- a/content/common/content_security_policy/csp_source_list.cc
+++ b/content/common/content_security_policy/csp_source_list.cc
@@ -11,9 +11,9 @@
 bool AllowFromSources(const GURL& url,
                       const std::vector<CSPSource>& sources,
                       CSPContext* context,
-                      bool is_redirect) {
+                      bool has_followed_redirect) {
   for (const CSPSource& source : sources) {
-    if (CSPSource::Allow(source, url, context, is_redirect))
+    if (CSPSource::Allow(source, url, context, has_followed_redirect))
       return true;
   }
   return false;
@@ -22,15 +22,18 @@
 };  // namespace
 
 CSPSourceList::CSPSourceList()
-    : allow_self(false), allow_star(false), allow_redirects(false), sources() {}
+    : allow_self(false),
+      allow_star(false),
+      allow_response_redirects(false),
+      sources() {}
 
 CSPSourceList::CSPSourceList(bool allow_self,
                              bool allow_star,
-                             bool allow_redirects,
+                             bool allow_response_redirects,
                              std::vector<CSPSource> sources)
     : allow_self(allow_self),
       allow_star(allow_star),
-      allow_redirects(allow_redirects),
+      allow_response_redirects(allow_response_redirects),
       sources(sources) {}
 
 CSPSourceList::CSPSourceList(const CSPSourceList&) = default;
@@ -40,21 +43,16 @@
 bool CSPSourceList::Allow(const CSPSourceList& source_list,
                           const GURL& url,
                           CSPContext* context,
-                          bool is_redirect,
+                          bool has_followed_redirect,
                           bool is_response_check) {
   // If the source list allows all redirects, the decision can't be made until
   // the response is received.
-  if (source_list.allow_redirects && !is_response_check)
+  if (source_list.allow_response_redirects && !is_response_check)
     return true;
 
   // If the source list does not allow all redirects, the decision has already
   // been made when checking the request.
-  if (!source_list.allow_redirects && is_response_check)
-    return true;
-
-  // If the source list allows all redirects, all responses that are a redirect
-  // are allowed.
-  if (source_list.allow_redirects && is_response_check && is_redirect)
+  if (!source_list.allow_response_redirects && is_response_check)
     return true;
 
   // Wildcards match network schemes ('http', 'https', 'ftp', 'ws', 'wss'), and
@@ -73,11 +71,12 @@
 
   if (source_list.allow_self && context->self_source() &&
       CSPSource::Allow(context->self_source().value(), url, context,
-                       is_redirect)) {
+                       has_followed_redirect)) {
     return true;
   }
 
-  return AllowFromSources(url, source_list.sources, context, is_redirect);
+  return AllowFromSources(url, source_list.sources, context,
+                          has_followed_redirect);
 }
 
 std::string CSPSourceList::ToString() const {
diff --git a/content/common/content_security_policy/csp_source_list.h b/content/common/content_security_policy/csp_source_list.h
index 94af7755..a1ce31f 100644
--- a/content/common/content_security_policy/csp_source_list.h
+++ b/content/common/content_security_policy/csp_source_list.h
@@ -18,7 +18,7 @@
   CSPSourceList();
   CSPSourceList(bool allow_self,
                 bool allow_star,
-                bool allow_redirects,
+                bool allow_response_redirects,
                 std::vector<CSPSource> source_list);
   CSPSourceList(const CSPSourceList&);
   ~CSPSourceList();
@@ -27,7 +27,7 @@
   // on the source list itself.
   bool allow_self;
   bool allow_star;
-  bool allow_redirects;
+  bool allow_response_redirects;
   std::vector<CSPSource> sources;
 
   std::string ToString() const;
@@ -39,7 +39,7 @@
   static bool Allow(const CSPSourceList& source_list,
                     const GURL& url,
                     CSPContext* context,
-                    bool is_redirect = false,
+                    bool has_followed_redirect = false,
                     bool is_response_check = false);
 };
 
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 0cd83ad..f598bf8a2 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -20,6 +20,7 @@
 import "services/viz/public/interfaces/compositing/surface_id.mojom";
 import "third_party/blink/public/mojom/blob/blob_url_store.mojom";
 import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom";
+import "third_party/blink/public/mojom/frame/navigation_initiator.mojom";
 import "third_party/blink/public/platform/referrer.mojom";
 import "third_party/blink/public/web/commit_result.mojom";
 import "third_party/blink/public/web/window_features.mojom";
@@ -306,7 +307,8 @@
       CommonNavigationParams common_params,
       BeginNavigationParams begin_params,
       blink.mojom.BlobURLToken? blob_url_token,
-      associated NavigationClient? navigation_client);
+      associated NavigationClient? navigation_client,
+      blink.mojom.NavigationInitiator? navigation_initiator);
 
   // Sent when a subresource response has started.
   // |cert_status| is the bitmask of status info of the SSL certificate. (see
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 6bfafce..eee8d28e 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -460,6 +460,12 @@
   IPC_STRUCT_TRAITS_MEMBER(column_number)
 IPC_STRUCT_TRAITS_END()
 
+IPC_STRUCT_TRAITS_BEGIN(content::InitiatorCSPInfo)
+  IPC_STRUCT_TRAITS_MEMBER(should_check_main_world_csp)
+  IPC_STRUCT_TRAITS_MEMBER(initiator_csp)
+  IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
   IPC_STRUCT_TRAITS_MEMBER(url)
   IPC_STRUCT_TRAITS_MEMBER(referrer)
@@ -474,11 +480,9 @@
   IPC_STRUCT_TRAITS_MEMBER(method)
   IPC_STRUCT_TRAITS_MEMBER(post_data)
   IPC_STRUCT_TRAITS_MEMBER(source_location)
-  IPC_STRUCT_TRAITS_MEMBER(should_check_main_world_csp)
   IPC_STRUCT_TRAITS_MEMBER(has_user_gesture)
   IPC_STRUCT_TRAITS_MEMBER(started_from_context_menu)
-  IPC_STRUCT_TRAITS_MEMBER(initiator_csp)
-  IPC_STRUCT_TRAITS_MEMBER(initiator_self_source)
+  IPC_STRUCT_TRAITS_MEMBER(initiator_csp_info)
   IPC_STRUCT_TRAITS_MEMBER(origin_policy)
   IPC_STRUCT_TRAITS_MEMBER(input_start)
 IPC_STRUCT_TRAITS_END()
@@ -672,6 +676,7 @@
 IPC_STRUCT_TRAITS_BEGIN(content::CSPSourceList)
   IPC_STRUCT_TRAITS_MEMBER(allow_self)
   IPC_STRUCT_TRAITS_MEMBER(allow_star)
+  IPC_STRUCT_TRAITS_MEMBER(allow_response_redirects)
   IPC_STRUCT_TRAITS_MEMBER(sources)
 IPC_STRUCT_TRAITS_END()
 
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc
index 04cf967..e3d07f56 100644
--- a/content/common/navigation_params.cc
+++ b/content/common/navigation_params.cc
@@ -24,6 +24,18 @@
 
 SourceLocation::~SourceLocation() = default;
 
+InitiatorCSPInfo::InitiatorCSPInfo() = default;
+InitiatorCSPInfo::InitiatorCSPInfo(
+    CSPDisposition should_check_main_world_csp,
+    const std::vector<ContentSecurityPolicy>& initiator_csp,
+    const base::Optional<CSPSource>& initiator_self_source)
+    : should_check_main_world_csp(should_check_main_world_csp),
+      initiator_csp(initiator_csp),
+      initiator_self_source(initiator_self_source) {}
+InitiatorCSPInfo::InitiatorCSPInfo(const InitiatorCSPInfo& other) = default;
+
+InitiatorCSPInfo::~InitiatorCSPInfo() = default;
+
 CommonNavigationParams::CommonNavigationParams() = default;
 
 CommonNavigationParams::CommonNavigationParams(
@@ -40,11 +52,9 @@
     std::string method,
     const scoped_refptr<network::ResourceRequestBody>& post_data,
     base::Optional<SourceLocation> source_location,
-    CSPDisposition should_check_main_world_csp,
     bool started_from_context_menu,
     bool has_user_gesture,
-    const std::vector<ContentSecurityPolicy>& initiator_csp,
-    const base::Optional<CSPSource>& initiator_self_source,
+    const InitiatorCSPInfo& initiator_csp_info,
     base::TimeTicks input_start)
     : url(url),
       referrer(referrer),
@@ -59,11 +69,9 @@
       method(method),
       post_data(post_data),
       source_location(source_location),
-      should_check_main_world_csp(should_check_main_world_csp),
       started_from_context_menu(started_from_context_menu),
       has_user_gesture(has_user_gesture),
-      initiator_csp(initiator_csp),
-      initiator_self_source(initiator_self_source),
+      initiator_csp_info(initiator_csp_info),
       input_start(input_start) {
   // |method != "POST"| should imply absence of |post_data|.
   if (method != "POST" && post_data) {
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h
index f3641715..08655e4 100644
--- a/content/common/navigation_params.h
+++ b/content/common/navigation_params.h
@@ -57,6 +57,28 @@
 
 // Provided by the browser or the renderer -------------------------------------
 
+// Represents the Content Security Policy of the initator of the navigation.
+struct CONTENT_EXPORT InitiatorCSPInfo {
+  InitiatorCSPInfo();
+  InitiatorCSPInfo(CSPDisposition should_check_main_world_csp,
+                   const std::vector<ContentSecurityPolicy>& initiator_csp,
+                   const base::Optional<CSPSource>& initiator_self_source);
+  InitiatorCSPInfo(const InitiatorCSPInfo& other);
+  ~InitiatorCSPInfo();
+
+  // Whether or not the CSP of the main world should apply. When the navigation
+  // is initiated from a content script in an isolated world, the CSP defined
+  // in the main world should not apply.
+  // TODO(arthursonzogni): Instead of this boolean, the origin of the isolated
+  // world which has initiated the navigation should be passed.
+  // See https://crbug.com/702540
+  CSPDisposition should_check_main_world_csp = CSPDisposition::CHECK;
+
+  // The relevant CSP policies and the initiator 'self' source to be used.
+  std::vector<ContentSecurityPolicy> initiator_csp;
+  base::Optional<CSPSource> initiator_self_source;
+};
+
 // Used by all navigation IPCs.
 struct CONTENT_EXPORT CommonNavigationParams {
   CommonNavigationParams();
@@ -74,11 +96,9 @@
       std::string method,
       const scoped_refptr<network::ResourceRequestBody>& post_data,
       base::Optional<SourceLocation> source_location,
-      CSPDisposition should_check_main_world_csp,
       bool started_from_context_menu,
       bool has_user_gesture,
-      const std::vector<ContentSecurityPolicy>& initiator_csp,
-      const base::Optional<CSPSource>& initiator_self_source,
+      const InitiatorCSPInfo& initiator_csp_info,
       base::TimeTicks input_start = base::TimeTicks());
   CommonNavigationParams(const CommonNavigationParams& other);
   ~CommonNavigationParams();
@@ -141,14 +161,6 @@
   // not be set.
   base::Optional<SourceLocation> source_location;
 
-  // Whether or not the CSP of the main world should apply. When the navigation
-  // is initiated from a content script in an isolated world, the CSP defined
-  // in the main world should not apply.
-  // TODO(arthursonzogni): Instead of this boolean, the origin of the isolated
-  // world which has initiated the navigation should be passed.
-  // See https://crbug.com/702540
-  CSPDisposition should_check_main_world_csp = CSPDisposition::CHECK;
-
   // Whether or not this navigation was started from a context menu.
   bool started_from_context_menu = false;
 
@@ -156,8 +168,7 @@
   bool has_user_gesture = false;
 
   // We require a copy of the relevant CSP to perform navigation checks.
-  std::vector<ContentSecurityPolicy> initiator_csp;
-  base::Optional<CSPSource> initiator_self_source;
+  InitiatorCSPInfo initiator_csp_info;
 
   // The current origin policy for this request's origin.
   // (Empty if none applies.)
diff --git a/content/common/service_worker/service_worker_types.cc b/content/common/service_worker/service_worker_types.cc
index afb0f086..d69f31b8 100644
--- a/content/common/service_worker/service_worker_types.cc
+++ b/content/common/service_worker/service_worker_types.cc
@@ -5,7 +5,6 @@
 #include "content/common/service_worker/service_worker_types.h"
 
 #include "content/common/service_worker/service_worker_types.pb.h"
-#include "net/base/load_flags.h"
 #include "storage/common/blob_storage/blob_handle.h"
 
 namespace content {
@@ -128,33 +127,4 @@
   return request;
 }
 
-// static
-blink::mojom::FetchCacheMode
-ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(int load_flags) {
-  if (load_flags & net::LOAD_DISABLE_CACHE)
-    return blink::mojom::FetchCacheMode::kNoStore;
-
-  if (load_flags & net::LOAD_VALIDATE_CACHE)
-    return blink::mojom::FetchCacheMode::kValidateCache;
-
-  if (load_flags & net::LOAD_BYPASS_CACHE) {
-    if (load_flags & net::LOAD_ONLY_FROM_CACHE)
-      return blink::mojom::FetchCacheMode::kUnspecifiedForceCacheMiss;
-    return blink::mojom::FetchCacheMode::kBypassCache;
-  }
-
-  if (load_flags & net::LOAD_SKIP_CACHE_VALIDATION) {
-    if (load_flags & net::LOAD_ONLY_FROM_CACHE)
-      return blink::mojom::FetchCacheMode::kOnlyIfCached;
-    return blink::mojom::FetchCacheMode::kForceCache;
-  }
-
-  if (load_flags & net::LOAD_ONLY_FROM_CACHE) {
-    DCHECK(!(load_flags & net::LOAD_SKIP_CACHE_VALIDATION));
-    DCHECK(!(load_flags & net::LOAD_BYPASS_CACHE));
-    return blink::mojom::FetchCacheMode::kUnspecifiedOnlyIfCachedStrict;
-  }
-  return blink::mojom::FetchCacheMode::kDefault;
-}
-
 }  // namespace content
diff --git a/content/common/service_worker/service_worker_types.h b/content/common/service_worker/service_worker_types.h
index c9c1022..7754680 100644
--- a/content/common/service_worker/service_worker_types.h
+++ b/content/common/service_worker/service_worker_types.h
@@ -16,7 +16,6 @@
 #include "base/time/time.h"
 #include "content/common/content_export.h"
 #include "content/public/common/referrer.h"
-#include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/network/public/mojom/request_context_frame_type.mojom.h"
 #include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h"
@@ -91,7 +90,6 @@
   size_t EstimatedStructSize();
   std::string Serialize() const;
 
-  static blink::mojom::FetchCacheMode GetCacheModeFromLoadFlags(int load_flags);
   static ServiceWorkerFetchRequest ParseFromString(
       const std::string& serialized);
 
diff --git a/content/common/service_worker/service_worker_types_unittest.cc b/content/common/service_worker/service_worker_types_unittest.cc
index 2b74de97..8a1fe70 100644
--- a/content/common/service_worker/service_worker_types_unittest.cc
+++ b/content/common/service_worker/service_worker_types_unittest.cc
@@ -2,48 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/common/service_worker/service_worker_types.h"
 #include "base/guid.h"
+#include "content/common/service_worker/service_worker_utils.h"
 #include "mojo/public/cpp/base/time_mojom_traits.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
 #include "url/mojom/url_gurl_mojom_traits.h"
 
-#include "net/base/load_flags.h"
-
 namespace content {
 
 namespace {
 
-using blink::mojom::FetchCacheMode;
-
-TEST(ServiceWorkerFetchRequestTest, CacheModeTest) {
-  EXPECT_EQ(FetchCacheMode::kDefault,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(0));
-  EXPECT_EQ(FetchCacheMode::kNoStore,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(
-                net::LOAD_DISABLE_CACHE));
-  EXPECT_EQ(FetchCacheMode::kValidateCache,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(
-                net::LOAD_VALIDATE_CACHE));
-  EXPECT_EQ(FetchCacheMode::kBypassCache,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(
-                net::LOAD_BYPASS_CACHE));
-  EXPECT_EQ(FetchCacheMode::kForceCache,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(
-                net::LOAD_SKIP_CACHE_VALIDATION));
-  EXPECT_EQ(FetchCacheMode::kOnlyIfCached,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(
-                net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION));
-  EXPECT_EQ(FetchCacheMode::kUnspecifiedOnlyIfCachedStrict,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(
-                net::LOAD_ONLY_FROM_CACHE));
-  EXPECT_EQ(FetchCacheMode::kUnspecifiedForceCacheMiss,
-            ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(
-                net::LOAD_ONLY_FROM_CACHE | net::LOAD_BYPASS_CACHE));
-}
-
 TEST(ServiceWorkerRequestTest, SerialiazeDeserializeRoundTrip) {
   ServiceWorkerFetchRequest request(
       GURL("foo.com"), "GET", {{"User-Agent", "Chrome"}},
diff --git a/content/common/service_worker/service_worker_utils.cc b/content/common/service_worker/service_worker_utils.cc
index 191ec845..44d34b8 100644
--- a/content/common/service_worker/service_worker_utils.cc
+++ b/content/common/service_worker/service_worker_utils.cc
@@ -13,6 +13,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/origin_util.h"
+#include "net/base/load_flags.h"
 #include "net/http/http_byte_range.h"
 #include "net/http/http_util.h"
 #include "services/network/public/cpp/features.h"
@@ -181,6 +182,35 @@
   return false;
 }
 
+// static
+blink::mojom::FetchCacheMode ServiceWorkerUtils::GetCacheModeFromLoadFlags(
+    int load_flags) {
+  if (load_flags & net::LOAD_DISABLE_CACHE)
+    return blink::mojom::FetchCacheMode::kNoStore;
+
+  if (load_flags & net::LOAD_VALIDATE_CACHE)
+    return blink::mojom::FetchCacheMode::kValidateCache;
+
+  if (load_flags & net::LOAD_BYPASS_CACHE) {
+    if (load_flags & net::LOAD_ONLY_FROM_CACHE)
+      return blink::mojom::FetchCacheMode::kUnspecifiedForceCacheMiss;
+    return blink::mojom::FetchCacheMode::kBypassCache;
+  }
+
+  if (load_flags & net::LOAD_SKIP_CACHE_VALIDATION) {
+    if (load_flags & net::LOAD_ONLY_FROM_CACHE)
+      return blink::mojom::FetchCacheMode::kOnlyIfCached;
+    return blink::mojom::FetchCacheMode::kForceCache;
+  }
+
+  if (load_flags & net::LOAD_ONLY_FROM_CACHE) {
+    DCHECK(!(load_flags & net::LOAD_SKIP_CACHE_VALIDATION));
+    DCHECK(!(load_flags & net::LOAD_BYPASS_CACHE));
+    return blink::mojom::FetchCacheMode::kUnspecifiedOnlyIfCachedStrict;
+  }
+  return blink::mojom::FetchCacheMode::kDefault;
+}
+
 bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
   if (!ServiceWorkerUtils::ScopeMatches(scope, url_))
     return false;
diff --git a/content/common/service_worker/service_worker_utils.h b/content/common/service_worker/service_worker_utils.h
index f0f25a65..2ba85d2 100644
--- a/content/common/service_worker/service_worker_utils.h
+++ b/content/common/service_worker/service_worker_utils.h
@@ -75,6 +75,11 @@
       bool is_main_script,
       blink::mojom::ServiceWorkerUpdateViaCache cache_mode);
 
+  // Converts an enum defined in net/base/load_flags.h to
+  // blink::mojom::FetchCacheMode.
+  CONTENT_EXPORT static blink::mojom::FetchCacheMode GetCacheModeFromLoadFlags(
+      int load_flags);
+
  private:
   static bool IsPathRestrictionSatisfiedInternal(
       const GURL& scope,
diff --git a/content/common/service_worker/service_worker_utils_unittest.cc b/content/common/service_worker/service_worker_utils_unittest.cc
index f75f04c..f19e682 100644
--- a/content/common/service_worker/service_worker_utils_unittest.cc
+++ b/content/common/service_worker/service_worker_utils_unittest.cc
@@ -2,11 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/command_line.h"
 #include "content/common/service_worker/service_worker_utils.h"
+
+#include "base/command_line.h"
 #include "content/public/common/content_switches.h"
+#include "net/base/load_flags.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using blink::mojom::FetchCacheMode;
+
 namespace content {
 
 namespace {
@@ -440,4 +444,30 @@
       filesystem_same_origin));
 }
 
+TEST(ServiceWorkerFetchRequestTest, CacheModeTest) {
+  EXPECT_EQ(FetchCacheMode::kDefault,
+            ServiceWorkerUtils::GetCacheModeFromLoadFlags(0));
+  EXPECT_EQ(
+      FetchCacheMode::kNoStore,
+      ServiceWorkerUtils::GetCacheModeFromLoadFlags(net::LOAD_DISABLE_CACHE));
+  EXPECT_EQ(
+      FetchCacheMode::kValidateCache,
+      ServiceWorkerUtils::GetCacheModeFromLoadFlags(net::LOAD_VALIDATE_CACHE));
+  EXPECT_EQ(
+      FetchCacheMode::kBypassCache,
+      ServiceWorkerUtils::GetCacheModeFromLoadFlags(net::LOAD_BYPASS_CACHE));
+  EXPECT_EQ(FetchCacheMode::kForceCache,
+            ServiceWorkerUtils::GetCacheModeFromLoadFlags(
+                net::LOAD_SKIP_CACHE_VALIDATION));
+  EXPECT_EQ(FetchCacheMode::kOnlyIfCached,
+            ServiceWorkerUtils::GetCacheModeFromLoadFlags(
+                net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION));
+  EXPECT_EQ(
+      FetchCacheMode::kUnspecifiedOnlyIfCachedStrict,
+      ServiceWorkerUtils::GetCacheModeFromLoadFlags(net::LOAD_ONLY_FROM_CACHE));
+  EXPECT_EQ(FetchCacheMode::kUnspecifiedForceCacheMiss,
+            ServiceWorkerUtils::GetCacheModeFromLoadFlags(
+                net::LOAD_ONLY_FROM_CACHE | net::LOAD_BYPASS_CACHE));
+}
+
 }  // namespace content
diff --git a/content/common/throttling_url_loader.cc b/content/common/throttling_url_loader.cc
index fd72391e..d4840a7 100644
--- a/content/common/throttling_url_loader.cc
+++ b/content/common/throttling_url_loader.cc
@@ -6,6 +6,7 @@
 
 #include "base/debug/alias.h"
 #include "base/single_thread_task_runner.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/http/http_status_code.h"
@@ -190,6 +191,7 @@
 
 void ThrottlingURLLoader::FollowRedirect(
     const base::Optional<net::HttpRequestHeaders>& modified_headers) {
+  debug_log_.emplace_back("FollowRedirect");
   const base::Optional<net::HttpRequestHeaders>* modified_headers_to_send =
       &modified_headers;
   if (modified_request_headers_) {
@@ -218,6 +220,7 @@
 }
 
 void ThrottlingURLLoader::FollowRedirectForcingRestart() {
+  debug_log_.emplace_back("FollowRedirectForcingRestart");
   url_loader_.reset();
   client_binding_.Close();
 
@@ -238,6 +241,7 @@
 void ThrottlingURLLoader::RestartWithFactory(
     scoped_refptr<network::SharedURLLoaderFactory> factory,
     uint32_t url_loader_options) {
+  debug_log_.emplace_back("RestartWithFactory");
   // TODO(crbug.com/882661): Remove these aliases and turn CHECKs to DCHECKs
   // when the linked bug is fixed.
   DeferredStage deferred_stage = deferred_stage_;
@@ -280,6 +284,7 @@
       client_binding_(this),
       traffic_annotation_(traffic_annotation),
       weak_factory_(this) {
+  debug_log_.emplace_back("ctor");
   throttles_.reserve(throttles.size());
   for (auto& throttle : throttles)
     throttles_.emplace_back(this, std::move(throttle));
@@ -292,6 +297,7 @@
     uint32_t options,
     network::ResourceRequest* url_request,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+  debug_log_.emplace_back("Start");
   DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
   DCHECK(!loader_completed_);
 
@@ -315,8 +321,10 @@
         // URL.
         url_request->url = original_url;
       }
-      if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
+      if (!HandleThrottleResult(throttle, throttle_deferred, &deferred)) {
+        debug_log_.emplace_back("Start::Return");
         return;
+      }
     }
 
     // If a throttle had changed the URL, set it in the ResourceRequest struct
@@ -328,14 +336,17 @@
   start_info_ =
       std::make_unique<StartInfo>(factory, routing_id, request_id, options,
                                   url_request, std::move(task_runner));
-  if (deferred)
+  if (deferred) {
+    debug_log_.emplace_back("Start::Deferred");
     deferred_stage_ = DEFERRED_START;
-  else
+  } else {
     StartNow();
+  }
 }
 
 void ThrottlingURLLoader::StartNow() {
   DCHECK(start_info_);
+  debug_log_.emplace_back("StartNow");
   if (!throttle_redirect_url_.is_empty()) {
     net::RedirectInfo redirect_info;
     redirect_info.status_code = net::HTTP_TEMPORARY_REDIRECT;
@@ -353,6 +364,7 @@
             header_string.c_str(), header_string.length()));
     response_head.encoded_data_length = header_string.size();
     OnReceiveRedirect(redirect_info, response_head);
+    debug_log_.emplace_back("StartNow::Redirect");
     return;
   }
 
@@ -405,6 +417,7 @@
 
 void ThrottlingURLLoader::OnReceiveResponse(
     const network::ResourceResponseHead& response_head) {
+  debug_log_.emplace_back("OnReceiveResponse");
   DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
   DCHECK(!loader_completed_);
   DCHECK(deferring_throttles_.empty());
@@ -417,25 +430,30 @@
       bool throttle_deferred = false;
       throttle->WillProcessResponse(response_url_, &response_head_copy,
                                     &throttle_deferred);
-      if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
+      if (!HandleThrottleResult(throttle, throttle_deferred, &deferred)) {
+        debug_log_.emplace_back("OnReceiveResponse::Return");
         return;
+      }
     }
 
     if (deferred) {
       deferred_stage_ = DEFERRED_RESPONSE;
       response_info_ = std::make_unique<ResponseInfo>(response_head_copy);
       client_binding_.PauseIncomingMethodCallProcessing();
+      debug_log_.emplace_back("OnReceiveResponse::Deferred");
       return;
     }
   }
 
   sent_on_receive_response_ = true;
+  debug_log_.emplace_back("OnReceiveResponse::Sent");
   forwarding_client_->OnReceiveResponse(response_head_copy);
 }
 
 void ThrottlingURLLoader::OnReceiveRedirect(
     const net::RedirectInfo& redirect_info,
     const network::ResourceResponseHead& response_head) {
+  debug_log_.emplace_back("OnReceiveRedirect");
   DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
   DCHECK(!loader_completed_);
   DCHECK(deferring_throttles_.empty());
@@ -453,8 +471,10 @@
                                     &modified_headers);
       if (!weak_ptr)
         return;
-      if (!HandleThrottleResult(throttle, throttle_deferred, &deferred))
+      if (!HandleThrottleResult(throttle, throttle_deferred, &deferred)) {
+        debug_log_.emplace_back("OnReceiveRedirect::Return");
         return;
+      }
 
       if (!to_be_removed_headers.empty()) {
         if (to_be_removed_request_headers_) {
@@ -480,6 +500,7 @@
       redirect_info_ =
           std::make_unique<RedirectInfo>(redirect_info, response_head);
       client_binding_.PauseIncomingMethodCallProcessing();
+      debug_log_.emplace_back("OnReceiveRedirect::Deferred");
       return;
     }
   }
@@ -497,6 +518,7 @@
   // redirect or if it will be cancelled. FollowRedirect would be a more
   // suitable place to set this URL but there we do not have the data.
   response_url_ = redirect_info.new_url;
+  debug_log_.emplace_back("OnReceiveRedirect::Sent");
   forwarding_client_->OnReceiveRedirect(redirect_info, response_head);
 }
 
@@ -528,23 +550,22 @@
 
 void ThrottlingURLLoader::OnStartLoadingResponseBody(
     mojo::ScopedDataPipeConsumerHandle body) {
-  // TODO(crbug.com/882661): Remove these aliases and turn CHECKs to DCHECKs
-  // when the linked bug is fixed.
-  DeferredStage deferred_stage = deferred_stage_;
-  base::debug::Alias(&deferred_stage);
-  bool loader_completed = loader_completed_;
-  base::debug::Alias(&loader_completed);
-  bool sent_on_receive_response = sent_on_receive_response_;
-  base::debug::Alias(&sent_on_receive_response);
+  debug_log_.emplace_back("OnStartLoadingResponseBody");
 
-  CHECK_EQ(DEFERRED_NONE, deferred_stage_);
-  CHECK(!loader_completed_);
-  CHECK(sent_on_receive_response_);
+  DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
+  DCHECK(!loader_completed_);
+  DCHECK(sent_on_receive_response_);
+
+  // TODO(crbug.com/882661): Remove when the linked bug is fixed.
+  if (!sent_on_receive_response_)
+    Crash();
+
   forwarding_client_->OnStartLoadingResponseBody(std::move(body));
 }
 
 void ThrottlingURLLoader::OnComplete(
     const network::URLLoaderCompletionStatus& status) {
+  debug_log_.emplace_back("OnComplete::Sent");
   DCHECK_EQ(DEFERRED_NONE, deferred_stage_);
   DCHECK(!loader_completed_);
 
@@ -563,6 +584,7 @@
 
 void ThrottlingURLLoader::CancelWithError(int error_code,
                                           base::StringPiece custom_reason) {
+  debug_log_.emplace_back("CancelWithError");
   if (loader_completed_)
     return;
 
@@ -576,8 +598,11 @@
 }
 
 void ThrottlingURLLoader::Resume() {
-  if (loader_completed_ || deferred_stage_ == DEFERRED_NONE)
+  debug_log_.emplace_back("Resume::" + base::NumberToString(deferred_stage_));
+  if (loader_completed_ || deferred_stage_ == DEFERRED_NONE) {
+    debug_log_.emplace_back("Resume::Return");
     return;
+  }
 
   auto prev_deferred_stage = deferred_stage_;
   deferred_stage_ = DEFERRED_NONE;
@@ -672,6 +697,12 @@
   loader_completed_ = true;
 }
 
+void ThrottlingURLLoader::Crash() {
+  std::string log = base::JoinString(debug_log_, " ");
+  DEBUG_ALIAS_FOR_CSTR(log_buf, log.c_str(), 2048);
+  CHECK(false);
+}
+
 ThrottlingURLLoader::ThrottleEntry::ThrottleEntry(
     ThrottlingURLLoader* loader,
     std::unique_ptr<URLLoaderThrottle> the_throttle)
diff --git a/content/common/throttling_url_loader.h b/content/common/throttling_url_loader.h
index 1d49bb6..65cd68f 100644
--- a/content/common/throttling_url_loader.h
+++ b/content/common/throttling_url_loader.h
@@ -143,6 +143,9 @@
   // Disconnects the client connection and releases the URLLoader.
   void DisconnectClient(base::StringPiece custom_description);
 
+  // TODO(crbug.com/882661): Remove when the linked bug is fixed.
+  void Crash();
+
   enum DeferredStage {
     DEFERRED_NONE,
     DEFERRED_START,
@@ -246,8 +249,9 @@
 
   bool response_intercepted_ = false;
 
-  // TODO(crbug.com/882661): Remove this when the linked bug is fixed.
+  // TODO(crbug.com/882661): Remove these when the linked bug is fixed.
   bool sent_on_receive_response_ = false;
+  std::vector<std::string> debug_log_;
 
   base::Optional<std::vector<std::string>> to_be_removed_request_headers_;
   base::Optional<net::HttpRequestHeaders> modified_request_headers_;
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index 5b2f498..2fd83239 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -112,6 +112,7 @@
           "device:mtp",
           "device:nfc",
           "device:serial",
+          "device:usb",
           "device:vibration",
           "device:wake_lock"
         ],
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc
index 5872f8bb..9fc6892 100644
--- a/content/public/test/navigation_simulator.cc
+++ b/content/public/test/navigation_simulator.cc
@@ -967,12 +967,12 @@
     render_frame_host_->frame_host_binding_for_testing()
         .impl()
         ->BeginNavigation(common_params, std::move(begin_params), nullptr,
-                          navigation_client_ptr.PassInterface());
+                          navigation_client_ptr.PassInterface(), nullptr);
   } else {
     render_frame_host_->frame_host_binding_for_testing()
         .impl()
         ->BeginNavigation(common_params, std::move(begin_params), nullptr,
-                          nullptr);
+                          nullptr, nullptr);
   }
 
   NavigationRequest* request =
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index e06bc5c..0a22468f 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -567,10 +567,8 @@
       url, Referrer(), ui::PAGE_TRANSITION_LINK, FrameMsg_Navigate_Type::RELOAD,
       true, false, GURL(), GURL(), PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(),
       "GET", nullptr, base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
       false /* started_from_context_menu */, false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      InitiatorCSPInfo());
   RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_);
   TestRenderFrame* frame =
       static_cast<TestRenderFrame*>(impl->GetMainRenderFrame());
@@ -711,11 +709,8 @@
       url, Referrer(), ui::PAGE_TRANSITION_FORWARD_BACK,
       FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT, true, false, GURL(),
       GURL(), PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(), "GET", nullptr,
-      base::Optional<SourceLocation>(),
-      CSPDisposition::CHECK /* should_check_main_world_csp */,
-      false /* started_from_context_menu */, false /* has_user_gesture */,
-      std::vector<ContentSecurityPolicy>() /* initiator_csp */,
-      CSPSource() /* initiator_self_source */);
+      base::Optional<SourceLocation>(), false /* started_from_context_menu */,
+      false /* has_user_gesture */, InitiatorCSPInfo());
   RequestNavigationParams request_params;
   request_params.page_state = state;
   request_params.nav_entry_id = pending_offset + 1;
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc
index 8d5a6ab..78ca5e2 100644
--- a/content/renderer/media/stream/webmediaplayer_ms.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -844,21 +844,11 @@
                         context_3d, context_support);
 }
 
-bool WebMediaPlayerMS::DidGetOpaqueResponseFromServiceWorker() const {
+bool WebMediaPlayerMS::WouldTaintOrigin() const {
   DCHECK(thread_checker_.CalledOnValidThread());
   return false;
 }
 
-bool WebMediaPlayerMS::HasSingleSecurityOrigin() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return true;
-}
-
-bool WebMediaPlayerMS::DidPassCORSAccessCheck() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return true;
-}
-
 double WebMediaPlayerMS::MediaTimeForTimeValue(double timeValue) const {
   return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
 }
diff --git a/content/renderer/media/stream/webmediaplayer_ms.h b/content/renderer/media/stream/webmediaplayer_ms.h
index 1f3ec20..8c35955 100644
--- a/content/renderer/media/stream/webmediaplayer_ms.h
+++ b/content/renderer/media/stream/webmediaplayer_ms.h
@@ -163,9 +163,7 @@
   blink::WebString GetErrorMessage() const override;
   bool DidLoadingProgress() override;
 
-  bool DidGetOpaqueResponseFromServiceWorker() const override;
-  bool HasSingleSecurityOrigin() const override;
-  bool DidPassCORSAccessCheck() const override;
+  bool WouldTaintOrigin() const override;
 
   double MediaTimeForTimeValue(double timeValue) const override;
 
diff --git a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
index 6fc9103..d26bc814 100644
--- a/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
+++ b/content/renderer/media_capture_from_element/html_video_element_capturer_source_unittest.cc
@@ -76,9 +76,7 @@
   }
 
   bool DidLoadingProgress() override { return true; }
-  bool DidGetOpaqueResponseFromServiceWorker() const override { return false; }
-  bool HasSingleSecurityOrigin() const override { return true; }
-  bool DidPassCORSAccessCheck() const override { return true; }
+  bool WouldTaintOrigin() const override { return false; }
   double MediaTimeForTimeValue(double timeValue) const override { return 0.0; }
   unsigned DecodedFrameCount() const override { return 0; }
   unsigned DroppedFrameCount() const override { return 0; }
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 1ed2844..fa9f391 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -194,9 +194,11 @@
 
 namespace {
 
+#ifndef STATIC_ASSERT_ENUM
 #define STATIC_ASSERT_ENUM(a, b)                            \
   static_assert(static_cast<int>(a) == static_cast<int>(b), \
                 "mismatching enums: " #a)
+#endif
 
 // Check PP_TextInput_Type and ui::TextInputType are kept in sync.
 STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_NONE, PP_TEXTINPUT_TYPE_NONE);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 20539cd..c9b6d0f 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -537,13 +537,14 @@
       static_cast<PreviewsState>(info.url_request.GetPreviewsState()),
       base::TimeTicks::Now(), info.url_request.HttpMethod().Latin1(),
       GetRequestBodyForWebURLRequest(info.url_request), source_location,
-      should_check_main_world_csp, false /* started_from_context_menu */,
-      info.url_request.HasUserGesture(),
-      BuildContentSecurityPolicyList(info.url_request.GetNavigationCSP()),
-      info.url_request.GetNavigationCSP().self_source.has_value()
-          ? base::Optional<CSPSource>(BuildCSPSource(
-                info.url_request.GetNavigationCSP().self_source.value()))
-          : base::nullopt,
+      false /* started_from_context_menu */, info.url_request.HasUserGesture(),
+      InitiatorCSPInfo(
+          should_check_main_world_csp,
+          BuildContentSecurityPolicyList(info.url_request.GetInitiatorCSP()),
+          info.url_request.GetInitiatorCSP().self_source.has_value()
+              ? base::Optional<CSPSource>(BuildCSPSource(
+                    info.url_request.GetInitiatorCSP().self_source.value()))
+              : base::nullopt),
       input_start);
 }
 
@@ -4195,7 +4196,8 @@
 
 void RenderFrameImpl::DidStartProvisionalLoad(
     blink::WebDocumentLoader* document_loader,
-    blink::WebURLRequest& request) {
+    blink::WebURLRequest& request,
+    mojo::ScopedMessagePipeHandle navigation_initiator_handle) {
   // In fast/loader/stop-provisional-loads.html, we abort the load before this
   // callback is invoked.
   if (!document_loader)
@@ -4226,7 +4228,7 @@
     info.input_start = pending_navigation_info_->input_start;
 
     pending_navigation_info_.reset(nullptr);
-    BeginNavigation(info);
+    BeginNavigation(info, std::move(navigation_initiator_handle));
   }
 
   NavigationState* navigation_state =
@@ -6306,10 +6308,12 @@
       main_thread_use_time));
 }
 
+#ifndef STATIC_ASSERT_ENUM
 #define STATIC_ASSERT_ENUM(a, b)                            \
   static_assert(static_cast<int>(a) == static_cast<int>(b), \
                 "mismatching enums: " #a)
 #undef STATIC_ASSERT_ENUM
+#endif
 
 void RenderFrameImpl::OnEnableViewSourceMode() {
   DCHECK(frame_);
@@ -6721,7 +6725,9 @@
 }
 }  // namespace
 
-void RenderFrameImpl::BeginNavigation(const NavigationPolicyInfo& info) {
+void RenderFrameImpl::BeginNavigation(
+    const NavigationPolicyInfo& info,
+    mojo::ScopedMessagePipeHandle navigation_initiator_handle) {
   browser_side_navigation_pending_ = true;
   browser_side_navigation_pending_url_ = info.url_request.Url();
 
@@ -6820,10 +6826,15 @@
     BindNavigationClient(mojo::MakeRequest(&navigation_client_info));
     navigation_state->set_navigation_client(std::move(navigation_client_impl_));
   }
+
+  blink::mojom::NavigationInitiatorPtr initiator_ptr(
+      blink::mojom::NavigationInitiatorPtrInfo(
+          std::move(navigation_initiator_handle), 0));
+
   GetFrameHost()->BeginNavigation(
       MakeCommonNavigationParams(info, load_flags, info.input_start),
       std::move(begin_navigation_params), std::move(blob_url_token),
-      std::move(navigation_client_info));
+      std::move(navigation_client_info), std::move(initiator_ptr));
 }
 
 void RenderFrameImpl::LoadDataURL(
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index e993cf33..b4fe35c6 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -649,8 +649,10 @@
   void WillSendSubmitEvent(const blink::WebFormElement& form) override;
   void DidCreateDocumentLoader(
       blink::WebDocumentLoader* document_loader) override;
-  void DidStartProvisionalLoad(blink::WebDocumentLoader* document_loader,
-                               blink::WebURLRequest& request) override;
+  void DidStartProvisionalLoad(
+      blink::WebDocumentLoader* document_loader,
+      blink::WebURLRequest& request,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) override;
   void DidFailProvisionalLoad(const blink::WebURLError& error,
                               blink::WebHistoryCommitType commit_type) override;
   void DidCommitProvisionalLoad(
@@ -1181,7 +1183,9 @@
       const RequestNavigationParams& request_params);
 
   // Sends a FrameHostMsg_BeginNavigation to the browser
-  void BeginNavigation(const NavigationPolicyInfo& info);
+  void BeginNavigation(
+      const NavigationPolicyInfo& info,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle);
 
   // Loads a data url.
   void LoadDataURL(
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index eb47dcd..5a3d0d9 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -298,7 +298,7 @@
       static_cast<ResourceType>(request.resource_type)));
   web_request->SetCredentialsMode(request.fetch_credentials_mode);
   web_request->SetCacheMode(
-      ServiceWorkerFetchRequest::GetCacheModeFromLoadFlags(request.load_flags));
+      ServiceWorkerUtils::GetCacheModeFromLoadFlags(request.load_flags));
   web_request->SetRedirectMode(request.fetch_redirect_mode);
   web_request->SetRequestContext(
       GetBlinkRequestContext(static_cast<blink::mojom::RequestContextType>(
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 6be7d66..4be7db30 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -85,7 +85,8 @@
   void BeginNavigation(const CommonNavigationParams& common_params,
                        mojom::BeginNavigationParamsPtr begin_params,
                        blink::mojom::BlobURLTokenPtr blob_url_token,
-                       mojom::NavigationClientAssociatedPtrInfo) override {}
+                       mojom::NavigationClientAssociatedPtrInfo,
+                       blink::mojom::NavigationInitiatorPtr) override {}
 
   void SubresourceResponseStarted(const GURL& url,
                                   net::CertStatus cert_status) override {}
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 6c427b77..d309cf4 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -455,9 +455,10 @@
   if (IsPerNavigationMojoInterfaceEnabled()) {
     GetRemoteAssociatedInterfaces()->GetInterface(&navigation_client_ptr);
     BeginNavigation(common_params, std::move(begin_params), nullptr,
-                    navigation_client_ptr.PassInterface());
+                    navigation_client_ptr.PassInterface(), nullptr);
   } else {
-    BeginNavigation(common_params, std::move(begin_params), nullptr, nullptr);
+    BeginNavigation(common_params, std::move(begin_params), nullptr, nullptr,
+                    nullptr);
   }
 }
 
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 28d6cc8..7edaa88 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -172,7 +172,7 @@
       "test/test_device_client.h",
       "usb/mojo/device_impl_unittest.cc",
       "usb/mojo/device_manager_impl_unittest.cc",
-      "usb/public/cpp/filter_utils_unittest.cc",
+      "usb/public/cpp/usb_utils_unittest.cc",
       "usb/usb_descriptors_unittest.cc",
       "usb/usb_device_handle_unittest.cc",
       "usb/usb_service_unittest.cc",
diff --git a/device/usb/mojo/device_impl.cc b/device/usb/mojo/device_impl.cc
index 4c53767..f97bcf0 100644
--- a/device/usb/mojo/device_impl.cc
+++ b/device/usb/mojo/device_impl.cc
@@ -18,6 +18,7 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/stl_util.h"
 #include "device/usb/mojo/type_converters.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/usb_descriptors.h"
 #include "device/usb/usb_device.h"
 
@@ -54,20 +55,6 @@
   std::move(callback).Run(mojo::ConvertTo<mojom::UsbTransferStatus>(status));
 }
 
-std::vector<mojom::UsbIsochronousPacketPtr> BuildIsochronousPacketArray(
-    const std::vector<uint32_t>& packet_lengths,
-    mojom::UsbTransferStatus status) {
-  std::vector<mojom::UsbIsochronousPacketPtr> packets;
-  packets.reserve(packet_lengths.size());
-  for (uint32_t packet_length : packet_lengths) {
-    auto packet = mojom::UsbIsochronousPacket::New();
-    packet->length = packet_length;
-    packet->status = status;
-    packets.push_back(std::move(packet));
-  }
-  return packets;
-}
-
 void OnIsochronousTransferIn(
     mojom::UsbDevice::IsochronousTransferInCallback callback,
     scoped_refptr<base::RefCountedBytes> buffer,
diff --git a/device/usb/mojo/device_manager_impl.cc b/device/usb/mojo/device_manager_impl.cc
index d75bcc8..9a3e29e 100644
--- a/device/usb/mojo/device_manager_impl.cc
+++ b/device/usb/mojo/device_manager_impl.cc
@@ -16,7 +16,7 @@
 #include "device/base/device_client.h"
 #include "device/usb/mojo/device_impl.h"
 #include "device/usb/mojo/type_converters.h"
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/public/mojom/device.mojom.h"
 #include "device/usb/usb_device.h"
 #include "device/usb/usb_service.h"
diff --git a/device/usb/public/cpp/BUILD.gn b/device/usb/public/cpp/BUILD.gn
index f0dd7350..df68a9d 100644
--- a/device/usb/public/cpp/BUILD.gn
+++ b/device/usb/public/cpp/BUILD.gn
@@ -4,8 +4,8 @@
 
 source_set("cpp") {
   sources = [
-    "filter_utils.cc",
-    "filter_utils.h",
+    "usb_utils.cc",
+    "usb_utils.h",
   ]
 
   deps = [
@@ -13,3 +13,25 @@
     "//device/usb/public/mojom",
   ]
 }
+
+static_library("test_support") {
+  testonly = true
+
+  sources = [
+    "fake_usb_device.cc",
+    "fake_usb_device.h",
+    "fake_usb_device_info.cc",
+    "fake_usb_device_info.h",
+    "fake_usb_device_manager.cc",
+    "fake_usb_device_manager.h",
+  ]
+
+  deps = [
+    ":cpp",
+  ]
+
+  public_deps = [
+    "//base",
+    "//device/usb/public/mojom",
+  ]
+}
diff --git a/device/usb/public/cpp/fake_usb_device.cc b/device/usb/public/cpp/fake_usb_device.cc
new file mode 100644
index 0000000..a1a5b95
--- /dev/null
+++ b/device/usb/public/cpp/fake_usb_device.cc
@@ -0,0 +1,133 @@
+// Copyright 2018 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/public/cpp/fake_usb_device.h"
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
+#include "device/usb/public/cpp/usb_utils.h"
+
+namespace device {
+
+// static
+void FakeUsbDevice::Create(scoped_refptr<FakeUsbDeviceInfo> device,
+                           mojom::UsbDeviceRequest request,
+                           mojom::UsbDeviceClientPtr client) {
+  auto* device_object = new FakeUsbDevice(device, std::move(client));
+  device_object->binding_ = mojo::MakeStrongBinding(
+      base::WrapUnique(device_object), std::move(request));
+}
+
+FakeUsbDevice::~FakeUsbDevice() {
+  CloseHandle();
+}
+
+FakeUsbDevice::FakeUsbDevice(scoped_refptr<FakeUsbDeviceInfo> device,
+                             mojom::UsbDeviceClientPtr client)
+    : device_(device), observer_(this), client_(std::move(client)) {
+  DCHECK(device_);
+  observer_.Add(device_.get());
+}
+
+void FakeUsbDevice::CloseHandle() {
+  if (is_opened_ && client_)
+    client_->OnDeviceClosed();
+
+  is_opened_ = false;
+}
+
+// Device implementation:
+void FakeUsbDevice::Open(OpenCallback callback) {
+  is_opened_ = true;
+  if (client_)
+    client_->OnDeviceOpened();
+
+  std::move(callback).Run(mojom::UsbOpenDeviceError::OK);
+}
+
+void FakeUsbDevice::Close(CloseCallback callback) {
+  CloseHandle();
+  std::move(callback).Run();
+}
+void FakeUsbDevice::SetConfiguration(uint8_t value,
+                                     SetConfigurationCallback callback) {
+  std::move(callback).Run(true);
+}
+void FakeUsbDevice::ClaimInterface(uint8_t interface_number,
+                                   ClaimInterfaceCallback callback) {
+  std::move(callback).Run(true);
+}
+void FakeUsbDevice::ReleaseInterface(uint8_t interface_number,
+                                     ReleaseInterfaceCallback callback) {
+  std::move(callback).Run(true);
+}
+void FakeUsbDevice::SetInterfaceAlternateSetting(
+    uint8_t interface_number,
+    uint8_t alternate_setting,
+    SetInterfaceAlternateSettingCallback callback) {
+  std::move(callback).Run(true);
+}
+void FakeUsbDevice::Reset(ResetCallback callback) {
+  std::move(callback).Run(true);
+}
+void FakeUsbDevice::ClearHalt(uint8_t endpoint, ClearHaltCallback callback) {
+  std::move(callback).Run(true);
+}
+void FakeUsbDevice::ControlTransferIn(mojom::UsbControlTransferParamsPtr params,
+                                      uint32_t length,
+                                      uint32_t timeout,
+                                      ControlTransferInCallback callback) {
+  std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED, {});
+}
+void FakeUsbDevice::ControlTransferOut(
+    mojom::UsbControlTransferParamsPtr params,
+    const std::vector<uint8_t>& data,
+    uint32_t timeout,
+    ControlTransferOutCallback callback) {
+  std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED);
+}
+void FakeUsbDevice::GenericTransferIn(uint8_t endpoint_number,
+                                      uint32_t length,
+                                      uint32_t timeout,
+                                      GenericTransferInCallback callback) {
+  std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED, {});
+}
+void FakeUsbDevice::GenericTransferOut(uint8_t endpoint_number,
+                                       const std::vector<uint8_t>& data,
+                                       uint32_t timeout,
+                                       GenericTransferOutCallback callback) {
+  std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED);
+}
+void FakeUsbDevice::IsochronousTransferIn(
+    uint8_t endpoint_number,
+    const std::vector<uint32_t>& packet_lengths,
+    uint32_t timeout,
+    IsochronousTransferInCallback callback) {
+  std::move(callback).Run(
+      {}, BuildIsochronousPacketArray(packet_lengths,
+                                      mojom::UsbTransferStatus::COMPLETED));
+}
+void FakeUsbDevice::IsochronousTransferOut(
+    uint8_t endpoint_number,
+    const std::vector<uint8_t>& data,
+    const std::vector<uint32_t>& packet_lengths,
+    uint32_t timeout,
+    IsochronousTransferOutCallback callback) {
+  std::move(callback).Run(BuildIsochronousPacketArray(
+      packet_lengths, mojom::UsbTransferStatus::COMPLETED));
+}
+
+void FakeUsbDevice::OnDeviceRemoved(scoped_refptr<FakeUsbDeviceInfo> device) {
+  DCHECK_EQ(device_, device);
+  binding_->Close();
+}
+
+}  // namespace device
diff --git a/device/usb/public/cpp/fake_usb_device.h b/device/usb/public/cpp/fake_usb_device.h
new file mode 100644
index 0000000..be85bdb
--- /dev/null
+++ b/device/usb/public/cpp/fake_usb_device.h
@@ -0,0 +1,95 @@
+// Copyright 2018 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_PUBLIC_CPP_FAKE_USB_DEVICE_H_
+#define DEVICE_USB_PUBLIC_CPP_FAKE_USB_DEVICE_H_
+
+#include <stdint.h>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
+#include "device/usb/public/cpp/fake_usb_device_info.h"
+#include "device/usb/public/mojom/device.mojom.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace device {
+
+// This class provides fake implementation for device::mojom::UsbDevice.
+// It should be used together with FakeUsbDeviceManager and FakeUsbDeviceInfo
+// just for testing.
+class FakeUsbDevice : public mojom::UsbDevice,
+                      public FakeUsbDeviceInfo::Observer {
+ public:
+  static void Create(scoped_refptr<FakeUsbDeviceInfo> device,
+                     mojom::UsbDeviceRequest request,
+                     mojom::UsbDeviceClientPtr client);
+  ~FakeUsbDevice() override;
+
+ private:
+  FakeUsbDevice(scoped_refptr<FakeUsbDeviceInfo> device,
+                mojom::UsbDeviceClientPtr client);
+
+  // Device implementation:
+  void Open(OpenCallback callback) override;
+  void Close(CloseCallback callback) override;
+  void SetConfiguration(uint8_t value,
+                        SetConfigurationCallback callback) override;
+  void ClaimInterface(uint8_t interface_number,
+                      ClaimInterfaceCallback callback) override;
+  void ReleaseInterface(uint8_t interface_number,
+                        ReleaseInterfaceCallback callback) override;
+  void SetInterfaceAlternateSetting(
+      uint8_t interface_number,
+      uint8_t alternate_setting,
+      SetInterfaceAlternateSettingCallback callback) override;
+  void Reset(ResetCallback callback) override;
+  void ClearHalt(uint8_t endpoint, ClearHaltCallback callback) override;
+  void ControlTransferIn(mojom::UsbControlTransferParamsPtr params,
+                         uint32_t length,
+                         uint32_t timeout,
+                         ControlTransferInCallback callback) override;
+  void ControlTransferOut(mojom::UsbControlTransferParamsPtr params,
+                          const std::vector<uint8_t>& data,
+                          uint32_t timeout,
+                          ControlTransferOutCallback callback) override;
+  void GenericTransferIn(uint8_t endpoint_number,
+                         uint32_t length,
+                         uint32_t timeout,
+                         GenericTransferInCallback callback) override;
+  void GenericTransferOut(uint8_t endpoint_number,
+                          const std::vector<uint8_t>& data,
+                          uint32_t timeout,
+                          GenericTransferOutCallback callback) override;
+  void IsochronousTransferIn(uint8_t endpoint_number,
+                             const std::vector<uint32_t>& packet_lengths,
+                             uint32_t timeout,
+                             IsochronousTransferInCallback callback) override;
+  void IsochronousTransferOut(uint8_t endpoint_number,
+                              const std::vector<uint8_t>& data,
+                              const std::vector<uint32_t>& packet_lengths,
+                              uint32_t timeout,
+                              IsochronousTransferOutCallback callback) override;
+
+  // FakeUsbDeviceInfo::Observer implementation:
+  void OnDeviceRemoved(scoped_refptr<FakeUsbDeviceInfo> device) override;
+
+  void CloseHandle();
+
+  const scoped_refptr<FakeUsbDeviceInfo> device_;
+
+  ScopedObserver<FakeUsbDeviceInfo, FakeUsbDeviceInfo::Observer> observer_;
+
+  bool is_opened_ = false;
+  mojo::StrongBindingPtr<mojom::UsbDevice> binding_;
+  device::mojom::UsbDeviceClientPtr client_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeUsbDevice);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_USB_PUBLIC_CPP_FAKE_USB_DEVICE_H_
diff --git a/device/usb/public/cpp/fake_usb_device_info.cc b/device/usb/public/cpp/fake_usb_device_info.cc
new file mode 100644
index 0000000..8fad4d7
--- /dev/null
+++ b/device/usb/public/cpp/fake_usb_device_info.cc
@@ -0,0 +1,60 @@
+// Copyright 2018 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/public/cpp/fake_usb_device_info.h"
+
+#include "base/guid.h"
+#include "base/strings/utf_string_conversions.h"
+#include "device/usb/public/cpp/usb_utils.h"
+
+namespace device {
+
+void FakeUsbDeviceInfo::Observer::OnDeviceRemoved(
+    scoped_refptr<FakeUsbDeviceInfo> device) {}
+
+void FakeUsbDeviceInfo::SetDefault() {
+  device_info_.guid = base::GenerateGUID();
+  device_info_.usb_version_major = 0x02;
+  device_info_.usb_version_minor = 0x00;
+  device_info_.usb_version_subminor = 0x00;
+  device_info_.class_code = 0xff;
+  device_info_.subclass_code = 0xff;
+  device_info_.protocol_code = 0xff;
+  device_info_.device_version_major = 0x01;
+  device_info_.device_version_minor = 0x00;
+  device_info_.device_version_subminor = 0x00;
+}
+
+FakeUsbDeviceInfo::FakeUsbDeviceInfo(uint16_t vendor_id, uint16_t product_id)
+    : FakeUsbDeviceInfo(vendor_id, product_id, "", "", "") {}
+
+FakeUsbDeviceInfo::FakeUsbDeviceInfo(uint16_t vendor_id,
+                                     uint16_t product_id,
+                                     const std::string& manufacturer_string,
+                                     const std::string& product_string,
+                                     const std::string& serial_number) {
+  SetDefault();
+  device_info_.vendor_id = vendor_id;
+  device_info_.product_id = product_id;
+  device_info_.manufacturer_name = base::UTF8ToUTF16(manufacturer_string);
+  device_info_.product_name = base::UTF8ToUTF16(product_string),
+  device_info_.serial_number = base::UTF8ToUTF16(serial_number);
+}
+
+FakeUsbDeviceInfo::~FakeUsbDeviceInfo() = default;
+
+void FakeUsbDeviceInfo::AddObserver(Observer* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void FakeUsbDeviceInfo::RemoveObserver(Observer* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
+void FakeUsbDeviceInfo::NotifyDeviceRemoved() {
+  for (auto& observer : observer_list_)
+    observer.OnDeviceRemoved(this);
+}
+
+}  // namespace device
diff --git a/device/usb/public/cpp/fake_usb_device_info.h b/device/usb/public/cpp/fake_usb_device_info.h
new file mode 100644
index 0000000..fe3ec66b
--- /dev/null
+++ b/device/usb/public/cpp/fake_usb_device_info.h
@@ -0,0 +1,56 @@
+// Copyright 2018 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_PUBLIC_CPP_FAKE_USB_DEVICE_INFO_H_
+#define DEVICE_USB_PUBLIC_CPP_FAKE_USB_DEVICE_INFO_H_
+
+#include <stdint.h>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "device/usb/public/mojom/device.mojom.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+namespace device {
+
+// This class acts like device::UsbDevice and provides mojom::UsbDeviceInfo.
+// It should be used together with FakeUsbDeviceManager just for testing.
+class FakeUsbDeviceInfo : public base::RefCounted<FakeUsbDeviceInfo> {
+ public:
+  class Observer : public base::CheckedObserver {
+   public:
+    // This method is called when the FakeUsbDeviceManager that created this
+    // object detects that the device has been disconnected from the host.
+    virtual void OnDeviceRemoved(scoped_refptr<FakeUsbDeviceInfo> device);
+  };
+
+  FakeUsbDeviceInfo(uint16_t vendor_id, uint16_t product_id);
+  FakeUsbDeviceInfo(uint16_t vendor_id,
+                    uint16_t product_id,
+                    const std::string& manufacturer_string,
+                    const std::string& product_string,
+                    const std::string& serial_number);
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+  void NotifyDeviceRemoved();
+
+  std::string guid() { return device_info_.guid; }
+  mojom::UsbDeviceInfoPtr GetDeviceInfo() { return device_info_.Clone(); }
+
+ private:
+  friend class RefCounted<FakeUsbDeviceInfo>;
+  ~FakeUsbDeviceInfo();
+  void SetDefault();
+
+  mojom::UsbDeviceInfo device_info_;
+  base::ObserverList<Observer> observer_list_;
+  DISALLOW_COPY_AND_ASSIGN(FakeUsbDeviceInfo);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_USB_PUBLIC_CPP_FAKE_USB_DEVICE_INFO_H_
diff --git a/device/usb/public/cpp/fake_usb_device_manager.cc b/device/usb/public/cpp/fake_usb_device_manager.cc
new file mode 100644
index 0000000..de2c0617
--- /dev/null
+++ b/device/usb/public/cpp/fake_usb_device_manager.cc
@@ -0,0 +1,99 @@
+// Copyright 2018 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/public/cpp/fake_usb_device_manager.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/stl_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "device/usb/public/cpp/fake_usb_device.h"
+#include "device/usb/public/cpp/usb_utils.h"
+
+namespace device {
+
+FakeUsbDeviceManager::FakeUsbDeviceManager() : weak_factory_(this) {}
+
+FakeUsbDeviceManager::~FakeUsbDeviceManager() {}
+
+// mojom::UsbDeviceManager implementation:
+void FakeUsbDeviceManager::GetDevices(mojom::UsbEnumerationOptionsPtr options,
+                                      GetDevicesCallback callback) {
+  std::vector<mojom::UsbDeviceFilterPtr> filters;
+  if (options)
+    filters.swap(options->filters);
+
+  std::vector<mojom::UsbDeviceInfoPtr> device_infos;
+  for (const auto& it : devices_) {
+    mojom::UsbDeviceInfoPtr device_info = it.second->GetDeviceInfo();
+    if (UsbDeviceFilterMatchesAny(filters, *device_info)) {
+      device_infos.push_back(std::move(device_info));
+    }
+  }
+
+  std::move(callback).Run(std::move(device_infos));
+}
+
+void FakeUsbDeviceManager::GetDevice(const std::string& guid,
+                                     mojom::UsbDeviceRequest device_request,
+                                     mojom::UsbDeviceClientPtr device_client) {
+  auto it = devices_.find(guid);
+  if (it == devices_.end())
+    return;
+
+  FakeUsbDevice::Create(it->second, std::move(device_request),
+                        std::move(device_client));
+}
+
+void FakeUsbDeviceManager::SetClient(
+    mojom::UsbDeviceManagerClientAssociatedPtrInfo client) {
+  DCHECK(client);
+  mojom::UsbDeviceManagerClientAssociatedPtr client_ptr;
+  client_ptr.Bind(std::move(client));
+  clients_.AddPtr(std::move(client_ptr));
+}
+
+void FakeUsbDeviceManager::AddBinding(mojom::UsbDeviceManagerRequest request) {
+  bindings_.AddBinding(this, std::move(request));
+}
+
+mojom::UsbDeviceInfoPtr FakeUsbDeviceManager::AddDevice(
+    scoped_refptr<FakeUsbDeviceInfo> device) {
+  DCHECK(device);
+  DCHECK(!base::ContainsKey(devices_, device->guid()));
+  devices_[device->guid()] = device;
+  auto device_info = device->GetDeviceInfo();
+
+  // Notify all the clients.
+  clients_.ForAllPtrs(
+      [&device_info](device::mojom::UsbDeviceManagerClient* client) {
+        client->OnDeviceAdded(device_info->Clone());
+      });
+  return device_info;
+}
+
+void FakeUsbDeviceManager::RemoveDevice(
+    scoped_refptr<FakeUsbDeviceInfo> device) {
+  DCHECK(device);
+  DCHECK(base::ContainsKey(devices_, device->guid()));
+  auto device_info = device->GetDeviceInfo();
+  devices_.erase(device->guid());
+
+  // Notify all the clients
+  clients_.ForAllPtrs(
+      [&device_info](device::mojom::UsbDeviceManagerClient* client) {
+        client->OnDeviceRemoved(device_info->Clone());
+      });
+
+  device->NotifyDeviceRemoved();
+}
+
+void FakeUsbDeviceManager::RemoveDevice(const std::string& guid) {
+  DCHECK(ContainsKey(devices_, guid));
+  RemoveDevice(devices_[guid]);
+}
+
+}  // namespace device
diff --git a/device/usb/public/cpp/fake_usb_device_manager.h b/device/usb/public/cpp/fake_usb_device_manager.h
new file mode 100644
index 0000000..1473fc0
--- /dev/null
+++ b/device/usb/public/cpp/fake_usb_device_manager.h
@@ -0,0 +1,71 @@
+// Copyright 2018 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_PUBLIC_CPP_FAKE_USB_DEVICE_MANAGER_H_
+#define DEVICE_USB_PUBLIC_CPP_FAKE_USB_DEVICE_MANAGER_H_
+
+#include <string>
+#include <unordered_map>
+#include <utility>
+
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "device/usb/public/cpp/fake_usb_device_info.h"
+#include "device/usb/public/mojom/device.mojom.h"
+#include "device/usb/public/mojom/device_manager.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+
+namespace device {
+
+// This class implements a fake USB device manager which will only be used in
+// tests for device::mojom::UsbDeviceManager's users.
+class FakeUsbDeviceManager : public mojom::UsbDeviceManager {
+ public:
+  FakeUsbDeviceManager();
+  ~FakeUsbDeviceManager() override;
+
+  void AddBinding(mojom::UsbDeviceManagerRequest request);
+
+  // Create a device and add it to added_devices_.
+  template <typename... Args>
+  mojom::UsbDeviceInfoPtr CreateAndAddDevice(Args&&... args) {
+    scoped_refptr<FakeUsbDeviceInfo> device =
+        new FakeUsbDeviceInfo(std::forward<Args>(args)...);
+    return AddDevice(device);
+  }
+
+  mojom::UsbDeviceInfoPtr AddDevice(scoped_refptr<FakeUsbDeviceInfo> device);
+
+  void RemoveDevice(const std::string& guid);
+
+  void RemoveDevice(scoped_refptr<FakeUsbDeviceInfo> device);
+
+  bool IsBound() { return !bindings_.empty(); }
+
+  void CloseAllBindings() { bindings_.CloseAllBindings(); }
+
+ private:
+  // mojom::UsbDeviceManager implementation:
+  void GetDevices(mojom::UsbEnumerationOptionsPtr options,
+                  GetDevicesCallback callback) override;
+  void GetDevice(const std::string& guid,
+                 mojom::UsbDeviceRequest device_request,
+                 mojom::UsbDeviceClientPtr device_client) override;
+  void SetClient(
+      mojom::UsbDeviceManagerClientAssociatedPtrInfo client) override;
+
+  mojo::BindingSet<mojom::UsbDeviceManager> bindings_;
+  mojo::AssociatedInterfacePtrSet<mojom::UsbDeviceManagerClient> clients_;
+
+  std::unordered_map<std::string, scoped_refptr<FakeUsbDeviceInfo>> devices_;
+
+  base::WeakPtrFactory<FakeUsbDeviceManager> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeUsbDeviceManager);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_USB_PUBLIC_CPP_FAKE_USB_DEVICE_MANAGER_H_
diff --git a/device/usb/public/cpp/filter_utils.cc b/device/usb/public/cpp/usb_utils.cc
similarity index 83%
rename from device/usb/public/cpp/filter_utils.cc
rename to device/usb/public/cpp/usb_utils.cc
index fd01788..5b1f1839 100644
--- a/device/usb/public/cpp/filter_utils.cc
+++ b/device/usb/public/cpp/usb_utils.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
+
+#include <utility>
 
 #include "device/usb/usb_device.h"
 
@@ -102,4 +104,18 @@
   return false;
 }
 
+std::vector<mojom::UsbIsochronousPacketPtr> BuildIsochronousPacketArray(
+    const std::vector<uint32_t>& packet_lengths,
+    mojom::UsbTransferStatus status) {
+  std::vector<mojom::UsbIsochronousPacketPtr> packets;
+  packets.reserve(packet_lengths.size());
+  for (uint32_t packet_length : packet_lengths) {
+    auto packet = mojom::UsbIsochronousPacket::New();
+    packet->length = packet_length;
+    packet->status = status;
+    packets.push_back(std::move(packet));
+  }
+  return packets;
+}
+
 }  // namespace device
diff --git a/device/usb/public/cpp/filter_utils.h b/device/usb/public/cpp/usb_utils.h
similarity index 74%
rename from device/usb/public/cpp/filter_utils.h
rename to device/usb/public/cpp/usb_utils.h
index a028049..056fcfd 100644
--- a/device/usb/public/cpp/filter_utils.h
+++ b/device/usb/public/cpp/usb_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef DEVICE_USB_PUBLIC_CPP_FILTER_UTILS_H_
-#define DEVICE_USB_PUBLIC_CPP_FILTER_UTILS_H_
+#ifndef DEVICE_USB_PUBLIC_CPP_USB_UTILS_H_
+#define DEVICE_USB_PUBLIC_CPP_USB_UTILS_H_
 
 #include <vector>
 
@@ -28,6 +28,10 @@
     const std::vector<mojom::UsbDeviceFilterPtr>& filters,
     const mojom::UsbDeviceInfo& device_info);
 
+std::vector<mojom::UsbIsochronousPacketPtr> BuildIsochronousPacketArray(
+    const std::vector<uint32_t>& packet_lengths,
+    mojom::UsbTransferStatus status);
+
 }  // namespace device
 
-#endif  // DEVICE_USB_PUBLIC_CPP_FILTER_UTILS_H_
+#endif  // DEVICE_USB_PUBLIC_CPP_USB_UTILS_H_
diff --git a/device/usb/public/cpp/filter_utils_unittest.cc b/device/usb/public/cpp/usb_utils_unittest.cc
similarity index 85%
rename from device/usb/public/cpp/filter_utils_unittest.cc
rename to device/usb/public/cpp/usb_utils_unittest.cc
index 2cf8f63..426a097 100644
--- a/device/usb/public/cpp/filter_utils_unittest.cc
+++ b/device/usb/public/cpp/usb_utils_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/strings/utf_string_conversions.h"
 #include "device/usb/mock_usb_device.h"
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/usb_descriptors.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -18,7 +18,7 @@
 
 using testing::Return;
 
-class UsbFilterTest : public testing::Test {
+class UsbUtilsTest : public testing::Test {
  public:
   void SetUp() override {
     UsbConfigDescriptor config(1, false, false, 0);
@@ -32,26 +32,26 @@
   scoped_refptr<MockUsbDevice> android_phone_;
 };
 
-TEST_F(UsbFilterTest, MatchAny) {
+TEST_F(UsbUtilsTest, MatchAny) {
   auto filter = mojom::UsbDeviceFilter::New();
   EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchVendorId) {
+TEST_F(UsbUtilsTest, MatchVendorId) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_vendor_id = true;
   filter->vendor_id = 0x18d1;
   EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchVendorIdNegative) {
+TEST_F(UsbUtilsTest, MatchVendorIdNegative) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_vendor_id = true;
   filter->vendor_id = 0x1d6b;
   EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchProductId) {
+TEST_F(UsbUtilsTest, MatchProductId) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_vendor_id = true;
   filter->vendor_id = 0x18d1;
@@ -60,7 +60,7 @@
   EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchProductIdNegative) {
+TEST_F(UsbUtilsTest, MatchProductIdNegative) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_vendor_id = true;
   filter->vendor_id = 0x18d1;
@@ -69,21 +69,21 @@
   EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchInterfaceClass) {
+TEST_F(UsbUtilsTest, MatchInterfaceClass) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_class_code = true;
   filter->class_code = 0xff;
   EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchInterfaceClassNegative) {
+TEST_F(UsbUtilsTest, MatchInterfaceClassNegative) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_class_code = true;
   filter->class_code = 0xe0;
   EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchInterfaceSubclass) {
+TEST_F(UsbUtilsTest, MatchInterfaceSubclass) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_class_code = true;
   filter->class_code = 0xff;
@@ -92,7 +92,7 @@
   EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchInterfaceSubclassNegative) {
+TEST_F(UsbUtilsTest, MatchInterfaceSubclassNegative) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_class_code = true;
   filter->class_code = 0xff;
@@ -101,7 +101,7 @@
   EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchInterfaceProtocol) {
+TEST_F(UsbUtilsTest, MatchInterfaceProtocol) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_class_code = true;
   filter->class_code = 0xff;
@@ -112,7 +112,7 @@
   EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchInterfaceProtocolNegative) {
+TEST_F(UsbUtilsTest, MatchInterfaceProtocolNegative) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->has_class_code = true;
   filter->class_code = 0xff;
@@ -123,7 +123,7 @@
   EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchSerialNumber) {
+TEST_F(UsbUtilsTest, MatchSerialNumber) {
   auto filter = mojom::UsbDeviceFilter::New();
   filter->serial_number = base::ASCIIToUTF16("ABC123");
   EXPECT_TRUE(UsbDeviceFilterMatches(*filter, *android_phone_));
@@ -137,12 +137,12 @@
   EXPECT_FALSE(UsbDeviceFilterMatches(*filter, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchAnyEmptyList) {
+TEST_F(UsbUtilsTest, MatchAnyEmptyList) {
   std::vector<mojom::UsbDeviceFilterPtr> filters;
   ASSERT_TRUE(UsbDeviceFilterMatchesAny(filters, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchesAnyVendorId) {
+TEST_F(UsbUtilsTest, MatchesAnyVendorId) {
   std::vector<mojom::UsbDeviceFilterPtr> filters;
   filters.push_back(mojom::UsbDeviceFilter::New());
   filters.back()->has_vendor_id = true;
@@ -150,7 +150,7 @@
   ASSERT_TRUE(UsbDeviceFilterMatchesAny(filters, *android_phone_));
 }
 
-TEST_F(UsbFilterTest, MatchesAnyVendorIdNegative) {
+TEST_F(UsbUtilsTest, MatchesAnyVendorIdNegative) {
   std::vector<mojom::UsbDeviceFilterPtr> filters;
   filters.push_back(mojom::UsbDeviceFilter::New());
   filters.back()->has_vendor_id = true;
diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc
index dceae50f..eee0f08 100644
--- a/extensions/browser/api/device_permissions_prompt.cc
+++ b/extensions/browser/api/device_permissions_prompt.cc
@@ -16,7 +16,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/service_manager_connection.h"
 #include "device/base/device_client.h"
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/usb_device.h"
 #include "device/usb/usb_ids.h"
 #include "device/usb/usb_service.h"
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc
index eb6ddd6..5fc5b34 100644
--- a/extensions/browser/api/usb/usb_api.cc
+++ b/extensions/browser/api/usb/usb_api.cc
@@ -16,7 +16,7 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/values.h"
 #include "device/base/device_client.h"
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
 #include "device/usb/usb_descriptors.h"
 #include "device/usb/usb_device_handle.h"
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc
index 4f54050..cfccd40 100644
--- a/extensions/browser/app_window/app_window.cc
+++ b/extensions/browser/app_window/app_window.cc
@@ -1086,9 +1086,7 @@
 SkRegion* AppWindow::RawDraggableRegionsToSkRegion(
     const std::vector<DraggableRegion>& regions) {
   SkRegion* sk_region = new SkRegion;
-  for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
-       iter != regions.end();
-       ++iter) {
+  for (auto iter = regions.cbegin(); iter != regions.cend(); ++iter) {
     const DraggableRegion& region = *iter;
     sk_region->op(
         region.bounds.x(),
diff --git a/extensions/browser/app_window/app_window_geometry_cache.cc b/extensions/browser/app_window/app_window_geometry_cache.cc
index fd1d802..812b508 100644
--- a/extensions/browser/app_window/app_window_geometry_cache.cc
+++ b/extensions/browser/app_window/app_window_geometry_cache.cc
@@ -67,11 +67,9 @@
   extension_data[window_id].last_change = now;
 
   if (extension_data.size() > kMaxCachedWindows) {
-    ExtensionData::iterator oldest = extension_data.end();
+    auto oldest = extension_data.end();
     // Too many windows in the cache, find the oldest one to remove.
-    for (ExtensionData::iterator it = extension_data.begin();
-         it != extension_data.end();
-         ++it) {
+    for (auto it = extension_data.begin(); it != extension_data.end(); ++it) {
       // Don't expunge the window that was just added.
       if (it->first == window_id)
         continue;
@@ -99,18 +97,13 @@
 void AppWindowGeometryCache::SyncToStorage() {
   std::set<std::string> tosync;
   tosync.swap(unsynced_extensions_);
-  for (std::set<std::string>::const_iterator it = tosync.begin(),
-                                             eit = tosync.end();
-       it != eit;
-       ++it) {
+  for (auto it = tosync.cbegin(), eit = tosync.cend(); it != eit; ++it) {
     const std::string& extension_id = *it;
     const ExtensionData& extension_data = cache_[extension_id];
 
     std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
-    for (ExtensionData::const_iterator it = extension_data.begin(),
-                                       eit = extension_data.end();
-         it != eit;
-         ++it) {
+    for (auto it = extension_data.cbegin(), eit = extension_data.cend();
+         it != eit; ++it) {
       std::unique_ptr<base::DictionaryValue> value =
           std::make_unique<base::DictionaryValue>();
       const gfx::Rect& bounds = it->second.bounds;
@@ -156,8 +149,7 @@
     DCHECK(extension_data_it != cache_.end());
   }
 
-  ExtensionData::const_iterator window_data_it =
-      extension_data_it->second.find(window_id);
+  auto window_data_it = extension_data_it->second.find(window_id);
 
   if (window_data_it == extension_data_it->second.end())
     return false;
@@ -219,7 +211,7 @@
     // overwrite that information since it is probably the result of an
     // application starting up very quickly.
     const std::string& window_id = it.key();
-    ExtensionData::iterator cached_window = extension_data.find(window_id);
+    auto cached_window = extension_data.find(window_id);
     if (cached_window == extension_data.end()) {
       const base::DictionaryValue* stored_window;
       if (it.value().GetAsDictionary(&stored_window)) {
diff --git a/extensions/browser/app_window/app_window_registry.cc b/extensions/browser/app_window/app_window_registry.cc
index da30c95..4a59d05 100644
--- a/extensions/browser/app_window/app_window_registry.cc
+++ b/extensions/browser/app_window/app_window_registry.cc
@@ -100,9 +100,7 @@
 AppWindowRegistry::AppWindowList AppWindowRegistry::GetAppWindowsForApp(
     const std::string& app_id) const {
   AppWindowList app_windows;
-  for (AppWindowList::const_iterator i = app_windows_.begin();
-       i != app_windows_.end();
-       ++i) {
+  for (auto i = app_windows_.cbegin(); i != app_windows_.cend(); ++i) {
     if ((*i)->extension_id() == app_id)
       app_windows.push_back(*i);
   }
@@ -111,9 +109,7 @@
 
 void AppWindowRegistry::CloseAllAppWindowsForApp(const std::string& app_id) {
   const AppWindowList windows = GetAppWindowsForApp(app_id);
-  for (AppWindowRegistry::const_iterator it = windows.begin();
-       it != windows.end();
-       ++it) {
+  for (auto it = windows.cbegin(); it != windows.cend(); ++it) {
     (*it)->GetBaseWindow()->Close();
   }
 }
@@ -129,9 +125,7 @@
 
 AppWindow* AppWindowRegistry::GetAppWindowForNativeWindow(
     gfx::NativeWindow window) const {
-  for (AppWindowList::const_iterator i = app_windows_.begin();
-       i != app_windows_.end();
-       ++i) {
+  for (auto i = app_windows_.cbegin(); i != app_windows_.cend(); ++i) {
     if ((*i)->GetNativeWindow() == window)
       return *i;
   }
@@ -142,9 +136,7 @@
 AppWindow* AppWindowRegistry::GetCurrentAppWindowForApp(
     const std::string& app_id) const {
   AppWindow* result = NULL;
-  for (AppWindowList::const_iterator i = app_windows_.begin();
-       i != app_windows_.end();
-       ++i) {
+  for (auto i = app_windows_.cbegin(); i != app_windows_.cend(); ++i) {
     if ((*i)->extension_id() == app_id) {
       result = *i;
       if (result->GetBaseWindow()->IsActive())
@@ -159,9 +151,7 @@
     const std::string& app_id,
     const std::string& window_key) const {
   AppWindow* result = NULL;
-  for (AppWindowList::const_iterator i = app_windows_.begin();
-       i != app_windows_.end();
-       ++i) {
+  for (auto i = app_windows_.cbegin(); i != app_windows_.cend(); ++i) {
     if ((*i)->extension_id() == app_id && (*i)->window_key() == window_key) {
       result = *i;
       if (result->GetBaseWindow()->IsActive())
diff --git a/extensions/browser/blob_holder.cc b/extensions/browser/blob_holder.cc
index 892d227..7410dbf 100644
--- a/extensions/browser/blob_holder.cc
+++ b/extensions/browser/blob_holder.cc
@@ -58,9 +58,7 @@
 
 bool BlobHolder::ContainsBlobHandle(content::BlobHandle* handle) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  for (BlobHandleMultimap::const_iterator it = held_blobs_.begin();
-       it != held_blobs_.end();
-       ++it) {
+  for (auto it = held_blobs_.cbegin(); it != held_blobs_.cend(); ++it) {
     if (it->second.get() == handle)
       return true;
   }
@@ -70,10 +68,9 @@
 
 void BlobHolder::DropBlobs(const std::vector<std::string>& blob_uuids) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  for (std::vector<std::string>::const_iterator uuid_it = blob_uuids.begin();
-       uuid_it != blob_uuids.end();
+  for (auto uuid_it = blob_uuids.cbegin(); uuid_it != blob_uuids.cend();
        ++uuid_it) {
-    BlobHandleMultimap::iterator it = held_blobs_.find(*uuid_it);
+    auto it = held_blobs_.find(*uuid_it);
 
     if (it != held_blobs_.end()) {
       held_blobs_.erase(it);
diff --git a/extensions/browser/computed_hashes.cc b/extensions/browser/computed_hashes.cc
index e0a365b..dab6e435 100644
--- a/extensions/browser/computed_hashes.cc
+++ b/extensions/browser/computed_hashes.cc
@@ -144,7 +144,7 @@
                                        int* block_size,
                                        std::vector<std::string>* hashes) const {
   base::FilePath path = relative_path.NormalizePathSeparatorsTo('/');
-  std::map<base::FilePath, HashInfo>::const_iterator i = data_.find(path);
+  auto i = data_.find(path);
   if (i == data_.end()) {
     // If we didn't find the entry using exact match, it's possible the
     // developer is using a path with some letters in the incorrect case, which
diff --git a/extensions/browser/content_hash_tree.cc b/extensions/browser/content_hash_tree.cc
index 2e2180f..a8fa8d5 100644
--- a/extensions/browser/content_hash_tree.cc
+++ b/extensions/browser/content_hash_tree.cc
@@ -31,8 +31,8 @@
   while (current->size() > 1) {
     // Iterate over the current level of hashes, computing the hash of up to
     // |branch_factor| elements to form the hash of each parent node.
-    std::vector<std::string>::const_iterator i = current->begin();
-    while (i != current->end()) {
+    auto i = current->cbegin();
+    while (i != current->cend()) {
       std::unique_ptr<crypto::SecureHash> hash(
           crypto::SecureHash::Create(crypto::SecureHash::SHA256));
       for (int j = 0; j < branch_factor && i != current->end(); j++) {
diff --git a/extensions/browser/content_verifier/content_hash.cc b/extensions/browser/content_verifier/content_hash.cc
index e321f4b..bcbe797 100644
--- a/extensions/browser/content_verifier/content_hash.cc
+++ b/extensions/browser/content_verifier/content_hash.cc
@@ -267,7 +267,7 @@
   // Now iterate over all the paths in sorted order and compute the block hashes
   // for each one.
   ComputedHashes::Writer writer;
-  for (SortedFilePathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
+  for (auto i = paths.begin(); i != paths.end(); ++i) {
     if (is_cancelled && is_cancelled.Run())
       return false;
 
diff --git a/extensions/browser/content_verifier/test_utils.cc b/extensions/browser/content_verifier/test_utils.cc
index 84102a7..9885a59 100644
--- a/extensions/browser/content_verifier/test_utils.cc
+++ b/extensions/browser/content_verifier/test_utils.cc
@@ -110,8 +110,7 @@
   Result result = failure_reason == ContentVerifyJob::NONE ? Result::SUCCESS
                                                            : Result::FAILURE;
   bool found = false;
-  for (std::list<ExpectedResult>::iterator i = expectations_.begin();
-       i != expectations_.end(); ++i) {
+  for (auto i = expectations_.begin(); i != expectations_.end(); ++i) {
     if (i->extension_id == extension_id && i->path == relative_path &&
         i->result == result) {
       found = true;
diff --git a/extensions/browser/content_verifier_io_data.cc b/extensions/browser/content_verifier_io_data.cc
index 1f321c5b..f616fd3 100644
--- a/extensions/browser/content_verifier_io_data.cc
+++ b/extensions/browser/content_verifier_io_data.cc
@@ -47,8 +47,7 @@
 const ContentVerifierIOData::ExtensionData* ContentVerifierIOData::GetData(
     const std::string& extension_id) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-  std::map<std::string, std::unique_ptr<ExtensionData>>::iterator found =
-      data_map_.find(extension_id);
+  auto found = data_map_.find(extension_id);
   if (found != data_map_.end())
     return found->second.get();
   else
diff --git a/extensions/browser/declarative_user_script_manager.cc b/extensions/browser/declarative_user_script_manager.cc
index 3d567506..48075a5f 100644
--- a/extensions/browser/declarative_user_script_manager.cc
+++ b/extensions/browser/declarative_user_script_manager.cc
@@ -30,8 +30,7 @@
 DeclarativeUserScriptMaster*
 DeclarativeUserScriptManager::GetDeclarativeUserScriptMasterByID(
     const HostID& host_id) {
-  UserScriptMasterMap::iterator it =
-      declarative_user_script_masters_.find(host_id);
+  auto it = declarative_user_script_masters_.find(host_id);
 
   if (it != declarative_user_script_masters_.end())
     return it->second.get();
diff --git a/extensions/browser/event_listener_map.cc b/extensions/browser/event_listener_map.cc
index 0fa23dd..d7d18d5 100644
--- a/extensions/browser/event_listener_map.cc
+++ b/extensions/browser/event_listener_map.cc
@@ -181,7 +181,7 @@
 
 bool EventListenerMap::HasListenerForEvent(
     const std::string& event_name) const {
-  ListenerMap::const_iterator it = listeners_.find(event_name);
+  auto it = listeners_.find(event_name);
   return it != listeners_.end() && !it->second.empty();
 }
 
@@ -231,8 +231,7 @@
     const std::string& extension_id) {
   for (auto& it : listeners_) {
     auto& listener_map = it.second;
-    for (ListenerList::iterator it2 = listener_map.begin();
-         it2 != listener_map.end();) {
+    for (auto it2 = listener_map.begin(); it2 != listener_map.end();) {
       if ((*it2)->extension_id() == extension_id) {
         std::unique_ptr<EventListener> listener_removed = std::move(*it2);
         CleanupListener(listener_removed.get());
@@ -325,8 +324,7 @@
   CHECK(process);
   for (auto& it : listeners_) {
     auto& listener_map = it.second;
-    for (ListenerList::iterator it2 = listener_map.begin();
-         it2 != listener_map.end();) {
+    for (auto it2 = listener_map.begin(); it2 != listener_map.end();) {
       if ((*it2)->process() == process) {
         std::unique_ptr<EventListener> listener_removed = std::move(*it2);
         CleanupListener(listener_removed.get());
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index 2c159f6..7c18362 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -242,7 +242,7 @@
 }
 
 void EventRouter::UnregisterObserver(Observer* observer) {
-  for (ObserverMap::iterator it = observers_.begin(); it != observers_.end();) {
+  for (auto it = observers_.begin(); it != observers_.end();) {
     if (it->second == observer)
       it = observers_.erase(it);
     else
@@ -264,7 +264,7 @@
                                   listener->listener_url(),
                                   listener->GetBrowserContext());
   std::string base_event_name = GetBaseEventName(listener->event_name());
-  ObserverMap::iterator observer = observers_.find(base_event_name);
+  auto observer = observers_.find(base_event_name);
   if (observer != observers_.end())
     observer->second->OnListenerAdded(details);
 
@@ -282,7 +282,7 @@
                                   listener->listener_url(),
                                   listener->GetBrowserContext());
   std::string base_event_name = GetBaseEventName(listener->event_name());
-  ObserverMap::iterator observer = observers_.find(base_event_name);
+  auto observer = observers_.find(base_event_name);
   if (observer != observers_.end())
     observer->second->OnListenerRemoved(details);
 }
@@ -849,8 +849,7 @@
                                       const std::set<std::string>& events,
                                       RegisteredEventType type) {
   auto events_value = std::make_unique<base::ListValue>();
-  for (std::set<std::string>::const_iterator iter = events.begin();
-       iter != events.end(); ++iter) {
+  for (auto iter = events.cbegin(); iter != events.cend(); ++iter) {
     events_value->AppendString(*iter);
   }
   const char* pref_key = type == RegisteredEventType::kLazy
diff --git a/extensions/browser/extension_api_frame_id_map.cc b/extensions/browser/extension_api_frame_id_map.cc
index 54eb1d0..56e9837a 100644
--- a/extensions/browser/extension_api_frame_id_map.cc
+++ b/extensions/browser/extension_api_frame_id_map.cc
@@ -230,7 +230,7 @@
     const FrameData& cached_frame_data) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  FrameDataCallbacksMap::iterator map_iter = callbacks_map_.find(key);
+  auto map_iter = callbacks_map_.find(key);
   if (map_iter == callbacks_map_.end()) {
     // Can happen if ReceivedFrameDataOnIO was called after the frame ID was
     // resolved (e.g. via GetFrameDataOnIO), but before PostTaskAndReply
@@ -246,8 +246,8 @@
 
   // Note: Extra items can be appended to |callbacks| during this loop if a
   // callback calls GetFrameDataOnIO().
-  for (std::list<FrameDataCallback>::iterator it = callbacks.callbacks.begin();
-       it != callbacks.callbacks.end(); ++it) {
+  for (auto it = callbacks.callbacks.begin(); it != callbacks.callbacks.end();
+       ++it) {
     it->Run(cached_frame_data);
   }
   callbacks_map_.erase(key);
@@ -271,7 +271,7 @@
       render_process_id, frame_routing_id, &cached_frame_data);
 
   const RenderFrameIdKey key(render_process_id, frame_routing_id);
-  FrameDataCallbacksMap::iterator map_iter = callbacks_map_.find(key);
+  auto map_iter = callbacks_map_.find(key);
 
   if (did_find_cached_frame_data) {
     // Value already cached, thread hopping is not needed.
@@ -378,7 +378,7 @@
   }
 
   base::AutoLock lock(frame_data_map_lock_);
-  FrameDataMap::iterator iter = frame_data_map_.find(key);
+  auto iter = frame_data_map_.find(key);
   // The FrameData for |rfh| should have already been initialized.
   DCHECK(iter != frame_data_map_.end());
   iter->second.tab_id = tab_id;
@@ -406,7 +406,7 @@
   const RenderFrameIdKey key(main_frame->GetProcess()->GetID(),
                              main_frame->GetRoutingID());
   base::AutoLock lock(frame_data_map_lock_);
-  FrameDataMap::iterator iter = frame_data_map_.find(key);
+  auto iter = frame_data_map_.find(key);
 
   // We must have already cached the FrameData for this in
   // InitializeRenderFrameHost.
@@ -448,7 +448,7 @@
   const RenderFrameIdKey key(main_frame->GetProcess()->GetID(),
                              main_frame->GetRoutingID());
   base::AutoLock lock(frame_data_map_lock_);
-  FrameDataMap::iterator iter = frame_data_map_.find(key);
+  auto iter = frame_data_map_.find(key);
 
   // We must have already cached the FrameData for this in
   // InitializeRenderFrameHost.
diff --git a/extensions/browser/extension_error.cc b/extensions/browser/extension_error.cc
index 1347c05..736fd19 100644
--- a/extensions/browser/extension_error.cc
+++ b/extensions/browser/extension_error.cc
@@ -115,8 +115,7 @@
          "\n  Type:    RuntimeError"
          "\n  Context: " + context_url_.spec() +
          "\n  Stack Trace: ";
-  for (StackTrace::const_iterator iter = stack_trace_.begin();
-       iter != stack_trace_.end(); ++iter) {
+  for (auto iter = stack_trace_.cbegin(); iter != stack_trace_.cend(); ++iter) {
     result += "\n    {";
     result += "\n      Line:     " + base::NumberToString(iter->line_number) +
               "\n      Column:   " + base::NumberToString(iter->column_number) +
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc
index a451b39..616100b6 100644
--- a/extensions/browser/extension_function_dispatcher.cc
+++ b/extensions/browser/extension_function_dispatcher.cc
@@ -520,8 +520,7 @@
     int render_process_id) {
   UIThreadWorkerResponseCallbackWrapperMap& map =
       ui_thread_response_callback_wrappers_for_worker_;
-  for (UIThreadWorkerResponseCallbackWrapperMap::iterator it = map.begin();
-       it != map.end();) {
+  for (auto it = map.begin(); it != map.end();) {
     if (it->first.render_process_id == render_process_id) {
       it = map.erase(it);
       continue;
diff --git a/extensions/browser/extension_function_registry.cc b/extensions/browser/extension_function_registry.cc
index 61ecce0..f9a8d72 100644
--- a/extensions/browser/extension_function_registry.cc
+++ b/extensions/browser/extension_function_registry.cc
@@ -27,7 +27,7 @@
 bool ExtensionFunctionRegistry::OverrideFunctionForTesting(
     const std::string& name,
     ExtensionFunctionFactory factory) {
-  FactoryMap::iterator iter = factories_.find(name);
+  auto iter = factories_.find(name);
   if (iter == factories_.end())
     return false;
   iter->second.factory_ = factory;
@@ -36,7 +36,7 @@
 
 ExtensionFunction* ExtensionFunctionRegistry::NewFunction(
     const std::string& name) {
-  FactoryMap::iterator iter = factories_.find(name);
+  auto iter = factories_.find(name);
   if (iter == factories_.end()) {
     return NULL;
   }
diff --git a/extensions/browser/extension_pref_value_map.cc b/extensions/browser/extension_pref_value_map.cc
index 68c5c61..93fe044 100644
--- a/extensions/browser/extension_pref_value_map.cc
+++ b/extensions/browser/extension_pref_value_map.cc
@@ -68,7 +68,7 @@
     const std::string& extension_id,
     const std::string& pref_key,
     bool incognito) const {
-  ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
+  auto ext = entries_.find(extension_id);
   if (ext == entries_.end()) {
     NOTREACHED() << "Extension " << extension_id
                  << " is not registered but accesses pref " << pref_key
@@ -80,8 +80,7 @@
   if (incognito && !ext->second->incognito_enabled)
     return false;
 
-  ExtensionEntryMap::const_iterator winner =
-      GetEffectivePrefValueController(pref_key, incognito, NULL);
+  auto winner = GetEffectivePrefValueController(pref_key, incognito, NULL);
   if (winner == entries_.end())
     return true;
 
@@ -109,7 +108,7 @@
     const std::string& pref_key,
     bool* from_incognito) const {
   bool incognito = (from_incognito != NULL);
-  ExtensionEntryMap::const_iterator winner =
+  auto winner =
       GetEffectivePrefValueController(pref_key, incognito, from_incognito);
   if (winner == entries_.end())
     return false;
@@ -132,7 +131,7 @@
 }
 
 void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
-  ExtensionEntryMap::iterator i = entries_.find(ext_id);
+  auto i = entries_.find(ext_id);
   if (i == entries_.end())
     return;
   std::set<std::string> keys;  // keys set by this extension
@@ -196,7 +195,7 @@
 const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
     const std::string& ext_id,
     ExtensionPrefsScope scope) const {
-  ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
+  auto i = entries_.find(ext_id);
   CHECK(i != entries_.end());
   switch (scope) {
     case extensions::kExtensionPrefsScopeRegular:
@@ -241,8 +240,7 @@
     const std::string& key,
     bool incognito,
     bool* from_incognito) const {
-  ExtensionEntryMap::const_iterator winner =
-      GetEffectivePrefValueController(key, incognito, from_incognito);
+  auto winner = GetEffectivePrefValueController(key, incognito, from_incognito);
   if (winner == entries_.end())
     return NULL;
 
@@ -287,11 +285,10 @@
     const std::string& key,
     bool incognito,
     bool* from_incognito) const {
-  ExtensionEntryMap::const_iterator winner = entries_.end();
+  auto winner = entries_.cend();
   base::Time winners_install_time;
 
-  ExtensionEntryMap::const_iterator i;
-  for (i = entries_.begin(); i != entries_.end(); ++i) {
+  for (auto i = entries_.cbegin(); i != entries_.cend(); ++i) {
     const std::string& ext_id = i->first;
     const base::Time& install_time = i->second->install_time;
     const bool enabled = i->second->enabled;
@@ -370,8 +367,7 @@
 
 std::string ExtensionPrefValueMap::GetExtensionControllingPref(
     const std::string& pref_key) const {
-  ExtensionEntryMap::const_iterator winner =
-      GetEffectivePrefValueController(pref_key, false, NULL);
+  auto winner = GetEffectivePrefValueController(pref_key, false, NULL);
   if (winner == entries_.end())
     return std::string();
   return winner->first;
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index aa29d85..32fd9f2 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -392,8 +392,7 @@
   // Fix these paths.
   prefs::ScopedDictionaryPrefUpdate update(prefs_, pref_names::kExtensions);
   auto update_dict = update.Get();
-  for (std::set<std::string>::iterator i = absolute_keys.begin();
-       i != absolute_keys.end(); ++i) {
+  for (auto i = absolute_keys.begin(); i != absolute_keys.end(); ++i) {
     std::unique_ptr<prefs::DictionaryValueUpdate> extension_dict;
     if (!update_dict->GetDictionaryWithoutPathExpansion(*i, &extension_dict)) {
       NOTREACHED() << "Control should never reach here for extension " << *i;
@@ -1789,9 +1788,7 @@
   MakePathsRelative();
 
   // Ensure that any early observers are watching before prefs are initialized.
-  for (std::vector<ExtensionPrefsObserver*>::const_iterator iter =
-           early_observers.begin();
-       iter != early_observers.end();
+  for (auto iter = early_observers.cbegin(); iter != early_observers.cend();
        ++iter) {
     AddObserver(*iter);
   }
@@ -1856,7 +1853,7 @@
   std::insert_iterator<ExtensionIdContainer> insert_iterator(
       *id_container_out, id_container_out->end());
   std::string extension_id;
-  for (base::ListValue::const_iterator value_it = user_pref_as_list->begin();
+  for (auto value_it = user_pref_as_list->begin();
        value_it != user_pref_as_list->end(); ++value_it) {
     if (!value_it->GetAsString(&extension_id)) {
       NOTREACHED();
@@ -1874,8 +1871,7 @@
   ListPrefUpdate update(prefs_, pref);
   base::ListValue* list_of_values = update.Get();
   list_of_values->Clear();
-  for (typename ExtensionIdContainer::const_iterator iter = strings.begin();
-       iter != strings.end(); ++iter) {
+  for (auto iter = strings.cbegin(); iter != strings.cend(); ++iter) {
     list_of_values->AppendString(*iter);
   }
 }
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc
index 18a38ae..55d68f7 100644
--- a/extensions/browser/extension_registrar.cc
+++ b/extensions/browser/extension_registrar.cc
@@ -403,8 +403,7 @@
 
 void ExtensionRegistrar::DidCreateRenderViewForBackgroundPage(
     ExtensionHost* host) {
-  OrphanedDevTools::iterator iter =
-      orphaned_dev_tools_.find(host->extension_id());
+  auto iter = orphaned_dev_tools_.find(host->extension_id());
   if (iter == orphaned_dev_tools_.end())
     return;
   // Keepalive count is reset on extension reload. This re-establishes the
diff --git a/extensions/browser/extension_user_script_loader.cc b/extensions/browser/extension_user_script_loader.cc
index 1e4f55f..78878aa7 100644
--- a/extensions/browser/extension_user_script_loader.cc
+++ b/extensions/browser/extension_user_script_loader.cc
@@ -149,8 +149,7 @@
 SubstitutionMap* GetLocalizationMessages(
     const ExtensionUserScriptLoader::HostsInfo& hosts_info,
     const HostID& host_id) {
-  ExtensionUserScriptLoader::HostsInfo::const_iterator iter =
-      hosts_info.find(host_id);
+  auto iter = hosts_info.find(host_id);
   if (iter == hosts_info.end())
     return nullptr;
   return file_util::LoadMessageBundleSubstitutionMap(
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc
index 8a1ab79..6114ded5 100644
--- a/extensions/browser/guest_view/app_view/app_view_guest.cc
+++ b/extensions/browser/guest_view/app_view/app_view_guest.cc
@@ -70,7 +70,7 @@
     const std::string& guest_extension_id,
     content::RenderProcessHost* guest_render_process_host) {
   PendingResponseMap* response_map = pending_response_map.Pointer();
-  PendingResponseMap::iterator it = response_map->find(guest_instance_id);
+  auto it = response_map->find(guest_instance_id);
   // Kill the requesting process if it is not the real guest.
   if (it == response_map->end()) {
     // The requester used an invalid |guest_instance_id|.
diff --git a/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc b/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc
index 8f8ab11..62edf3f 100644
--- a/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc
+++ b/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc
@@ -61,7 +61,7 @@
   std::set<int> ids_to_add;
 
   GuestMapKey key = std::pair<int, int>(embedder_process_id, view_instance_id);
-  GuestContentScriptMap::iterator iter = guest_content_script_map_.find(key);
+  auto iter = guest_content_script_map_.find(key);
 
   // Step 1: finds the entry in guest_content_script_map_ by the given |key|.
   // If there isn't any content script added for the given guest yet, insert an
@@ -147,8 +147,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   GuestMapKey key = std::pair<int, int>(embedder_process_id, view_instance_id);
-  GuestContentScriptMap::iterator script_map_iter =
-      guest_content_script_map_.find(key);
+  auto script_map_iter = guest_content_script_map_.find(key);
   if (script_map_iter == guest_content_script_map_.end())
     return;
 
@@ -176,7 +175,7 @@
     }
   } else {
     for (const std::string& name : script_name_list) {
-      ContentScriptMap::iterator iter = map.find(name);
+      auto iter = map.find(name);
       if (iter == map.end())
         continue;
       const UserScriptIDPair& id_pair = iter->second;
diff --git a/extensions/browser/guest_view/web_view/web_view_find_helper.cc b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
index d54748c..7af72d80 100644
--- a/extensions/browser/guest_view/web_view/web_view_find_helper.cc
+++ b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
@@ -45,8 +45,7 @@
 }
 
 void WebViewFindHelper::EndFindSession(int session_request_id, bool canceled) {
-  FindInfoMap::iterator session_iterator =
-      find_info_map_.find(session_request_id);
+  auto session_iterator = find_info_map_.find(session_request_id);
   DCHECK(session_iterator != find_info_map_.end());
   FindInfo* find_info = session_iterator->second.get();
 
@@ -54,10 +53,8 @@
   find_info->SendResponse(canceled);
 
   // For every subsequent find request of the find session.
-  for (std::vector<base::WeakPtr<WebViewFindHelper::FindInfo> >::iterator i =
-           find_info->find_next_requests_.begin();
-       i != find_info->find_next_requests_.end();
-       ++i) {
+  for (auto i = find_info->find_next_requests_.begin();
+       i != find_info->find_next_requests_.end(); ++i) {
     DCHECK(i->get());
 
     // Do not call callbacks for subsequent find requests that have not been
@@ -148,7 +145,7 @@
                                   const gfx::Rect& selection_rect,
                                   int active_match_ordinal,
                                   bool final_update) {
-  FindInfoMap::iterator find_iterator = find_info_map_.find(request_id);
+  auto find_iterator = find_info_map_.find(request_id);
 
   // Ignore slow replies to canceled find requests.
   if (find_iterator == find_info_map_.end())
diff --git a/extensions/browser/image_loader.cc b/extensions/browser/image_loader.cc
index a5959d5..8c003a3 100644
--- a/extensions/browser/image_loader.cc
+++ b/extensions/browser/image_loader.cc
@@ -105,10 +105,7 @@
   bitmaps.resize(info_list.size());
 
   int i = 0;
-  for (std::vector<ImageLoader::ImageRepresentation>::const_iterator
-           it = info_list.begin();
-       it != info_list.end();
-       ++it, ++i) {
+  for (auto it = info_list.cbegin(); it != info_list.cend(); ++it, ++i) {
     DCHECK(it->resource.relative_path().empty() ||
            extension->path() == it->resource.extension_root());
 
@@ -291,8 +288,7 @@
 
   gfx::ImageSkia image_skia;
 
-  for (std::vector<LoadResult>::const_iterator it = load_result.begin();
-       it != load_result.end(); ++it) {
+  for (auto it = load_result.cbegin(); it != load_result.cend(); ++it) {
     const SkBitmap& bitmap = it->bitmap;
     const ImageRepresentation& image_rep = it->image_representation;
 
@@ -317,9 +313,7 @@
   std::map<std::pair<int, int>, gfx::ImageSkia> image_skia_map;
   gfx::ImageFamily image_family;
 
-  for (std::vector<LoadResult>::const_iterator it = load_result.begin();
-       it != load_result.end();
-       ++it) {
+  for (auto it = load_result.cbegin(); it != load_result.cend(); ++it) {
     const SkBitmap& bitmap = it->bitmap;
     const ImageRepresentation& image_rep = it->image_representation;
     const std::pair<int, int> key = std::make_pair(
@@ -330,10 +324,7 @@
         gfx::ImageSkiaRep(bitmap, image_rep.scale_factor));
   }
 
-  for (std::map<std::pair<int, int>, gfx::ImageSkia>::iterator it =
-           image_skia_map.begin();
-       it != image_skia_map.end();
-       ++it) {
+  for (auto it = image_skia_map.begin(); it != image_skia_map.end(); ++it) {
     it->second.MakeThreadSafe();
     image_family.Add(it->second);
   }
diff --git a/extensions/browser/info_map.cc b/extensions/browser/info_map.cc
index ef9fc31..7f2ba3d 100644
--- a/extensions/browser/info_map.cc
+++ b/extensions/browser/info_map.cc
@@ -96,7 +96,7 @@
 }
 
 base::Time InfoMap::GetInstallTime(const std::string& extension_id) const {
-  ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
+  auto iter = extra_data_.find(extension_id);
   if (iter != extra_data_.end())
     return iter->second.install_time;
   return base::Time();
@@ -104,7 +104,7 @@
 
 bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const {
   // Keep in sync with duplicate in extensions/browser/process_manager.cc.
-  ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
+  auto iter = extra_data_.find(extension_id);
   if (iter != extra_data_.end())
     return iter->second.incognito_enabled;
   return false;
@@ -217,14 +217,14 @@
 void InfoMap::SetNotificationsDisabled(
     const std::string& extension_id,
     bool notifications_disabled) {
-  ExtraDataMap::iterator iter = extra_data_.find(extension_id);
+  auto iter = extra_data_.find(extension_id);
   if (iter != extra_data_.end())
     iter->second.notifications_disabled = notifications_disabled;
 }
 
 bool InfoMap::AreNotificationsDisabled(
     const std::string& extension_id) const {
-  ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
+  auto iter = extra_data_.find(extension_id);
   if (iter != extra_data_.end())
     return iter->second.notifications_disabled;
   return false;
diff --git a/extensions/browser/lazy_background_task_queue.cc b/extensions/browser/lazy_background_task_queue.cc
index f982c720..49d4477 100644
--- a/extensions/browser/lazy_background_task_queue.cc
+++ b/extensions/browser/lazy_background_task_queue.cc
@@ -114,7 +114,7 @@
   }
   PendingTasksList* tasks_list = nullptr;
   PendingTasksKey key(browser_context, extension_id);
-  PendingTasksMap::iterator it = pending_tasks_.find(key);
+  auto it = pending_tasks_.find(key);
   if (it == pending_tasks_.end()) {
     const Extension* extension = ExtensionRegistry::Get(browser_context)
                                      ->enabled_extensions()
@@ -149,7 +149,7 @@
     return;
 
   PendingTasksKey key(browser_context, extension->id());
-  PendingTasksMap::iterator map_it = pending_tasks_.find(key);
+  auto map_it = pending_tasks_.find(key);
   if (map_it == pending_tasks_.end()) {
     if (BackgroundInfo::HasLazyBackgroundPage(extension))
       CHECK(!host);  // lazy page should not load without any pending tasks
diff --git a/extensions/browser/management_policy.cc b/extensions/browser/management_policy.cc
index b6e70cf7..f6b6f71 100644
--- a/extensions/browser/management_policy.cc
+++ b/extensions/browser/management_policy.cc
@@ -119,8 +119,7 @@
     return true;
   }
 
-  for (ProviderList::const_iterator it = providers_.begin();
-       it != providers_.end(); ++it)
+  for (auto it = providers_.cbegin(); it != providers_.cend(); ++it)
     if ((*it)->MustRemainDisabled(extension, reason, error))
       return true;
 
diff --git a/extensions/browser/mock_external_provider.cc b/extensions/browser/mock_external_provider.cc
index 52820e71..42c4d19 100644
--- a/extensions/browser/mock_external_provider.cc
+++ b/extensions/browser/mock_external_provider.cc
@@ -65,8 +65,8 @@
     const std::string& id,
     Manifest::Location* location,
     std::unique_ptr<base::Version>* version) const {
-  FileDataMap::const_iterator it1 = file_extension_map_.find(id);
-  UrlDataMap::const_iterator it2 = url_extension_map_.find(id);
+  auto it1 = file_extension_map_.find(id);
+  auto it2 = url_extension_map_.find(id);
 
   // |id| can't be on both |file_extension_map_| and |url_extension_map_|.
   if (it1 == file_extension_map_.end() && it2 == url_extension_map_.end())
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 6e97fdb..5be5c1b09 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -286,8 +286,7 @@
 
 void ProcessManager::UnregisterRenderFrameHost(
     content::RenderFrameHost* render_frame_host) {
-  ExtensionRenderFrames::iterator frame =
-      all_extension_frames_.find(render_frame_host);
+  auto frame = all_extension_frames_.find(render_frame_host);
 
   if (frame != all_extension_frames_.end()) {
     std::string extension_id = GetExtensionID(render_frame_host);
@@ -713,8 +712,7 @@
 
 void ProcessManager::AcquireLazyKeepaliveCountForFrame(
     content::RenderFrameHost* render_frame_host) {
-  ExtensionRenderFrames::iterator it =
-      all_extension_frames_.find(render_frame_host);
+  auto it = all_extension_frames_.find(render_frame_host);
   if (it == all_extension_frames_.end())
     return;
 
@@ -732,8 +730,7 @@
 
 void ProcessManager::ReleaseLazyKeepaliveCountForFrame(
     content::RenderFrameHost* render_frame_host) {
-  ExtensionRenderFrames::iterator iter =
-      all_extension_frames_.find(render_frame_host);
+  auto iter = all_extension_frames_.find(render_frame_host);
   if (iter == all_extension_frames_.end())
     return;
 
@@ -877,8 +874,8 @@
   // decrement the lazy_keepalive_count to negative for the new extension
   // instance when they are destroyed. Since we are erasing the background page
   // data for the unloaded extension, unregister the RenderFrameHosts too.
-  for (ExtensionRenderFrames::iterator it = all_extension_frames_.begin();
-       it != all_extension_frames_.end(); ) {
+  for (auto it = all_extension_frames_.begin();
+       it != all_extension_frames_.end();) {
     content::RenderFrameHost* host = it->first;
     if (GetExtensionID(host) == extension_id) {
       all_extension_frames_.erase(it++);
diff --git a/extensions/browser/process_map.cc b/extensions/browser/process_map.cc
index c12c635..18ada29 100644
--- a/extensions/browser/process_map.cc
+++ b/extensions/browser/process_map.cc
@@ -73,7 +73,7 @@
 
 int ProcessMap::RemoveAllFromProcess(int process_id) {
   int result = 0;
-  for (ItemSet::iterator iter = items_.begin(); iter != items_.end(); ) {
+  for (auto iter = items_.begin(); iter != items_.end();) {
     if (iter->process_id == process_id) {
       items_.erase(iter++);
       ++result;
@@ -86,8 +86,7 @@
 
 bool ProcessMap::Contains(const std::string& extension_id,
                           int process_id) const {
-  for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end();
-       ++iter) {
+  for (auto iter = items_.cbegin(); iter != items_.cend(); ++iter) {
     if (iter->process_id == process_id && iter->extension_id == extension_id)
       return true;
   }
@@ -95,8 +94,7 @@
 }
 
 bool ProcessMap::Contains(int process_id) const {
-  for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end();
-       ++iter) {
+  for (auto iter = items_.cbegin(); iter != items_.cend(); ++iter) {
     if (iter->process_id == process_id)
       return true;
   }
@@ -105,8 +103,7 @@
 
 std::set<std::string> ProcessMap::GetExtensionsInProcess(int process_id) const {
   std::set<std::string> result;
-  for (ItemSet::const_iterator iter = items_.begin(); iter != items_.end();
-       ++iter) {
+  for (auto iter = items_.cbegin(); iter != items_.cend(); ++iter) {
     if (iter->process_id == process_id)
       result.insert(iter->extension_id);
   }
diff --git a/extensions/browser/quota_service.cc b/extensions/browser/quota_service.cc
index 3d53713..8dc45c9 100644
--- a/extensions/browser/quota_service.cc
+++ b/extensions/browser/quota_service.cc
@@ -116,7 +116,7 @@
                                       const base::TimeTicks& event_time) {
   BucketList buckets;
   bucket_mapper_->GetBucketsForArgs(args, &buckets);
-  for (BucketList::iterator i = buckets.begin(); i != buckets.end(); ++i) {
+  for (auto i = buckets.begin(); i != buckets.end(); ++i) {
     if ((*i)->expiration().is_null())  // A brand new bucket.
       (*i)->Reset(config_, event_time);
     if (!Apply(*i, event_time))
diff --git a/extensions/browser/runtime_data.cc b/extensions/browser/runtime_data.cc
index a598dca..4beff20c 100644
--- a/extensions/browser/runtime_data.cc
+++ b/extensions/browser/runtime_data.cc
@@ -50,14 +50,14 @@
 void RuntimeData::OnExtensionUnloaded(content::BrowserContext* browser_context,
                                       const Extension* extension,
                                       UnloadedExtensionReason reason) {
-  ExtensionFlagsMap::iterator iter = extension_flags_.find(extension->id());
+  auto iter = extension_flags_.find(extension->id());
   if (iter != extension_flags_.end())
     iter->second = iter->second & kPersistAcrossUnloadMask;
 }
 
 bool RuntimeData::HasFlag(const std::string& extension_id,
                           RuntimeFlag flag) const {
-  ExtensionFlagsMap::const_iterator it = extension_flags_.find(extension_id);
+  auto it = extension_flags_.find(extension_id);
   if (it == extension_flags_.end())
     return false;
   return !!(it->second & flag);
diff --git a/extensions/browser/serial_extension_host_queue.cc b/extensions/browser/serial_extension_host_queue.cc
index 60a2044..6440821 100644
--- a/extensions/browser/serial_extension_host_queue.cc
+++ b/extensions/browser/serial_extension_host_queue.cc
@@ -55,8 +55,7 @@
 }
 
 void SerialExtensionHostQueue::Remove(DeferredStartRenderHost* host) {
-  std::list<DeferredStartRenderHost*>::iterator it =
-      std::find(queue_.begin(), queue_.end(), host);
+  auto it = std::find(queue_.begin(), queue_.end(), host);
   if (it != queue_.end())
     queue_.erase(it);
 }
diff --git a/extensions/browser/state_store.cc b/extensions/browser/state_store.cc
index 4eca45cb..c038e1d 100644
--- a/extensions/browser/state_store.cc
+++ b/extensions/browser/state_store.cc
@@ -186,8 +186,7 @@
 }
 
 void StateStore::RemoveKeysForExtension(const std::string& extension_id) {
-  for (std::set<std::string>::iterator key = registered_keys_.begin();
-       key != registered_keys_.end();
+  for (auto key = registered_keys_.begin(); key != registered_keys_.end();
        ++key) {
     task_queue_->InvokeWhenReady(base::Bind(&ValueStoreFrontend::Remove,
                                             base::Unretained(store_.get()),
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc
index fd96c492..66a9044 100644
--- a/extensions/browser/updater/extension_downloader.cc
+++ b/extensions/browser/updater/extension_downloader.cc
@@ -291,8 +291,7 @@
   ReportStats();
   url_stats_ = URLStats();
 
-  for (FetchMap::iterator it = fetches_preparing_.begin();
-       it != fetches_preparing_.end();
+  for (auto it = fetches_preparing_.begin(); it != fetches_preparing_.end();
        ++it) {
     std::vector<std::unique_ptr<ManifestFetchData>>& list = it->second;
     for (size_t i = 0; i < list.size(); ++i)
@@ -392,7 +391,7 @@
 
   // Find or create a ManifestFetchData to add this extension to.
   bool added = false;
-  FetchMap::iterator existing_iter =
+  auto existing_iter =
       fetches_preparing_.find(std::make_pair(request_id, update_url));
   if (existing_iter != fetches_preparing_.end() &&
       !existing_iter->second.empty()) {
@@ -1043,9 +1042,7 @@
     const std::set<std::string>& extension_ids,
     const std::set<int>& request_ids,
     ExtensionDownloaderDelegate::Error error) {
-  for (std::set<std::string>::const_iterator it = extension_ids.begin();
-       it != extension_ids.end();
-       ++it) {
+  for (auto it = extension_ids.cbegin(); it != extension_ids.cend(); ++it) {
     const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[*it];
     delegate_->OnExtensionDownloadFailed(*it, error, ping, request_ids);
     ping_results_.erase(*it);
diff --git a/extensions/browser/updater/manifest_fetch_data.cc b/extensions/browser/updater/manifest_fetch_data.cc
index 48535d9..1c8448f 100644
--- a/extensions/browser/updater/manifest_fetch_data.cc
+++ b/extensions/browser/updater/manifest_fetch_data.cc
@@ -207,7 +207,7 @@
 
 bool ManifestFetchData::DidPing(const std::string& extension_id,
                                 PingType type) const {
-  std::map<std::string, PingData>::const_iterator i = pings_.find(extension_id);
+  auto i = pings_.find(extension_id);
   if (i == pings_.end())
     return false;
   int value = 0;
diff --git a/extensions/browser/user_script_loader.cc b/extensions/browser/user_script_loader.cc
index 8a26dce9..faef48f 100644
--- a/extensions/browser/user_script_loader.cc
+++ b/extensions/browser/user_script_loader.cc
@@ -258,8 +258,7 @@
   if (clear_scripts_) {
     user_scripts_->clear();
   } else {
-    for (UserScriptList::iterator it = user_scripts_->begin();
-         it != user_scripts_->end();) {
+    for (auto it = user_scripts_->begin(); it != user_scripts_->end();) {
       UserScriptIDPair id_pair(it->get()->id());
       if (removed_script_hosts_.count(id_pair) > 0u)
         it = user_scripts_->erase(it);
diff --git a/extensions/browser/value_store/testing_value_store.cc b/extensions/browser/value_store/testing_value_store.cc
index 6f1d056..72a292c 100644
--- a/extensions/browser/value_store/testing_value_store.cc
+++ b/extensions/browser/value_store/testing_value_store.cc
@@ -59,8 +59,7 @@
     return ReadResult(CreateStatusCopy(status_));
 
   auto settings = std::make_unique<base::DictionaryValue>();
-  for (std::vector<std::string>::const_iterator it = keys.begin();
-      it != keys.end(); ++it) {
+  for (auto it = keys.cbegin(); it != keys.cend(); ++it) {
     base::Value* value = NULL;
     if (storage_.GetWithoutPathExpansion(*it, &value)) {
       settings->SetWithoutPathExpansion(*it, value->CreateDeepCopy());
@@ -115,8 +114,7 @@
     return WriteResult(CreateStatusCopy(status_));
 
   std::unique_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList());
-  for (std::vector<std::string>::const_iterator it = keys.begin();
-      it != keys.end(); ++it) {
+  for (auto it = keys.cbegin(); it != keys.cend(); ++it) {
     std::unique_ptr<base::Value> old_value;
     if (storage_.RemoveWithoutPathExpansion(*it, &old_value)) {
       changes->push_back(ValueStoreChange(*it, std::move(old_value), nullptr));
diff --git a/extensions/browser/value_store/value_store_change.cc b/extensions/browser/value_store/value_store_change.cc
index 757d27f..dc5abce 100644
--- a/extensions/browser/value_store/value_store_change.cc
+++ b/extensions/browser/value_store/value_store_change.cc
@@ -13,8 +13,7 @@
 std::string ValueStoreChange::ToJson(
     const ValueStoreChangeList& changes) {
   base::DictionaryValue changes_value;
-  for (ValueStoreChangeList::const_iterator it = changes.begin();
-      it != changes.end(); ++it) {
+  for (auto it = changes.cbegin(); it != changes.cend(); ++it) {
     std::unique_ptr<base::DictionaryValue> change_value =
         std::make_unique<base::DictionaryValue>();
     if (it->old_value()) {
diff --git a/extensions/browser/value_store/value_store_unittest.cc b/extensions/browser/value_store/value_store_unittest.cc
index 198fdf3..b797e43 100644
--- a/extensions/browser/value_store/value_store_unittest.cc
+++ b/extensions/browser/value_store/value_store_unittest.cc
@@ -91,8 +91,7 @@
 
   std::set<std::string> keys_seen;
 
-  for (ValueStoreChangeList::const_iterator it = actual.begin();
-      it != actual.end(); ++it) {
+  for (auto it = actual.cbegin(); it != actual.cend(); ++it) {
     if (keys_seen.count(it->key())) {
       return testing::AssertionFailure() <<
           "Multiple changes seen for key: " << it->key();
diff --git a/extensions/browser/verified_contents.cc b/extensions/browser/verified_contents.cc
index 1d84d3a..9677b41 100644
--- a/extensions/browser/verified_contents.cc
+++ b/extensions/browser/verified_contents.cc
@@ -221,7 +221,7 @@
           base::FilePath::FromUTF8Unsafe(file_path_string);
       base::FilePath::StringType lowercase_file_path =
           base::ToLowerASCII(file_path.value());
-      RootHashes::iterator i = verified_contents->root_hashes_.insert(
+      auto i = verified_contents->root_hashes_.insert(
           std::make_pair(lowercase_file_path, std::string()));
       i->second.swap(root_hash);
 
@@ -409,8 +409,7 @@
     const std::string& expected) const {
   std::pair<RootHashes::const_iterator, RootHashes::const_iterator> hashes =
       root_hashes_.equal_range(normalized_relative_path);
-  for (RootHashes::const_iterator iter = hashes.first; iter != hashes.second;
-       ++iter) {
+  for (auto iter = hashes.first; iter != hashes.second; ++iter) {
     if (expected == iter->second)
       return true;
   }
diff --git a/extensions/browser/warning_service.cc b/extensions/browser/warning_service.cc
index 1f5cf12..ea53c8c 100644
--- a/extensions/browser/warning_service.cc
+++ b/extensions/browser/warning_service.cc
@@ -36,8 +36,7 @@
     const std::set<Warning::WarningType>& types) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ExtensionIdSet affected_extensions;
-  for (WarningSet::iterator i = warnings_.begin();
-       i != warnings_.end();) {
+  for (auto i = warnings_.begin(); i != warnings_.end();) {
     if (types.find(i->warning_type()) != types.end()) {
       affected_extensions.insert(i->extension_id());
       warnings_.erase(i++);
@@ -54,8 +53,7 @@
     GetWarningTypesAffectingExtension(const std::string& extension_id) const {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   std::set<Warning::WarningType> result;
-  for (WarningSet::const_iterator i = warnings_.begin();
-       i != warnings_.end(); ++i) {
+  for (auto i = warnings_.cbegin(); i != warnings_.cend(); ++i) {
     if (i->extension_id() == extension_id)
       result.insert(i->warning_type());
   }
@@ -70,8 +68,7 @@
   const ExtensionSet& extension_set =
       ExtensionRegistry::Get(browser_context_)->enabled_extensions();
 
-  for (WarningSet::const_iterator i = warnings_.begin();
-       i != warnings_.end(); ++i) {
+  for (auto i = warnings_.cbegin(); i != warnings_.cend(); ++i) {
     if (i->extension_id() == extension_id)
       result.push_back(i->GetLocalizedMessage(&extension_set));
   }
diff --git a/extensions/common/api/bluetooth/bluetooth_manifest_permission.cc b/extensions/common/api/bluetooth/bluetooth_manifest_permission.cc
index 37fe8e3..e3785397 100644
--- a/extensions/common/api/bluetooth/bluetooth_manifest_permission.cc
+++ b/extensions/common/api/bluetooth/bluetooth_manifest_permission.cc
@@ -95,9 +95,7 @@
     const BluetoothPermissionRequest& request) const {
 
   device::BluetoothUUID param_uuid(request.uuid);
-  for (BluetoothUuidSet::const_iterator it = uuids_.begin();
-       it != uuids_.end();
-       ++it) {
+  for (auto it = uuids_.cbegin(); it != uuids_.cend(); ++it) {
     device::BluetoothUUID uuid(*it);
     if (param_uuid == uuid)
       return true;
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_data.cc b/extensions/common/api/printer_provider/usb_printer_manifest_data.cc
index 500f1f9..5bd9b94 100644
--- a/extensions/common/api/printer_provider/usb_printer_manifest_data.cc
+++ b/extensions/common/api/printer_provider/usb_printer_manifest_data.cc
@@ -8,7 +8,7 @@
 #include <utility>
 
 #include "base/strings/utf_string_conversions.h"
-#include "device/usb/public/cpp/filter_utils.h"
+#include "device/usb/public/cpp/usb_utils.h"
 #include "device/usb/public/mojom/device_manager.mojom.h"
 #include "device/usb/usb_device.h"
 #include "extensions/common/api/extensions_manifest_types.h"
diff --git a/extensions/common/api/sockets/sockets_manifest_permission.cc b/extensions/common/api/sockets/sockets_manifest_permission.cc
index 1affb83..41b58e5 100644
--- a/extensions/common/api/sockets/sockets_manifest_permission.cc
+++ b/extensions/common/api/sockets/sockets_manifest_permission.cc
@@ -77,9 +77,8 @@
     content::SocketPermissionRequest::OperationType operation_type) {
   host_patterns.reset(new SocketHostPatterns());
   host_patterns->as_strings.reset(new std::vector<std::string>());
-  for (SocketPermissionEntrySet::const_iterator it =
-           permission->entries().begin();
-       it != permission->entries().end(); ++it) {
+  for (auto it = permission->entries().cbegin();
+       it != permission->entries().cend(); ++it) {
     if (it->pattern().type == operation_type) {
       host_patterns->as_strings->push_back(it->GetHostPatternAsString());
     }
@@ -200,9 +199,7 @@
 bool SocketsManifestPermission::CheckRequest(
     const Extension* extension,
     const SocketPermissionRequest& request) const {
-  for (SocketPermissionEntrySet::const_iterator it = permissions_.begin();
-       it != permissions_.end();
-       ++it) {
+  for (auto it = permissions_.cbegin(); it != permissions_.cend(); ++it) {
     if (it->Check(request))
       return true;
   }
diff --git a/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc b/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc
index c7b1774..450fead 100644
--- a/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc
+++ b/extensions/common/api/sockets/sockets_manifest_permission_unittest.cc
@@ -99,9 +99,8 @@
   // Note: We use multiset because SocketsManifestPermission does not have to
   // store entries in the order found in the json message.
   std::multiset<CheckFormatEntry> parsed_permissions;
-  for (SocketPermissionEntrySet::const_iterator it =
-           permission->entries().begin();
-       it != permission->entries().end(); ++it) {
+  for (auto it = permission->entries().cbegin();
+       it != permission->entries().cend(); ++it) {
     parsed_permissions.insert(
         CheckFormatEntry(it->pattern().type, it->GetHostPatternAsString()));
   }
diff --git a/extensions/common/event_filter.cc b/extensions/common/event_filter.cc
index 0ee16f77..2b31915 100644
--- a/extensions/common/event_filter.cc
+++ b/extensions/common/event_filter.cc
@@ -122,7 +122,7 @@
 }
 
 std::string EventFilter::RemoveEventMatcher(MatcherID id) {
-  std::map<MatcherID, std::string>::iterator it = id_to_event_name_.find(id);
+  auto it = id_to_event_name_.find(id);
   std::string event_name = it->second;
   // EventMatcherEntry's destructor causes the condition set ids to be removed
   // from url_matcher_.
@@ -153,7 +153,7 @@
       continue;
     }
     MatcherID id = matcher_id->second;
-    EventMatcherMap::const_iterator matcher_entry = matcher_map.find(id);
+    auto matcher_entry = matcher_map.find(id);
     if (matcher_entry == matcher_map.end()) {
       // Matcher must be for a different event.
       continue;
@@ -176,7 +176,7 @@
 
 int EventFilter::GetMatcherCountForEventForTesting(
     const std::string& name) const {
-  EventMatcherMultiMap::const_iterator it = event_matchers_.find(name);
+  auto it = event_matchers_.find(name);
   return it != event_matchers_.end() ? it->second.size() : 0;
 }
 
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc
index 06da0fc..916d5d5 100644
--- a/extensions/common/extension.cc
+++ b/extensions/common/extension.cc
@@ -395,7 +395,7 @@
 Extension::ManifestData* Extension::GetManifestData(const std::string& key)
     const {
   DCHECK(finished_parsing_manifest_ || thread_checker_.CalledOnValidThread());
-  ManifestDataMap::const_iterator iter = manifest_data_.find(key);
+  auto iter = manifest_data_.find(key);
   if (iter != manifest_data_.end())
     return iter->second.get();
   return NULL;
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc
index b8d5b0d..4ba7807 100644
--- a/extensions/common/extension_api.cc
+++ b/extensions/common/extension_api.cc
@@ -173,7 +173,7 @@
     Feature::Context context,
     const GURL& url,
     CheckAliasStatus check_alias) {
-  FeatureProviderMap::iterator provider = dependency_providers_.find("api");
+  auto provider = dependency_providers_.find("api");
   CHECK(provider != dependency_providers_.end());
 
   if (api.IsAvailableToContext(extension, context, url).is_available())
@@ -226,7 +226,7 @@
 base::StringPiece ExtensionAPI::GetSchemaStringPiece(
     const std::string& api_name) {
   DCHECK_EQ(api_name, GetAPINameFromFullName(api_name, nullptr));
-  StringPieceMap::iterator cached = schema_strings_.find(api_name);
+  auto cached = schema_strings_.find(api_name);
   if (cached != schema_strings_.end())
     return cached->second;
 
@@ -247,7 +247,7 @@
   std::string api_name = GetAPINameFromFullName(full_name, &child_name);
 
   const base::DictionaryValue* result = NULL;
-  SchemaMap::iterator maybe_schema = schemas_.find(api_name);
+  auto maybe_schema = schemas_.find(api_name);
   if (maybe_schema != schemas_.end()) {
     result = maybe_schema->second.get();
   } else {
@@ -273,8 +273,7 @@
   std::string feature_name;
   SplitDependencyName(full_name, &feature_type, &feature_name);
 
-  FeatureProviderMap::iterator provider =
-      dependency_providers_.find(feature_type);
+  auto provider = dependency_providers_.find(feature_type);
   if (provider == dependency_providers_.end())
     return NULL;
 
@@ -332,7 +331,7 @@
   if (alias.empty())
     return Feature::Availability(Feature::NOT_PRESENT, "Alias not defined");
 
-  FeatureProviderMap::iterator provider = dependency_providers_.find("api");
+  auto provider = dependency_providers_.find("api");
   CHECK(provider != dependency_providers_.end());
 
   // Check if there is a child feature associated with full name for alias API.
diff --git a/extensions/common/extension_icon_set.cc b/extensions/common/extension_icon_set.cc
index 4c39d492..cb707bf2 100644
--- a/extensions/common/extension_icon_set.cc
+++ b/extensions/common/extension_icon_set.cc
@@ -27,12 +27,11 @@
   // The searches for MATCH_BIGGER and MATCH_SMALLER below rely on the fact that
   // std::map is sorted. This is per the spec, so it should be safe to rely on.
   if (match_type == MATCH_EXACTLY) {
-    IconMap::const_iterator result = map_.find(size);
+    auto result = map_.find(size);
     return result == map_.end() ? base::EmptyString() : result->second;
   } else if (match_type == MATCH_SMALLER) {
-    IconMap::const_reverse_iterator result = map_.rend();
-    for (IconMap::const_reverse_iterator iter = map_.rbegin();
-         iter != map_.rend(); ++iter) {
+    auto result = map_.rend();
+    for (auto iter = map_.rbegin(); iter != map_.rend(); ++iter) {
       if (iter->first <= size) {
         result = iter;
         break;
@@ -41,15 +40,14 @@
     return result == map_.rend() ? base::EmptyString() : result->second;
   } else {
     DCHECK(match_type == MATCH_BIGGER);
-    IconMap::const_iterator result = map_.end();
-    for (IconMap::const_iterator iter = map_.begin(); iter != map_.end();
-         ++iter) {
+    auto result = map_.cend();
+    for (auto iter = map_.cbegin(); iter != map_.cend(); ++iter) {
       if (iter->first >= size) {
         result = iter;
         break;
       }
     }
-    return result == map_.end() ? base::EmptyString() : result->second;
+    return result == map_.cend() ? base::EmptyString() : result->second;
   }
 }
 
@@ -64,8 +62,7 @@
   DCHECK_NE(path[0], '/') <<
       "ExtensionIconSet stores icon paths without leading slash.";
 
-  for (IconMap::const_iterator iter = map_.begin(); iter != map_.end();
-       ++iter) {
+  for (auto iter = map_.cbegin(); iter != map_.cend(); ++iter) {
     if (iter->second == path)
       return iter->first;
   }
diff --git a/extensions/common/extension_l10n_util.cc b/extensions/common/extension_l10n_util.cc
index 1c73ece..2a8fe2c 100644
--- a/extensions/common/extension_l10n_util.cc
+++ b/extensions/common/extension_l10n_util.cc
@@ -411,8 +411,7 @@
   if (!GetValidLocales(locale_path, &valid_locales, error))
     return false;
 
-  for (std::set<std::string>::const_iterator locale = valid_locales.begin();
-       locale != valid_locales.end();
+  for (auto locale = valid_locales.cbegin(); locale != valid_locales.cend();
        ++locale) {
     std::string locale_error;
     std::unique_ptr<base::DictionaryValue> catalog =
diff --git a/extensions/common/extension_messages.cc b/extensions/common/extension_messages.cc
index c27ac18..78e8720 100644
--- a/extensions/common/extension_messages.cc
+++ b/extensions/common/extension_messages.cc
@@ -158,8 +158,7 @@
   if (!ReadParam(m, iter, &patterns))
     return false;
 
-  for (std::set<URLPattern>::iterator i = patterns.begin();
-       i != patterns.end(); ++i)
+  for (auto i = patterns.begin(); i != patterns.end(); ++i)
     p->AddPattern(*i);
   return true;
 }
diff --git a/extensions/common/extension_set.cc b/extensions/common/extension_set.cc
index 6930efb..217c2df 100644
--- a/extensions/common/extension_set.cc
+++ b/extensions/common/extension_set.cc
@@ -115,8 +115,7 @@
 }
 
 const Extension* ExtensionSet::GetHostedAppByURL(const GURL& url) const {
-  for (ExtensionMap::const_iterator iter = extensions_.begin();
-       iter != extensions_.end(); ++iter) {
+  for (auto iter = extensions_.cbegin(); iter != extensions_.cend(); ++iter) {
     if (iter->second->web_extent().MatchesURL(url))
       return iter->second.get();
   }
@@ -126,8 +125,7 @@
 
 const Extension* ExtensionSet::GetHostedAppByOverlappingWebExtent(
     const URLPatternSet& extent) const {
-  for (ExtensionMap::const_iterator iter = extensions_.begin();
-       iter != extensions_.end(); ++iter) {
+  for (auto iter = extensions_.cbegin(); iter != extensions_.cend(); ++iter) {
     if (iter->second->web_extent().OverlapsWith(extent))
       return iter->second.get();
   }
@@ -142,7 +140,7 @@
 }
 
 const Extension* ExtensionSet::GetByID(const std::string& id) const {
-  ExtensionMap::const_iterator i = extensions_.find(id);
+  auto i = extensions_.find(id);
   if (i != extensions_.end())
     return i->second.get();
   else
@@ -151,8 +149,7 @@
 
 ExtensionIdSet ExtensionSet::GetIDs() const {
   ExtensionIdSet ids;
-  for (ExtensionMap::const_iterator it = extensions_.begin();
-       it != extensions_.end(); ++it) {
+  for (auto it = extensions_.cbegin(); it != extensions_.cend(); ++it) {
     ids.insert(it->first);
   }
   return ids;
@@ -162,8 +159,7 @@
   if (url.SchemeIs(kExtensionScheme))
     return true;
 
-  for (ExtensionMap::const_iterator it = extensions_.begin();
-       it != extensions_.end(); ++it) {
+  for (auto it = extensions_.cbegin(); it != extensions_.cend(); ++it) {
     if (it->second->location() == Manifest::COMPONENT &&
         it->second->web_extent().MatchesURL(url))
       return true;
diff --git a/extensions/common/features/complex_feature.cc b/extensions/common/features/complex_feature.cc
index b0a7d05..66b61cb1 100644
--- a/extensions/common/features/complex_feature.cc
+++ b/extensions/common/features/complex_feature.cc
@@ -44,8 +44,7 @@
   if (first_availability.is_available())
     return first_availability;
 
-  for (FeatureList::const_iterator it = features_.begin() + 1;
-       it != features_.end(); ++it) {
+  for (auto it = features_.cbegin() + 1; it != features_.cend(); ++it) {
     Availability availability = (*it)->IsAvailableToManifest(
         hashed_id, type, location, manifest_version, platform);
     if (availability.is_available())
@@ -66,8 +65,7 @@
   if (first_availability.is_available())
     return first_availability;
 
-  for (FeatureList::const_iterator it = features_.begin() + 1;
-       it != features_.end(); ++it) {
+  for (auto it = features_.cbegin() + 1; it != features_.cend(); ++it) {
     Availability availability =
         (*it)->IsAvailableToContext(extension, context, url, platform);
     if (availability.is_available())
@@ -84,8 +82,7 @@
   if (first_availability.is_available())
     return first_availability;
 
-  for (FeatureList::const_iterator iter = features_.begin() + 1;
-       iter != features_.end(); ++iter) {
+  for (auto iter = features_.cbegin() + 1; iter != features_.cend(); ++iter) {
     Availability availability = (*iter)->IsAvailableToEnvironment();
     if (availability.is_available())
       return availability;
@@ -96,9 +93,7 @@
 }
 
 bool ComplexFeature::IsIdInBlocklist(const HashedExtensionId& hashed_id) const {
-  for (FeatureList::const_iterator it = features_.begin();
-       it != features_.end();
-       ++it) {
+  for (auto it = features_.cbegin(); it != features_.cend(); ++it) {
     if ((*it)->IsIdInBlocklist(hashed_id))
       return true;
   }
@@ -106,9 +101,7 @@
 }
 
 bool ComplexFeature::IsIdInAllowlist(const HashedExtensionId& hashed_id) const {
-  for (FeatureList::const_iterator it = features_.begin();
-       it != features_.end();
-       ++it) {
+  for (auto it = features_.cbegin(); it != features_.cend(); ++it) {
     if ((*it)->IsIdInAllowlist(hashed_id))
       return true;
   }
diff --git a/extensions/common/features/feature_provider.cc b/extensions/common/features/feature_provider.cc
index 682a50e..c652fab 100644
--- a/extensions/common/features/feature_provider.cc
+++ b/extensions/common/features/feature_provider.cc
@@ -130,7 +130,7 @@
 }
 
 const Feature* FeatureProvider::GetFeature(const std::string& name) const {
-  FeatureMap::const_iterator iter = features_.find(name);
+  auto iter = features_.find(name);
   if (iter != features_.end())
     return iter->second.get();
   else
diff --git a/extensions/common/manifest_handler.cc b/extensions/common/manifest_handler.cc
index ce46bd8ad..526e9e7b 100644
--- a/extensions/common/manifest_handler.cc
+++ b/extensions/common/manifest_handler.cc
@@ -141,8 +141,7 @@
       handlers_by_priority[priority_map_[handler]] = handler;
     }
   }
-  for (std::map<int, ManifestHandler*>::iterator iter =
-           handlers_by_priority.begin();
+  for (auto iter = handlers_by_priority.begin();
        iter != handlers_by_priority.end(); ++iter) {
     if (!(iter->second)->Parse(extension, error))
       return false;
@@ -163,8 +162,7 @@
       handlers.insert(handler);
     }
   }
-  for (std::set<ManifestHandler*>::iterator iter = handlers.begin();
-       iter != handlers.end(); ++iter) {
+  for (auto iter = handlers.begin(); iter != handlers.end(); ++iter) {
     if (!(*iter)->Validate(extension, error, warnings))
       return false;
   }
diff --git a/extensions/common/manifest_handlers/automation.cc b/extensions/common/manifest_handlers/automation.cc
index 1d076c3..ae3c5fd 100644
--- a/extensions/common/manifest_handlers/automation.cc
+++ b/extensions/common/manifest_handlers/automation.cc
@@ -243,8 +243,7 @@
     } else {
       specified_matches = true;
 
-      for (std::vector<std::string>::iterator it =
-               automation_object.matches->begin();
+      for (auto it = automation_object.matches->begin();
            it != automation_object.matches->end(); ++it) {
         // TODO(aboxhall): Refactor common logic from content_scripts_handler,
         // manifest_url_handler and user_script.cc into a single location and
diff --git a/extensions/common/manifest_handlers/externally_connectable.cc b/extensions/common/manifest_handlers/externally_connectable.cc
index cd1313bb..3d77516 100644
--- a/extensions/common/manifest_handlers/externally_connectable.cc
+++ b/extensions/common/manifest_handlers/externally_connectable.cc
@@ -110,10 +110,8 @@
   URLPatternSet matches;
 
   if (externally_connectable->matches) {
-    for (std::vector<std::string>::iterator it =
-             externally_connectable->matches->begin();
-         it != externally_connectable->matches->end();
-         ++it) {
+    for (auto it = externally_connectable->matches->begin();
+         it != externally_connectable->matches->end(); ++it) {
       // Safe to use SCHEME_ALL here; externally_connectable gives a page ->
       // extension communication path, not the other way.
       URLPattern pattern(URLPattern::SCHEME_ALL);
@@ -165,10 +163,8 @@
   bool all_ids = false;
 
   if (externally_connectable->ids) {
-    for (std::vector<std::string>::iterator it =
-             externally_connectable->ids->begin();
-         it != externally_connectable->ids->end();
-         ++it) {
+    for (auto it = externally_connectable->ids->begin();
+         it != externally_connectable->ids->end(); ++it) {
       if (*it == kAllIds) {
         all_ids = true;
       } else if (crx_file::id_util::IdIsValid(*it)) {
diff --git a/extensions/common/manifest_handlers/requirements_info.cc b/extensions/common/manifest_handlers/requirements_info.cc
index 826e624..0456adb 100644
--- a/extensions/common/manifest_handlers/requirements_info.cc
+++ b/extensions/common/manifest_handlers/requirements_info.cc
@@ -98,7 +98,7 @@
         return false;
       }
 
-      for (base::ListValue::const_iterator feature_iter = features->begin();
+      for (auto feature_iter = features->begin();
            feature_iter != features->end(); ++feature_iter) {
         std::string feature;
         if (feature_iter->GetAsString(&feature)) {
diff --git a/extensions/common/message_bundle.cc b/extensions/common/message_bundle.cc
index f75472b..d77e8ba 100644
--- a/extensions/common/message_bundle.cc
+++ b/extensions/common/message_bundle.cc
@@ -69,8 +69,7 @@
                          std::string* error) {
   dictionary_.clear();
 
-  for (CatalogVector::const_reverse_iterator it = locale_catalogs.rbegin();
-       it != locale_catalogs.rend(); ++it) {
+  for (auto it = locale_catalogs.rbegin(); it != locale_catalogs.rend(); ++it) {
     base::DictionaryValue* catalog = (*it).get();
     for (base::DictionaryValue::Iterator message_it(*catalog);
          !message_it.IsAtEnd(); message_it.Advance()) {
@@ -113,7 +112,7 @@
   }
 
   // Add all reserved messages to the dictionary, but check for collisions.
-  SubstitutionMap::iterator it = append_messages.begin();
+  auto it = append_messages.begin();
   for (; it != append_messages.end(); ++it) {
     if (base::ContainsKey(dictionary_, it->first)) {
       *error = ErrorUtils::FormatErrorMessage(
@@ -330,8 +329,7 @@
 }
 
 L10nMessagesMap* GetL10nMessagesMap(const std::string& extension_id) {
-  ExtensionToL10nMessagesMap::iterator it =
-      g_extension_to_messages_map.Get().messages_map.find(extension_id);
+  auto it = g_extension_to_messages_map.Get().messages_map.find(extension_id);
   if (it != g_extension_to_messages_map.Get().messages_map.end())
     return &(it->second);
 
diff --git a/extensions/common/permissions/permission_message_util.cc b/extensions/common/permissions/permission_message_util.cc
index fb8deb3..026061c 100644
--- a/extensions/common/permissions/permission_message_util.cc
+++ b/extensions/common/permissions/permission_message_util.cc
@@ -76,7 +76,7 @@
     }
 
     // Check if we've already seen this host.
-    HostVector::iterator it = hosts_best_rcd.begin();
+    auto it = hosts_best_rcd.begin();
     for (; it != hosts_best_rcd.end(); ++it) {
       if (it->first == host)
         break;
diff --git a/extensions/common/permissions/permission_set.cc b/extensions/common/permissions/permission_set.cc
index 85e7747..a533286 100644
--- a/extensions/common/permissions/permission_set.cc
+++ b/extensions/common/permissions/permission_set.cc
@@ -17,7 +17,7 @@
 
 void AddPatternsAndRemovePaths(const URLPatternSet& set, URLPatternSet* out) {
   DCHECK(out);
-  for (URLPatternSet::const_iterator i = set.begin(); i != set.end(); ++i) {
+  for (auto i = set.begin(); i != set.end(); ++i) {
     URLPattern p = *i;
     p.SetPath("/*");
     out->AddPattern(p);
diff --git a/extensions/common/permissions/permissions_info.cc b/extensions/common/permissions/permissions_info.cc
index de94f5c..008cd71 100644
--- a/extensions/common/permissions/permissions_info.cc
+++ b/extensions/common/permissions/permissions_info.cc
@@ -32,19 +32,19 @@
 }
 
 const APIPermissionInfo* PermissionsInfo::GetByID(APIPermission::ID id) const {
-  IDMap::const_iterator i = id_map_.find(id);
+  auto i = id_map_.find(id);
   return (i == id_map_.end()) ? nullptr : i->second.get();
 }
 
 const APIPermissionInfo* PermissionsInfo::GetByName(
     const std::string& name) const {
-  NameMap::const_iterator i = name_map_.find(name);
+  auto i = name_map_.find(name);
   return (i == name_map_.end()) ? nullptr : i->second;
 }
 
 APIPermissionSet PermissionsInfo::GetAll() const {
   APIPermissionSet permissions;
-  for (IDMap::const_iterator i = id_map_.begin(); i != id_map_.end(); ++i)
+  for (auto i = id_map_.cbegin(); i != id_map_.cend(); ++i)
     permissions.insert(i->second->id());
   return permissions;
 }
@@ -52,8 +52,7 @@
 APIPermissionSet PermissionsInfo::GetAllByName(
     const std::set<std::string>& permission_names) const {
   APIPermissionSet permissions;
-  for (std::set<std::string>::const_iterator i = permission_names.begin();
-       i != permission_names.end(); ++i) {
+  for (auto i = permission_names.cbegin(); i != permission_names.cend(); ++i) {
     const APIPermissionInfo* permission_info = GetByName(*i);
     if (permission_info)
       permissions.insert(permission_info->id());
@@ -62,7 +61,7 @@
 }
 
 bool PermissionsInfo::HasChildPermissions(const std::string& name) const {
-  NameMap::const_iterator i = name_map_.lower_bound(name + '.');
+  auto i = name_map_.lower_bound(name + '.');
   if (i == name_map_.end()) return false;
   return base::StartsWith(i->first, name + '.', base::CompareCase::SENSITIVE);
 }
diff --git a/extensions/common/url_pattern.cc b/extensions/common/url_pattern.cc
index 1b5a979f..a2046a53 100644
--- a/extensions/common/url_pattern.cc
+++ b/extensions/common/url_pattern.cc
@@ -748,8 +748,7 @@
 
 bool URLPattern::MatchesAnyScheme(
     const std::vector<std::string>& schemes) const {
-  for (std::vector<std::string>::const_iterator i = schemes.begin();
-       i != schemes.end(); ++i) {
+  for (auto i = schemes.cbegin(); i != schemes.cend(); ++i) {
     if (MatchesScheme(*i))
       return true;
   }
@@ -759,8 +758,7 @@
 
 bool URLPattern::MatchesAllSchemes(
     const std::vector<std::string>& schemes) const {
-  for (std::vector<std::string>::const_iterator i = schemes.begin();
-       i != schemes.end(); ++i) {
+  for (auto i = schemes.cbegin(); i != schemes.cend(); ++i) {
     if (!MatchesScheme(*i))
       return false;
   }
diff --git a/extensions/common/url_pattern_set.cc b/extensions/common/url_pattern_set.cc
index 096e941..ccbe34b 100644
--- a/extensions/common/url_pattern_set.cc
+++ b/extensions/common/url_pattern_set.cc
@@ -150,8 +150,7 @@
                          const URLPatternSet& url_pattern_set) {
   out << "{ ";
 
-  std::set<URLPattern>::const_iterator iter =
-      url_pattern_set.patterns().begin();
+  auto iter = url_pattern_set.patterns().cbegin();
   if (!url_pattern_set.patterns().empty()) {
     out << *iter;
     ++iter;
@@ -204,8 +203,7 @@
 }
 
 bool URLPatternSet::Contains(const URLPatternSet& other) const {
-  for (URLPatternSet::const_iterator it = other.begin();
-       it != other.end(); ++it) {
+  for (auto it = other.begin(); it != other.end(); ++it) {
     if (!ContainsPattern(*it))
       return false;
   }
@@ -214,8 +212,7 @@
 }
 
 bool URLPatternSet::ContainsPattern(const URLPattern& pattern) const {
-  for (URLPatternSet::const_iterator it = begin();
-       it != end(); ++it) {
+  for (auto it = begin(); it != end(); ++it) {
     if (it->Contains(pattern))
       return true;
   }
@@ -223,8 +220,8 @@
 }
 
 bool URLPatternSet::MatchesURL(const GURL& url) const {
-  for (URLPatternSet::const_iterator pattern = patterns_.begin();
-       pattern != patterns_.end(); ++pattern) {
+  for (auto pattern = patterns_.cbegin(); pattern != patterns_.cend();
+       ++pattern) {
     if (pattern->MatchesURL(url))
       return true;
   }
@@ -233,7 +230,7 @@
 }
 
 bool URLPatternSet::MatchesAllURLs() const {
-  for (URLPatternSet::const_iterator host = begin(); host != end(); ++host) {
+  for (auto host = begin(); host != end(); ++host) {
     if (host->match_all_urls() ||
         (host->match_subdomains() && host->host().empty()))
       return true;
@@ -242,8 +239,8 @@
 }
 
 bool URLPatternSet::MatchesSecurityOrigin(const GURL& origin) const {
-  for (URLPatternSet::const_iterator pattern = patterns_.begin();
-       pattern != patterns_.end(); ++pattern) {
+  for (auto pattern = patterns_.begin(); pattern != patterns_.end();
+       ++pattern) {
     if (pattern->MatchesSecurityOrigin(origin))
       return true;
   }
@@ -254,10 +251,9 @@
 bool URLPatternSet::OverlapsWith(const URLPatternSet& other) const {
   // Two extension extents overlap if there is any one URL that would match at
   // least one pattern in each of the extents.
-  for (URLPatternSet::const_iterator i = patterns_.begin();
-       i != patterns_.end(); ++i) {
-    for (URLPatternSet::const_iterator j = other.patterns().begin();
-         j != other.patterns().end(); ++j) {
+  for (auto i = patterns_.cbegin(); i != patterns_.cend(); ++i) {
+    for (auto j = other.patterns().cbegin(); j != other.patterns().cend();
+         ++j) {
       if (i->OverlapsWith(*j))
         return true;
     }
@@ -268,8 +264,7 @@
 
 std::unique_ptr<base::ListValue> URLPatternSet::ToValue() const {
   std::unique_ptr<base::ListValue> value(new base::ListValue);
-  for (URLPatternSet::const_iterator i = patterns_.begin();
-       i != patterns_.end(); ++i)
+  for (auto i = patterns_.cbegin(); i != patterns_.cend(); ++i)
     value->AppendIfNotPresent(std::make_unique<base::Value>(i->GetAsString()));
   return value;
 }
@@ -302,9 +297,7 @@
 std::unique_ptr<std::vector<std::string>> URLPatternSet::ToStringVector()
     const {
   std::unique_ptr<std::vector<std::string>> value(new std::vector<std::string>);
-  for (URLPatternSet::const_iterator i = patterns_.begin();
-       i != patterns_.end();
-       ++i) {
+  for (auto i = patterns_.cbegin(); i != patterns_.cend(); ++i) {
     value->push_back(i->GetAsString());
   }
   return value;
diff --git a/extensions/common/user_script.cc b/extensions/common/user_script.cc
index 14349e6..e2babca 100644
--- a/extensions/common/user_script.cc
+++ b/extensions/common/user_script.cc
@@ -25,8 +25,7 @@
 
 bool UrlMatchesGlobs(const std::vector<std::string>* globs,
                      const GURL& url) {
-  for (std::vector<std::string>::const_iterator glob = globs->begin();
-       glob != globs->end(); ++glob) {
+  for (auto glob = globs->cbegin(); glob != globs->cend(); ++glob) {
     if (base::MatchPattern(url.spec(), *glob))
       return true;
   }
@@ -214,8 +213,7 @@
 void UserScript::PickleGlobs(base::Pickle* pickle,
                              const std::vector<std::string>& globs) const {
   pickle->WriteUInt32(globs.size());
-  for (std::vector<std::string>::const_iterator glob = globs.begin();
-       glob != globs.end(); ++glob) {
+  for (auto glob = globs.cbegin(); glob != globs.cend(); ++glob) {
     pickle->WriteString(*glob);
   }
 }
@@ -229,8 +227,8 @@
 void UserScript::PickleURLPatternSet(base::Pickle* pickle,
                                      const URLPatternSet& pattern_list) const {
   pickle->WriteUInt32(pattern_list.patterns().size());
-  for (URLPatternSet::const_iterator pattern = pattern_list.begin();
-       pattern != pattern_list.end(); ++pattern) {
+  for (auto pattern = pattern_list.begin(); pattern != pattern_list.end();
+       ++pattern) {
     pickle->WriteInt(pattern->valid_schemes());
     pickle->WriteString(pattern->GetAsString());
   }
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index a721305..a57ca0f 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -1314,9 +1314,8 @@
 }
 
 bool Dispatcher::IsWithinPlatformApp() {
-  for (std::set<std::string>::iterator iter = active_extension_ids_.begin();
-       iter != active_extension_ids_.end();
-       ++iter) {
+  for (auto iter = active_extension_ids_.begin();
+       iter != active_extension_ids_.end(); ++iter) {
     const Extension* extension =
         RendererExtensionRegistry::Get()->GetByID(*iter);
     if (extension && extension->is_platform_app())
diff --git a/extensions/renderer/extension_throttle_simulation_unittest.cc b/extensions/renderer/extension_throttle_simulation_unittest.cc
index 60c32052..5a16900 100644
--- a/extensions/renderer/extension_throttle_simulation_unittest.cc
+++ b/extensions/renderer/extension_throttle_simulation_unittest.cc
@@ -93,13 +93,11 @@
     TimeTicks start_time = TimeTicks();
     TimeTicks now = start_time;
     while ((now - start_time) <= maximum_simulated_duration) {
-      for (std::vector<Actor*>::iterator it = actors_.begin();
-           it != actors_.end(); ++it) {
+      for (auto it = actors_.begin(); it != actors_.end(); ++it) {
         (*it)->AdvanceTime(now);
       }
 
-      for (std::vector<Actor*>::iterator it = actors_.begin();
-           it != actors_.end(); ++it) {
+      for (auto it = actors_.begin(); it != actors_.end(); ++it) {
         (*it)->PerformAction();
       }
 
diff --git a/extensions/renderer/ipc_message_sender.cc b/extensions/renderer/ipc_message_sender.cc
index e82d208..db9b27cb 100644
--- a/extensions/renderer/ipc_message_sender.cc
+++ b/extensions/renderer/ipc_message_sender.cc
@@ -208,8 +208,7 @@
   }
 
   void SendOnRequestResponseReceivedIPC(int request_id) override {
-    std::map<int, std::string>::iterator iter =
-        request_id_to_guid_.find(request_id);
+    auto iter = request_id_to_guid_.find(request_id);
     DCHECK(iter != request_id_to_guid_.end());
     dispatcher_->Send(new ExtensionHostMsg_DecrementServiceWorkerActivity(
         service_worker_version_id_, iter->second));
diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc
index 73d390c5eb..70e2896 100644
--- a/extensions/renderer/module_system.cc
+++ b/extensions/renderer/module_system.cc
@@ -612,7 +612,7 @@
     return value.As<v8::Object>();
   }
 
-  NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
+  auto i = native_handler_map_.find(native_name);
   if (i == native_handler_map_.end()) {
     Fatal(context_,
           "Couldn't find native for requireNative(" + native_name + ")");
@@ -808,7 +808,7 @@
 }
 
 void ModuleSystem::ClobberExistingNativeHandler(const std::string& name) {
-  NativeHandlerMap::iterator existing_handler = native_handler_map_.find(name);
+  auto existing_handler = native_handler_map_.find(name);
   if (existing_handler != native_handler_map_.end()) {
     clobbered_native_handlers_.push_back(std::move(existing_handler->second));
     native_handler_map_.erase(existing_handler);
diff --git a/extensions/renderer/request_sender.cc b/extensions/renderer/request_sender.cc
index 5c45c68..1705457 100644
--- a/extensions/renderer/request_sender.cc
+++ b/extensions/renderer/request_sender.cc
@@ -48,7 +48,7 @@
 }
 
 std::unique_ptr<PendingRequest> RequestSender::RemoveRequest(int request_id) {
-  PendingRequestMap::iterator i = pending_requests_.find(request_id);
+  auto i = pending_requests_.find(request_id);
   if (i == pending_requests_.end())
     return std::unique_ptr<PendingRequest>();
   std::unique_ptr<PendingRequest> result = std::move(i->second);
@@ -145,8 +145,7 @@
 }
 
 void RequestSender::InvalidateSource(Source* source) {
-  for (PendingRequestMap::iterator it = pending_requests_.begin();
-       it != pending_requests_.end();) {
+  for (auto it = pending_requests_.begin(); it != pending_requests_.end();) {
     if (it->second->source == source)
       pending_requests_.erase(it++);
     else
diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc
index f5b4ed2..5bf8446 100644
--- a/extensions/renderer/script_injection.cc
+++ b/extensions/renderer/script_injection.cc
@@ -56,7 +56,7 @@
 
   int id = 0;
   const std::string& key = injection_host->id().id();
-  IsolatedWorldMap::iterator iter = isolated_worlds.find(key);
+  auto iter = isolated_worlds.find(key);
   if (iter != isolated_worlds.end()) {
     id = iter->second;
   } else {
diff --git a/extensions/renderer/script_injection_manager.cc b/extensions/renderer/script_injection_manager.cc
index baac563..e298137 100644
--- a/extensions/renderer/script_injection_manager.cc
+++ b/extensions/renderer/script_injection_manager.cc
@@ -152,7 +152,7 @@
 
 void ScriptInjectionManager::RFOHelper::DidFailProvisionalLoad(
     const blink::WebURLError& error) {
-  FrameStatusMap::iterator it = manager_->frame_statuses_.find(render_frame());
+  auto it = manager_->frame_statuses_.find(render_frame());
   if (it != manager_->frame_statuses_.end() &&
       it->second == UserScript::DOCUMENT_START) {
     // Since the provisional load failed, the frame stays at its previous loaded
@@ -347,7 +347,7 @@
 void ScriptInjectionManager::StartInjectScripts(
     content::RenderFrame* frame,
     UserScript::RunLocation run_location) {
-  FrameStatusMap::iterator iter = frame_statuses_.find(frame);
+  auto iter = frame_statuses_.find(frame);
   // We also don't execute if we detect that the run location is somehow out of
   // order. This can happen if:
   // - The first run location reported for the frame isn't DOCUMENT_START, or
diff --git a/extensions/renderer/user_script_set.cc b/extensions/renderer/user_script_set.cc
index 40cf7f9..8a755fa 100644
--- a/extensions/renderer/user_script_set.cc
+++ b/extensions/renderer/user_script_set.cc
@@ -242,7 +242,7 @@
 blink::WebString UserScriptSet::GetJsSource(const UserScript::File& file,
                                             bool emulate_greasemonkey) {
   const GURL& url = file.url();
-  std::map<GURL, blink::WebString>::iterator iter = script_sources_.find(url);
+  auto iter = script_sources_.find(url);
   if (iter != script_sources_.end())
     return iter->second;
 
@@ -269,7 +269,7 @@
 
 blink::WebString UserScriptSet::GetCssSource(const UserScript::File& file) {
   const GURL& url = file.url();
-  std::map<GURL, blink::WebString>::iterator iter = script_sources_.find(url);
+  auto iter = script_sources_.find(url);
   if (iter != script_sources_.end())
     return iter->second;
 
diff --git a/extensions/renderer/user_script_set_manager.cc b/extensions/renderer/user_script_set_manager.cc
index 85b6ea6e..60c0b5d 100644
--- a/extensions/renderer/user_script_set_manager.cc
+++ b/extensions/renderer/user_script_set_manager.cc
@@ -65,9 +65,8 @@
     UserScript::RunLocation run_location) {
   static_scripts_.GetInjections(injections, render_frame, tab_id, run_location,
                                 activity_logging_enabled_);
-  for (UserScriptSetMap::iterator it = programmatic_scripts_.begin();
-       it != programmatic_scripts_.end();
-       ++it) {
+  for (auto it = programmatic_scripts_.begin();
+       it != programmatic_scripts_.end(); ++it) {
     it->second->GetInjections(injections, render_frame, tab_id, run_location,
                               activity_logging_enabled_);
   }
@@ -77,9 +76,8 @@
     std::set<std::string>* ids) const {
   DCHECK(ids);
   static_scripts_.GetActiveExtensionIds(ids);
-  for (UserScriptSetMap::const_iterator it = programmatic_scripts_.begin();
-       it != programmatic_scripts_.end();
-       ++it) {
+  for (auto it = programmatic_scripts_.cbegin();
+       it != programmatic_scripts_.cend(); ++it) {
     it->second->GetActiveExtensionIds(ids);
   }
 }
diff --git a/extensions/renderer/v8_schema_registry.cc b/extensions/renderer/v8_schema_registry.cc
index 1410d67..0f5d1eb 100644
--- a/extensions/renderer/v8_schema_registry.cc
+++ b/extensions/renderer/v8_schema_registry.cc
@@ -110,9 +110,7 @@
 
   v8::Local<v8::Array> v8_apis(v8::Array::New(isolate, apis.size()));
   size_t api_index = 0;
-  for (std::vector<std::string>::const_iterator i = apis.begin();
-       i != apis.end();
-       ++i) {
+  for (auto i = apis.cbegin(); i != apis.cend(); ++i) {
     v8_apis->Set(api_index++, GetSchema(*i));
   }
   return handle_scope.Escape(v8_apis);
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 661f757..96f85fa 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -3294,7 +3294,7 @@
 
 buckets {
   name: "luci.chromium.webrtc.fyi"
-  acl_sets: "waterfall"
+  acl_sets: "ci"
 
   swarming {
     hostname: "chromium-swarm.appspot.com"
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index a3ab8c0a..e4aea44 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -946,6 +946,7 @@
   _browserViewWrangler = nil;
 
   [_mainCoordinator stop];
+  _httpProtocolHandlerDelegate.reset();
 
   ios::GetChromeBrowserProvider()
       ->GetMailtoHandlerProvider()
diff --git a/ios/chrome/app/startup/chrome_app_startup_parameters.h b/ios/chrome/app/startup/chrome_app_startup_parameters.h
index f7216ff..1111fd68 100644
--- a/ios/chrome/app/startup/chrome_app_startup_parameters.h
+++ b/ios/chrome/app/startup/chrome_app_startup_parameters.h
@@ -25,6 +25,8 @@
   CALLER_APP_GOOGLE_MAPS,
   CALLER_APP_NOT_AVAILABLE,  // Includes being launched from Smart App Banner.
   CALLER_APP_GOOGLE_CHROME_TODAY_EXTENSION,
+  CALLER_APP_GOOGLE_CHROME_SEARCH_EXTENSION,
+  CALLER_APP_GOOGLE_CHROME_CONTENT_EXTENSION,
   MOBILE_SESSION_CALLER_APP_COUNT,
 };
 
diff --git a/ios/chrome/app/startup/chrome_app_startup_parameters.mm b/ios/chrome/app/startup/chrome_app_startup_parameters.mm
index 371e5cc..0fde383 100644
--- a/ios/chrome/app/startup/chrome_app_startup_parameters.mm
+++ b/ios/chrome/app/startup/chrome_app_startup_parameters.mm
@@ -336,6 +336,12 @@
   if ([_secureSourceApp
           isEqualToString:app_group::kOpenCommandSourceTodayExtension])
     return CALLER_APP_GOOGLE_CHROME_TODAY_EXTENSION;
+  if ([_secureSourceApp
+          isEqualToString:app_group::kOpenCommandSourceSearchExtension])
+    return CALLER_APP_GOOGLE_CHROME_SEARCH_EXTENSION;
+  if ([_secureSourceApp
+          isEqualToString:app_group::kOpenCommandSourceContentExtension])
+    return CALLER_APP_GOOGLE_CHROME_CONTENT_EXTENSION;
 
   if (![_declaredSourceApp length])
     return CALLER_APP_NOT_AVAILABLE;
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index a6cb2dd..c7c2a544 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1536,10 +1536,12 @@
         Passphrase required
       </message>
       <message name="IDS_IOS_SYNC_ENCRYPTION_PASSPHRASE_HINT" desc="The information text on how to reset encryption passphrase for sync, shown on the sync encryption settings [Length: 300em] [iOS only]">
-        To change this setting, <ph name="BEGIN_LINK">BEGIN_LINK</ph>reset sync<ph name="END_LINK">END_LINK</ph>
+        Passphrase encryption doesn’t include payment methods and addresses from Google Pay.
+
+To change this setting, <ph name="BEGIN_LINK">BEGIN_LINK</ph>reset sync<ph name="END_LINK">END_LINK</ph>
       </message>
       <message name="IDS_IOS_SYNC_ENCRYPTION_PASSPHRASE_INFO" desc="The information text for encrypting sync using a passphrase, shown on the passphrase screen [iOS only]">
-        Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, you will need to reset sync. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph>
+        Passphrase encryption doesn’t include payment methods and addresses from Google Pay. Only someone with your passphrase can read your encrypted data. The passphrase is not sent to or stored by Google. If you forget your passphrase or want to change this setting, you will need to reset sync. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph>
       </message>
       <message name="IDS_IOS_SYNC_ENCRYPTION_TITLE" desc="The title for the Sync Encryption item [iOS only]">
         Encryption
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.h b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.h
index abf18e0..f72d10c7 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.h
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.h
@@ -28,6 +28,11 @@
 - (void)setTitle:(NSString*)title;
 - (void)setFavicon:(UIImage*)favicon;
 
+// After this is called, the cell is listening for the
+// UIContentSizeCategoryDidChangeNotification notification and updates its font
+// size to the new category.
+- (void)registerForContentSizeUpdates;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_POPUP_MENU_CELLS_POPUP_MENU_NAVIGATION_ITEM_H_
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm
index 414f05a..0c72f03 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_navigation_item.mm
@@ -57,6 +57,7 @@
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
     cell = [[PopupMenuNavigationCell alloc] init];
+    [cell registerForContentSizeUpdates];
   });
 
   [self configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
@@ -91,7 +92,8 @@
 
     _titleLabel = [[UILabel alloc] init];
     _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
-    _titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+    _titleLabel.font = [self titleFont];
+    _titleLabel.adjustsFontForContentSizeCategory = YES;
 
     UIView* faviconBackground = [[UIView alloc] init];
     faviconBackground.translatesAutoresizingMaskIntoConstraints = NO;
@@ -152,9 +154,31 @@
   }
 }
 
+- (void)registerForContentSizeUpdates {
+  // This is needed because if the cell is static (used for height),
+  // adjustsFontForContentSizeCategory isn't working.
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(preferredContentSizeDidChange:)
+             name:UIContentSizeCategoryDidChangeNotification
+           object:nil];
+}
+
 - (void)prepareForReuse {
   [super prepareForReuse];
   [self setFavicon:nil];
 }
 
+#pragma mark - Private
+
+// Callback when the preferred Content Size change.
+- (void)preferredContentSizeDidChange:(NSNotification*)notification {
+  self.titleLabel.font = [self titleFont];
+}
+
+// Font to be used for the title.
+- (UIFont*)titleFont {
+  return [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h
index eb0d33d..ea80f86 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h
@@ -46,6 +46,11 @@
 // Sets the text of the badge text. Hides the badge text if |badgeText| is nil.
 - (void)setBadgeText:(NSString*)badgeText;
 
+// After this is called, the cell is listening for the
+// UIContentSizeCategoryDidChangeNotification notification and updates its font
+// size to the new category.
+- (void)registerForContentSizeUpdates;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_POPUP_MENU_CELLS_POPUP_MENU_TOOLS_ITEM_H_
diff --git a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm
index dc8e668..383f0bd 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm
+++ b/ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.mm
@@ -27,7 +27,6 @@
 const CGFloat kInnerMargin = 11;
 const CGFloat kMargin = 15;
 const CGFloat kTopMargin = 8;
-const CGFloat kTopMarginBadge = 14;
 const CGFloat kMaxHeight = 100;
 NSString* const kToolsMenuTextBadgeAccessibilityIdentifier =
     @"kToolsMenuTextBadgeAccessibilityIdentifier";
@@ -72,6 +71,7 @@
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
     cell = [[PopupMenuToolsCell alloc] init];
+    [cell registerForContentSizeUpdates];
   });
 
   [self configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
@@ -122,14 +122,21 @@
 
     _titleLabel = [[UILabel alloc] init];
     _titleLabel.numberOfLines = 0;
-    _titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+    _titleLabel.font = [self titleFont];
     [_titleLabel
         setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
                                         forAxis:
                                             UILayoutConstraintAxisHorizontal];
     [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultLow - 1
                                    forAxis:UILayoutConstraintAxisHorizontal];
+    // The compression resistance has to be higher priority than the minimal
+    // height constraint so it can increase the height of the cell to be
+    // displayed on multiple lines.
+    [_titleLabel
+        setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh
+                                        forAxis:UILayoutConstraintAxisVertical];
     _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
+    _titleLabel.adjustsFontForContentSizeCategory = YES;
 
     _imageView = [[UIImageView alloc] init];
     _imageView.translatesAutoresizingMaskIntoConstraints = NO;
@@ -148,14 +155,26 @@
     [self.contentView addSubview:_numberBadgeView];
     [self.contentView addSubview:_textBadgeView];
 
+    [NSLayoutConstraint activateConstraints:@[
+      [_titleLabel.centerYAnchor
+          constraintEqualToAnchor:self.contentView.centerYAnchor],
+      // Align the center of image with the center of the capital letter of the
+      // first line of the title.
+      [_imageView.centerYAnchor
+          constraintEqualToAnchor:_titleLabel.firstBaselineAnchor
+                         constant:-[self titleFont].capHeight / 2.0],
+      [_numberBadgeView.centerYAnchor
+          constraintEqualToAnchor:_imageView.centerYAnchor],
+      [_textBadgeView.centerYAnchor
+          constraintEqualToAnchor:_imageView.centerYAnchor],
+      [self.contentView.heightAnchor
+          constraintGreaterThanOrEqualToConstant:kCellHeight],
+    ]];
     ApplyVisualConstraintsWithMetrics(
         @[
           @"H:|-(margin)-[image(imageLength)]-(innerMargin)-[label]",
           @"H:[numberBadge]-(margin)-|", @"H:[textBadge]-(margin)-|",
-          @"V:|-(topMargin)-[image(imageLength)]",
-          @"V:|-(topMarginBadge)-[numberBadge]",
-          @"V:|-(topMarginBadge)-[textBadge]",
-          @"V:|-(topMargin)-[label]-(topMargin)-|"
+          @"V:|-(>=topMargin)-[label]-(>=topMargin)-|"
         ],
         @{
           @"image" : _imageView,
@@ -167,18 +186,21 @@
           @"margin" : @(kMargin),
           @"innerMargin" : @(kInnerMargin),
           @"topMargin" : @(kTopMargin),
-          @"topMarginBadge" : @(kTopMarginBadge),
           @"imageLength" : @(kImageLength),
         });
 
-    [self.contentView.heightAnchor
-        constraintGreaterThanOrEqualToConstant:kCellHeight]
-        .active = YES;
+    // The height constraint is used to have something as small as possible when
+    // calculating the size of the prototype cell.
+    NSLayoutConstraint* heightConstraint =
+        [self.contentView.heightAnchor constraintEqualToConstant:kCellHeight];
+    heightConstraint.priority = UILayoutPriorityDefaultLow;
+
     NSLayoutConstraint* trailingEdge = [_titleLabel.trailingAnchor
         constraintEqualToAnchor:self.contentView.trailingAnchor
                        constant:-kMargin];
     trailingEdge.priority = UILayoutPriorityDefaultHigh - 2;
-    trailingEdge.active = YES;
+    [NSLayoutConstraint
+        activateConstraints:@[ trailingEdge, heightConstraint ]];
 
     self.isAccessibilityElement = YES;
   }
@@ -240,6 +262,18 @@
   return UIColorFromRGB(kEnabledDefaultColor);
 }
 
+- (void)registerForContentSizeUpdates {
+  // This is needed because if the cell is static (used for height),
+  // adjustsFontForContentSizeCategory isn't working.
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(preferredContentSizeDidChange:)
+             name:UIContentSizeCategoryDidChangeNotification
+           object:nil];
+}
+
+#pragma mark - UIView
+
 - (void)layoutSubviews {
   [super layoutSubviews];
 
@@ -285,6 +319,16 @@
 
 #pragma mark - Private
 
+// Callback when the preferred Content Size change.
+- (void)preferredContentSizeDidChange:(NSNotification*)notification {
+  self.titleLabel.font = [self titleFont];
+}
+
+// Font to be used for the title.
+- (UIFont*)titleFont {
+  return [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+}
+
 // Returns the color of the disabled button's title.
 + (UIColor*)disabledColor {
   static UIColor* systemTintColorForDisabled = nil;
diff --git a/ios/chrome/browser/ui/settings/utils/pref_backed_boolean.mm b/ios/chrome/browser/ui/settings/utils/pref_backed_boolean.mm
index 09e4a37..89c13db 100644
--- a/ios/chrome/browser/ui/settings/utils/pref_backed_boolean.mm
+++ b/ios/chrome/browser/ui/settings/utils/pref_backed_boolean.mm
@@ -12,15 +12,6 @@
 #error "This file requires ARC support."
 #endif
 
-namespace {
-
-// Adaptor function to allow invoking onChange as a base::Closure.
-void OnChange(id<ObservableBoolean> object) {
-  [object.observer booleanDidChange:object];
-}
-
-}  // namespace
-
 @implementation PrefBackedBoolean {
   BooleanPrefMember _pref;
 }
@@ -30,14 +21,14 @@
 - (id)initWithPrefService:(PrefService*)prefs prefName:(const char*)prefName {
   self = [super init];
   if (self) {
-    // Create a base::Closure that calls onChange.
-    // Bind expects a refcounted object but allows us to pass a raw pointer
-    // with Unretained.  Since the closure will be deleted when |_pref| is
-    // deleted, which happens when |self| is deleted, we know |self| will still
-    // be valid when the closure is invoked.
-    base::Closure onChangeClosure =
-        base::Bind(&OnChange, base::Unretained(self));
-    _pref.Init(prefName, prefs, onChangeClosure);
+    // Use weak pointer to prevent circular dependency.
+    __weak PrefBackedBoolean* weakSelf = self;
+    _pref.Init(prefName, prefs, base::BindRepeating(^() {
+                 PrefBackedBoolean* strongSelf = weakSelf;
+                 if (strongSelf) {
+                   [strongSelf.observer booleanDidChange:strongSelf];
+                 }
+               }));
   }
   return self;
 }
diff --git a/media/blink/multibuffer_data_source.cc b/media/blink/multibuffer_data_source.cc
index 69198c9..74ad445 100644
--- a/media/blink/multibuffer_data_source.cc
+++ b/media/blink/multibuffer_data_source.cc
@@ -286,23 +286,8 @@
   return single_origin_;
 }
 
-bool MultibufferDataSource::DidPassCORSAccessCheck() const {
-  if (url_data()->cors_mode() == UrlData::CORS_UNSPECIFIED)
-    return false;
-
-  // If init_cb is set, we know initialization is not finished yet.
-  if (init_cb_)
-    return false;
-  if (failed_)
-    return false;
-  return true;
-}
-
-bool MultibufferDataSource::DidGetOpaqueResponseViaServiceWorker() const {
-  return url_data()->has_opaque_data();
-
-  // TODO(falken): Do we need to do something about |init_cb_| like
-  // in DidPassCORSAccessCheck()?
+bool MultibufferDataSource::IsCorsCrossOrigin() const {
+  return url_data()->is_cors_cross_origin();
 }
 
 void MultibufferDataSource::MediaPlaybackRateChanged(double playback_rate) {
@@ -627,8 +612,6 @@
     // Progress callback might be called after the start callback,
     // make sure that we update single_origin_ now.
     media_log_->SetBooleanProperty("single_origin", single_origin_);
-    media_log_->SetBooleanProperty("passed_cors_access_check",
-                                   DidPassCORSAccessCheck());
     media_log_->SetBooleanProperty("range_header_supported",
                                    url_data()->range_supported());
   }
diff --git a/media/blink/multibuffer_data_source.h b/media/blink/multibuffer_data_source.h
index 19d61eb..4da62a5 100644
--- a/media/blink/multibuffer_data_source.h
+++ b/media/blink/multibuffer_data_source.h
@@ -79,12 +79,9 @@
   // Method called on the render thread.
   bool HasSingleOrigin();
 
-  // Returns true if the media resource passed a CORS access control check.
-  bool DidPassCORSAccessCheck() const;
-
-  // Returns true if a service worker provided the media resource response,
-  // and the response was opaque.
-  bool DidGetOpaqueResponseViaServiceWorker() const;
+  // https://html.spec.whatwg.org/#cors-cross-origin
+  // This must be called after the response arrives.
+  bool IsCorsCrossOrigin() const;
 
   // Notifies changes in playback state for controlling media buffering
   // behavior.
diff --git a/media/blink/multibuffer_data_source_unittest.cc b/media/blink/multibuffer_data_source_unittest.cc
index 284a75df..4b9f83e 100644
--- a/media/blink/multibuffer_data_source_unittest.cc
+++ b/media/blink/multibuffer_data_source_unittest.cc
@@ -1493,35 +1493,104 @@
   Stop();
 }
 
-TEST_F(MultibufferDataSourceTest, DidPassCORSAccessTest) {
+TEST_F(MultibufferDataSourceTest, ResponseTypeBasic) {
   InitializeWithCORS(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
   set_preload(MultibufferDataSource::NONE);
   WebURLResponse response1 =
       response_generator_->GeneratePartial206(0, kDataSize - 1);
-  response1.SetWasFetchedViaServiceWorker(true);
-  std::vector<blink::WebURL> urlList = {GURL(kHttpDifferentOriginUrl)};
-  response1.SetURLListViaServiceWorker(urlList);
-  WebURLResponse response2 =
-      response_generator_->GeneratePartial206(kDataSize, kDataSize * 2 - 1);
+  response1.SetType(network::mojom::FetchResponseType::kBasic);
 
   EXPECT_CALL(host_, SetTotalBytes(kFileSize));
   EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
   EXPECT_CALL(*this, ReadCallback(kDataSize));
 
-  EXPECT_FALSE(data_source_->DidPassCORSAccessCheck());
   Respond(response1);
   ReceiveData(kDataSize);
   ReadAt(0);
   EXPECT_TRUE(loading());
-  EXPECT_TRUE(data_source_->DidPassCORSAccessCheck());
+  EXPECT_FALSE(data_source_->IsCorsCrossOrigin());
 
   FinishLoading();
+}
 
-  // Verify that if reader_ is null, DidPassCORSAccessCheck still returns true.
-  data_source_->Stop();
-  base::RunLoop().RunUntilIdle();
+TEST_F(MultibufferDataSourceTest, ResponseTypeCors) {
+  InitializeWithCORS(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+  set_preload(MultibufferDataSource::NONE);
+  WebURLResponse response1 =
+      response_generator_->GeneratePartial206(0, kDataSize - 1);
+  response1.SetType(network::mojom::FetchResponseType::kCORS);
 
-  EXPECT_TRUE(data_source_->DidPassCORSAccessCheck());
+  EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+  EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+  EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+  Respond(response1);
+  ReceiveData(kDataSize);
+  ReadAt(0);
+  EXPECT_TRUE(loading());
+  EXPECT_FALSE(data_source_->IsCorsCrossOrigin());
+
+  FinishLoading();
+}
+
+TEST_F(MultibufferDataSourceTest, ResponseTypeDefault) {
+  InitializeWithCORS(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+  set_preload(MultibufferDataSource::NONE);
+  WebURLResponse response1 =
+      response_generator_->GeneratePartial206(0, kDataSize - 1);
+  response1.SetType(network::mojom::FetchResponseType::kDefault);
+
+  EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+  EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+  EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+  Respond(response1);
+  ReceiveData(kDataSize);
+  ReadAt(0);
+  EXPECT_TRUE(loading());
+  EXPECT_FALSE(data_source_->IsCorsCrossOrigin());
+
+  FinishLoading();
+}
+
+TEST_F(MultibufferDataSourceTest, ResponseTypeOpaque) {
+  InitializeWithCORS(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+  set_preload(MultibufferDataSource::NONE);
+  WebURLResponse response1 =
+      response_generator_->GeneratePartial206(0, kDataSize - 1);
+  response1.SetType(network::mojom::FetchResponseType::kOpaque);
+
+  EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+  EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+  EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+  Respond(response1);
+  ReceiveData(kDataSize);
+  ReadAt(0);
+  EXPECT_TRUE(loading());
+  EXPECT_TRUE(data_source_->IsCorsCrossOrigin());
+
+  FinishLoading();
+}
+
+TEST_F(MultibufferDataSourceTest, ResponseTypeOpaqueRedirect) {
+  InitializeWithCORS(kHttpUrl, true, UrlData::CORS_ANONYMOUS);
+  set_preload(MultibufferDataSource::NONE);
+  WebURLResponse response1 =
+      response_generator_->GeneratePartial206(0, kDataSize - 1);
+  response1.SetType(network::mojom::FetchResponseType::kOpaqueRedirect);
+
+  EXPECT_CALL(host_, SetTotalBytes(kFileSize));
+  EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize));
+  EXPECT_CALL(*this, ReadCallback(kDataSize));
+
+  Respond(response1);
+  ReceiveData(kDataSize);
+  ReadAt(0);
+  EXPECT_TRUE(loading());
+  EXPECT_TRUE(data_source_->IsCorsCrossOrigin());
+
+  FinishLoading();
 }
 
 TEST_F(MultibufferDataSourceTest, EtagTest) {
diff --git a/media/blink/resource_multibuffer_data_provider.cc b/media/blink/resource_multibuffer_data_provider.cc
index b3872d0..89f1c9e 100644
--- a/media/blink/resource_multibuffer_data_provider.cc
+++ b/media/blink/resource_multibuffer_data_provider.cc
@@ -280,6 +280,8 @@
   int64_t content_length = response.ExpectedContentLength();
   bool end_of_file = false;
   bool do_fail = false;
+  // We get the response type here because aborting the loader may change it.
+  const auto response_type = response.GetType();
   bytes_to_discard_ = 0;
 
   // We make a strong assumption that when we reach here we have either
@@ -333,10 +335,9 @@
         url_data_->url_index()->TryInsert(destination_url_data);
   }
 
-  // This is vital for security! A service worker can respond with a response
-  // from a different origin, so this response type is needed to detect that.
-  destination_url_data->set_has_opaque_data(
-      network::cors::IsCORSCrossOriginResponseType(response.GetType()));
+  // This is vital for security!
+  destination_url_data->set_is_cors_cross_origin(
+      network::cors::IsCORSCrossOriginResponseType(response_type));
 
   if (destination_url_data != url_data_) {
     // At this point, we've encountered a redirect, or found a better url data
diff --git a/media/blink/url_index.cc b/media/blink/url_index.cc
index 6968b19cd..3fb6349 100644
--- a/media/blink/url_index.cc
+++ b/media/blink/url_index.cc
@@ -65,7 +65,6 @@
       length_(kPositionNotSpecified),
       range_supported_(false),
       cacheable_(false),
-      has_opaque_data_(false),
       last_used_(),
       multibuffer_(this, url_index_->block_shift_) {}
 
@@ -103,9 +102,8 @@
       last_modified_ = other->last_modified_;
     }
     bytes_read_from_cache_ += other->bytes_read_from_cache_;
-    // set_has_opaque_data() will not relax from opaque to non-opaque if already
-    // opaque.
-    set_has_opaque_data(other->has_opaque_data_);
+    // is_cors_corss_origin_ will not relax from true to false.
+    set_is_cors_cross_origin(other->is_cors_cross_origin_);
     multibuffer()->MergeFrom(other->multibuffer());
   }
 }
@@ -122,10 +120,10 @@
   }
 }
 
-void UrlData::set_has_opaque_data(bool has_opaque_data) {
-  if (has_opaque_data_)
+void UrlData::set_is_cors_cross_origin(bool is_cors_cross_origin) {
+  if (is_cors_cross_origin_)
     return;
-  has_opaque_data_ = has_opaque_data;
+  is_cors_cross_origin_ = is_cors_cross_origin;
 }
 
 void UrlData::RedirectTo(const scoped_refptr<UrlData>& url_data) {
diff --git a/media/blink/url_index.h b/media/blink/url_index.h
index 77ea0e4d..2c15bc7a 100644
--- a/media/blink/url_index.h
+++ b/media/blink/url_index.h
@@ -125,7 +125,8 @@
   // Returns our url_index.
   UrlIndex* url_index() const { return url_index_; }
 
-  bool has_opaque_data() const { return has_opaque_data_; }
+  // This must be called after the response arrives.
+  bool is_cors_cross_origin() const { return is_cors_cross_origin_; }
 
   // Notifies the url index that this is currently used.
   // The url <-> URLData mapping will be eventually be invalidated if
@@ -145,7 +146,7 @@
   void set_range_supported();
   void set_last_modified(base::Time last_modified);
   void set_etag(const std::string& etag);
-  void set_has_opaque_data(bool has_opaque_data);
+  void set_is_cors_cross_origin(bool is_cors_cross_origin);
 
   // A redirect has occured (or we've found a better UrlData for the same
   // resource).
@@ -238,9 +239,8 @@
   // will not cache this url.
   bool cacheable_;
 
-  // True if a service worker intercepted a request for this resource
-  // and provided an opaque response.
-  bool has_opaque_data_;
+  // https://html.spec.whatwg.org/#cors-cross-origin
+  bool is_cors_cross_origin_ = false;
 
   // Last time some media time used this resource.
   // Note that we use base::Time rather than base::TimeTicks because
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index df23310..cf0857d 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1175,12 +1175,6 @@
       context_support);
 }
 
-bool WebMediaPlayerImpl::DidGetOpaqueResponseFromServiceWorker() const {
-  if (data_source_)
-    return data_source_->DidGetOpaqueResponseViaServiceWorker();
-  return false;
-}
-
 bool WebMediaPlayerImpl::HasSingleSecurityOrigin() const {
   if (demuxer_found_hls_) {
     // HLS manifests might pull segments from a different origin. We can't know
@@ -1193,10 +1187,15 @@
   return true;
 }
 
-bool WebMediaPlayerImpl::DidPassCORSAccessCheck() const {
-  if (data_source_)
-    return data_source_->DidPassCORSAccessCheck();
-  return false;
+bool WebMediaPlayerImpl::WouldTaintOrigin() const {
+  if (!HasSingleSecurityOrigin()) {
+    // When the resource is redirected to another origin we think it as
+    // tainted. This is actually not specified, and is under discussion.
+    // See https://github.com/whatwg/fetch/issues/737.
+    return true;
+  }
+
+  return data_source_ && data_source_->IsCorsCrossOrigin();
 }
 
 double WebMediaPlayerImpl::MediaTimeForTimeValue(double timeValue) const {
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index a5c9ab7..233e37b4 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -188,10 +188,7 @@
 
   blink::WebString GetErrorMessage() const override;
   bool DidLoadingProgress() override;
-
-  bool DidGetOpaqueResponseFromServiceWorker() const override;
-  bool HasSingleSecurityOrigin() const override;
-  bool DidPassCORSAccessCheck() const override;
+  bool WouldTaintOrigin() const override;
 
   double MediaTimeForTimeValue(double timeValue) const override;
 
@@ -332,6 +329,8 @@
   void OnPipelineResumed();
   void OnDemuxerOpened();
 
+  bool HasSingleSecurityOrigin() const;
+
   // Pipeline::Client overrides.
   void OnError(PipelineStatus status) override;
   void OnEnded() override;
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc
index 36dac20..3e94d9a 100644
--- a/media/gpu/android/media_codec_video_decoder.cc
+++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
@@ -155,23 +156,24 @@
   DVLOG(2) << __func__;
   ReleaseCodec();
   codec_allocator_->StopThread(this);
-
-  if (!media_crypto_context_)
-    return;
-
-  // Cancel previously registered callback (if any).
-  media_crypto_context_->SetMediaCryptoReadyCB(
-      MediaCryptoContext::MediaCryptoReadyCB());
-
-  if (cdm_registration_id_)
-    media_crypto_context_->UnregisterPlayer(cdm_registration_id_);
 }
 
 void MediaCodecVideoDecoder::Destroy() {
   DVLOG(1) << __func__;
+
+  if (media_crypto_context_) {
+    // Cancel previously registered callback (if any).
+    media_crypto_context_->SetMediaCryptoReadyCB(base::NullCallback());
+    if (cdm_registration_id_)
+      media_crypto_context_->UnregisterPlayer(cdm_registration_id_);
+    media_crypto_context_ = nullptr;
+    cdm_registration_id_ = 0;
+  }
+
   // Mojo callbacks require that they're run before destruction.
   if (reset_cb_)
     std::move(reset_cb_).Run();
+
   // Cancel callbacks we no longer want.
   codec_allocator_weak_factory_.InvalidateWeakPtrs();
   CancelPendingDecodes(DecodeStatus::ABORTED);
diff --git a/media/gpu/android/media_codec_video_decoder_unittest.cc b/media/gpu/android/media_codec_video_decoder_unittest.cc
index 028a6cf..121ec92f9 100644
--- a/media/gpu/android/media_codec_video_decoder_unittest.cc
+++ b/media/gpu/android/media_codec_video_decoder_unittest.cc
@@ -282,12 +282,13 @@
   base::android::ScopedJavaGlobalRef<jobject> media_crypto_;
   bool require_secure_video_decoder_ = false;
 
+  // This must outlive |mcvd_| .
+  std::unique_ptr<MockMediaCryptoContext> cdm_;
+
   // |mcvd_raw_| lets us call PumpCodec() even after |mcvd_| is dropped, for
   // testing the teardown path.
   MediaCodecVideoDecoder* mcvd_raw_;
   std::unique_ptr<MediaCodecVideoDecoder> mcvd_;
-  // This must outlive |mcvd_| .
-  std::unique_ptr<MockMediaCryptoContext> cdm_;
 };
 
 // Tests which only work for a single codec.
@@ -639,6 +640,46 @@
   testing::Mock::VerifyAndClearExpectations(&reset_cb);
 }
 
+// Makes sure UnregisterPlayer() works with async decoder destruction.
+// Uses VP8 because this is the only codec that could trigger async destruction.
+// See https://crbug.com/893498
+TEST_P(MediaCodecVideoDecoderVp8Test, UnregisterPlayerBeforeAsyncDestruction) {
+  CreateCdm(true, false);
+  EXPECT_CALL(*cdm_, RegisterPlayer(_, _));
+  auto* codec = InitializeFully_OneDecodePending(
+      TestVideoConfig::NormalEncrypted(codec_));
+
+  // Accept the first decode to transition out of the flushed state. This is
+  // necessary to make sure the decoder is destructed asynchronously.
+  codec->AcceptOneInput();
+  PumpCodec();
+
+  // When |mcvd_| is reset, expect that it will unregister itself immediately,
+  // before the decoder is actually destructed, asynchronously.
+  EXPECT_CALL(*cdm_, UnregisterPlayer(MockMediaCryptoContext::kRegistrationId));
+  mcvd_.reset();
+
+  // Make sure the decoder has not been destroyed yet.
+  destruction_observer_->DoNotAllowDestruction();
+}
+
+// A reference test for UnregisterPlayerBeforeAsyncDestruction.
+TEST_P(MediaCodecVideoDecoderVp8Test, UnregisterPlayerBeforeSyncDestruction) {
+  CreateCdm(true, false);
+  EXPECT_CALL(*cdm_, RegisterPlayer(_, _));
+  InitializeFully_OneDecodePending(TestVideoConfig::NormalEncrypted(codec_));
+
+  // Do not attempt any decode to keep the decoder in a clean state. This is
+  // necessary to make sure the decoder is destructed synchronously.
+
+  // When |mcvd_| is reset, expect that it will unregister itself immediately.
+  EXPECT_CALL(*cdm_, UnregisterPlayer(MockMediaCryptoContext::kRegistrationId));
+  mcvd_.reset();
+
+  // Make sure the decoder is now destroyed.
+  destruction_observer_->ExpectDestruction();
+}
+
 TEST_P(MediaCodecVideoDecoderH264Test, ResetDoesNotDrainNonVp8Codecs) {
   auto* codec =
       InitializeFully_OneDecodePending(TestVideoConfig::Large(codec_));
diff --git a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
index 04e1376..936d715 100644
--- a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
@@ -439,8 +439,6 @@
     DVLOGF(3) << "buffer[" << i << "]: picture_id=" << output_record.picture_id;
   }
 
-  DCHECK_EQ(output_queue_->FreeBuffersCount(), 0u);
-
   if (output_mode_ == Config::OutputMode::ALLOCATE) {
     ScheduleDecodeBufferTaskIfNeeded();
   }
diff --git a/net/dns/BUILD.gn b/net/dns/BUILD.gn
index c00a1f16..d70a30f4 100644
--- a/net/dns/BUILD.gn
+++ b/net/dns/BUILD.gn
@@ -166,11 +166,6 @@
     # TODO(crbug.com/874654): Remove once migrated to network service IPC.
     "//components/network_hints/browser",
 
-    # content/public/browser/resource_hints.h
-    # Deprecated and soon to be removed.
-    # TODO(crbug.com/875238): Remove once code is removed.
-    "//content/public/browser:browser_sources",
-
     # headless/lib/browser/headless_url_request_context_getter.cc
     # URLRequestContext creation for headless.
     "//headless",
diff --git a/net/third_party/quic/core/http/quic_headers_stream.cc b/net/third_party/quic/core/http/quic_headers_stream.cc
index b0c914e..45288ef 100644
--- a/net/third_party/quic/core/http/quic_headers_stream.cc
+++ b/net/third_party/quic/core/http/quic_headers_stream.cc
@@ -26,7 +26,7 @@
 QuicHeadersStream::CompressedHeaderInfo::~CompressedHeaderInfo() {}
 
 QuicHeadersStream::QuicHeadersStream(QuicSpdySession* session)
-    : QuicStream(kHeadersStreamId, session, /*is_static=*/true),
+    : QuicStream(kHeadersStreamId, session, /*is_static=*/true, BIDIRECTIONAL),
       spdy_session_(session) {
   // The headers stream is exempt from connection level flow control.
   DisableConnectionFlowControlForThisStream();
diff --git a/net/third_party/quic/core/http/quic_spdy_stream.cc b/net/third_party/quic/core/http/quic_spdy_stream.cc
index fe2c14f..4b7f0c0fd 100644
--- a/net/third_party/quic/core/http/quic_spdy_stream.cc
+++ b/net/third_party/quic/core/http/quic_spdy_stream.cc
@@ -27,7 +27,7 @@
                                                         " ")
 
 QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session)
-    : QuicStream(id, spdy_session, /*is_static=*/false),
+    : QuicStream(id, spdy_session, /*is_static=*/false, BIDIRECTIONAL),
       spdy_session_(spdy_session),
       visitor_(nullptr),
       headers_decompressed_(false),
diff --git a/net/third_party/quic/core/quic_crypto_stream.cc b/net/third_party/quic/core/quic_crypto_stream.cc
index 73d633c..7a34af0 100644
--- a/net/third_party/quic/core/quic_crypto_stream.cc
+++ b/net/third_party/quic/core/quic_crypto_stream.cc
@@ -23,7 +23,7 @@
                                                         " ")
 
 QuicCryptoStream::QuicCryptoStream(QuicSession* session)
-    : QuicStream(kCryptoStreamId, session, /*is_static=*/true) {
+    : QuicStream(kCryptoStreamId, session, /*is_static=*/true, BIDIRECTIONAL) {
   // The crypto stream is exempt from connection level flow control.
   DisableConnectionFlowControlForThisStream();
 }
diff --git a/net/third_party/quic/core/quic_error_codes.cc b/net/third_party/quic/core/quic_error_codes.cc
index a77aa65..9b5db05a 100644
--- a/net/third_party/quic/core/quic_error_codes.cc
+++ b/net/third_party/quic/core/quic_error_codes.cc
@@ -151,6 +151,8 @@
     RETURN_STRING_LITERAL(QUIC_INVALID_MESSAGE_DATA);
     RETURN_STRING_LITERAL(IETF_QUIC_PROTOCOL_VIOLATION);
     RETURN_STRING_LITERAL(QUIC_INVALID_NEW_TOKEN);
+    RETURN_STRING_LITERAL(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM);
+    RETURN_STRING_LITERAL(QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM);
     RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
     // Intentionally have no default case, so we'll break the build
     // if we add errors and don't put them here.
diff --git a/net/third_party/quic/core/quic_error_codes.h b/net/third_party/quic/core/quic_error_codes.h
index 31c3e29..124078e0 100644
--- a/net/third_party/quic/core/quic_error_codes.h
+++ b/net/third_party/quic/core/quic_error_codes.h
@@ -309,8 +309,13 @@
   IETF_QUIC_PROTOCOL_VIOLATION = 113,
   QUIC_INVALID_NEW_TOKEN = 114,
 
+  // Received stream data on a WRITE_UNIDIRECTIONAL stream.
+  QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM = 115,
+  // Try to send stream data on a READ_UNIDIRECTIONAL stream.
+  QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM = 116,
+
   // No error. Used as bound while iterating.
-  QUIC_LAST_ERROR = 115,
+  QUIC_LAST_ERROR = 117,
 };
 // QuicErrorCodes is encoded as a single octet on-the-wire.
 static_assert(static_cast<int>(QUIC_LAST_ERROR) <=
diff --git a/net/third_party/quic/core/quic_session_test.cc b/net/third_party/quic/core/quic_session_test.cc
index 477f0df..bd16d99 100644
--- a/net/third_party/quic/core/quic_session_test.cc
+++ b/net/third_party/quic/core/quic_session_test.cc
@@ -15,6 +15,7 @@
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_stream.h"
 #include "net/third_party/quic/core/quic_utils.h"
+#include "net/third_party/quic/platform/api/quic_arraysize.h"
 #include "net/third_party/quic/platform/api/quic_expect_bug.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_map_util.h"
@@ -23,6 +24,7 @@
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 #include "net/third_party/quic/platform/api/quic_test.h"
+#include "net/third_party/quic/platform/api/quic_test_mem_slice_vector.h"
 #include "net/third_party/quic/test_tools/quic_config_peer.h"
 #include "net/third_party/quic/test_tools/quic_connection_peer.h"
 #include "net/third_party/quic/test_tools/quic_flow_controller_peer.h"
@@ -103,11 +105,13 @@
 
 class TestStream : public QuicStream {
  public:
-  TestStream(QuicStreamId id, QuicSession* session)
-      : QuicStream(id, session, /*is_static=*/false) {}
+  TestStream(QuicStreamId id, QuicSession* session, StreamType type)
+      : QuicStream(id, session, /*is_static=*/false, type) {}
 
   using QuicStream::CloseReadSide;
   using QuicStream::CloseWriteSide;
+  using QuicStream::WriteMemSlices;
+  using QuicStream::WritevData;
 
   void OnDataAvailable() override {}
 
@@ -141,7 +145,8 @@
   }
 
   TestStream* CreateOutgoingDynamicStream() override {
-    TestStream* stream = new TestStream(GetNextOutgoingStreamId(), this);
+    TestStream* stream =
+        new TestStream(GetNextOutgoingStreamId(), this, BIDIRECTIONAL);
     ActivateStream(QuicWrapUnique(stream));
     return stream;
   }
@@ -154,7 +159,7 @@
           ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
       return nullptr;
     } else {
-      TestStream* stream = new TestStream(id, this);
+      TestStream* stream = new TestStream(id, this, BIDIRECTIONAL);
       ActivateStream(QuicWrapUnique(stream));
       return stream;
     }
@@ -215,6 +220,7 @@
     return WritevData(stream, stream->id(), bytes, 0, FIN);
   }
 
+  using QuicSession::ActivateStream;
   using QuicSession::closed_streams;
   using QuicSession::next_outgoing_stream_id;
   using QuicSession::PostProcessAfterData;
@@ -1540,6 +1546,87 @@
   EXPECT_TRUE(session_.closed_streams()->empty());
 }
 
+TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
+  session_.set_writev_consumes_all_data(true);
+  TestStream* stream4 = new TestStream(4, &session_, WRITE_UNIDIRECTIONAL);
+  session_.ActivateStream(QuicWrapUnique(stream4));
+  QuicString body(100, '.');
+  stream4->WriteOrBufferData(body, false, nullptr);
+  EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
+  stream4->WriteOrBufferData(body, true, nullptr);
+  EXPECT_TRUE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
+}
+
+TEST_P(QuicSessionTestServer, ReceivedDataOnWriteUnidirectionalStream) {
+  TestStream* stream4 = new TestStream(4, &session_, WRITE_UNIDIRECTIONAL);
+  session_.ActivateStream(QuicWrapUnique(stream4));
+
+  EXPECT_CALL(
+      *connection_,
+      CloseConnection(QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM, _, _))
+      .Times(1);
+  QuicStreamFrame stream_frame(4, false, 0, 2);
+  session_.OnStreamFrame(stream_frame);
+}
+
+TEST_P(QuicSessionTestServer, ReadUnidirectionalStream) {
+  TestStream* stream4 = new TestStream(4, &session_, READ_UNIDIRECTIONAL);
+  session_.ActivateStream(QuicWrapUnique(stream4));
+  EXPECT_FALSE(stream4->IsWaitingForAcks());
+  // Discard all incoming data.
+  stream4->StopReading();
+
+  QuicString data(100, '.');
+  QuicStreamFrame stream_frame(4, false, 0, data);
+  stream4->OnStreamFrame(stream_frame);
+  EXPECT_TRUE(session_.closed_streams()->empty());
+
+  QuicStreamFrame stream_frame2(4, true, 100, data);
+  stream4->OnStreamFrame(stream_frame2);
+  EXPECT_EQ(1u, session_.closed_streams()->size());
+}
+
+TEST_P(QuicSessionTestServer, WriteOrBufferDataOnReadUnidirectionalStream) {
+  TestStream* stream4 = new TestStream(4, &session_, READ_UNIDIRECTIONAL);
+  session_.ActivateStream(QuicWrapUnique(stream4));
+
+  EXPECT_CALL(*connection_,
+              CloseConnection(
+                  QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
+      .Times(1);
+  QuicString body(100, '.');
+  stream4->WriteOrBufferData(body, false, nullptr);
+}
+
+TEST_P(QuicSessionTestServer, WritevDataOnReadUnidirectionalStream) {
+  TestStream* stream4 = new TestStream(4, &session_, READ_UNIDIRECTIONAL);
+  session_.ActivateStream(QuicWrapUnique(stream4));
+
+  EXPECT_CALL(*connection_,
+              CloseConnection(
+                  QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
+      .Times(1);
+  QuicString body(100, '.');
+  struct iovec iov = {const_cast<char*>(body.data()), body.length()};
+  stream4->WritevData(&iov, 1, false);
+}
+
+TEST_P(QuicSessionTestServer, WriteMemSlicesOnReadUnidirectionalStream) {
+  TestStream* stream4 = new TestStream(4, &session_, READ_UNIDIRECTIONAL);
+  session_.ActivateStream(QuicWrapUnique(stream4));
+
+  EXPECT_CALL(*connection_,
+              CloseConnection(
+                  QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM, _, _))
+      .Times(1);
+  char data[1024];
+  std::vector<std::pair<char*, size_t>> buffers;
+  buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
+  buffers.push_back(std::make_pair(data, QUIC_ARRAYSIZE(data)));
+  QuicTestMemSliceVector vector(buffers);
+  stream4->WriteMemSlices(vector.span(), false);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_stream.cc b/net/third_party/quic/core/quic_stream.cc
index 4948266a1..64a015e 100644
--- a/net/third_party/quic/core/quic_stream.cc
+++ b/net/third_party/quic/core/quic_stream.cc
@@ -45,7 +45,10 @@
 // static
 const SpdyPriority QuicStream::kDefaultPriority;
 
-QuicStream::QuicStream(QuicStreamId id, QuicSession* session, bool is_static)
+QuicStream::QuicStream(QuicStreamId id,
+                       QuicSession* session,
+                       bool is_static,
+                       StreamType type)
     : sequencer_(this),
       id_(id),
       session_(session),
@@ -80,7 +83,15 @@
           session->connection()->helper()->GetStreamSendBufferAllocator()),
       buffered_data_threshold_(GetQuicFlag(FLAGS_quic_buffered_data_threshold)),
       is_static_(is_static),
-      deadline_(QuicTime::Zero()) {
+      deadline_(QuicTime::Zero()),
+      type_(type) {
+  if (type_ == WRITE_UNIDIRECTIONAL) {
+    set_fin_received(true);
+    CloseReadSide();
+  } else if (type_ == READ_UNIDIRECTIONAL) {
+    set_fin_sent(true);
+    CloseWriteSide();
+  }
   SetFromConfig();
   session_->RegisterStreamPriority(id, is_static_, priority_);
 }
@@ -105,6 +116,13 @@
 
   DCHECK(!(read_side_closed_ && write_side_closed_));
 
+  if (type_ == WRITE_UNIDIRECTIONAL) {
+    CloseConnectionWithDetails(
+        QUIC_DATA_RECEIVED_ON_WRITE_UNIDIRECTIONAL_STREAM,
+        "Data received on write unidirectional stream");
+    return;
+  }
+
   bool is_stream_too_long =
       (frame.offset > kMaxStreamLength) ||
       (kMaxStreamLength - frame.offset < frame.data_length);
@@ -251,6 +269,11 @@
   if (write_side_closed_) {
     QUIC_DLOG(ERROR) << ENDPOINT
                      << "Attempt to write when the write side is closed";
+    if (type_ == READ_UNIDIRECTIONAL) {
+      CloseConnectionWithDetails(
+          QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
+          "Try to send data on read unidirectional stream");
+    }
     return;
   }
 
@@ -331,6 +354,11 @@
   if (write_side_closed_) {
     QUIC_DLOG(ERROR) << ENDPOINT << "Stream " << id()
                      << "attempting to write when the write side is closed";
+    if (type_ == READ_UNIDIRECTIONAL) {
+      CloseConnectionWithDetails(
+          QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
+          "Try to send data on read unidirectional stream");
+    }
     return QuicConsumedData(0, false);
   }
 
@@ -395,6 +423,11 @@
   if (write_side_closed_) {
     QUIC_DLOG(ERROR) << ENDPOINT << "Stream " << id()
                      << "attempting to write when the write side is closed";
+    if (type_ == READ_UNIDIRECTIONAL) {
+      CloseConnectionWithDetails(
+          QUIC_TRY_TO_WRITE_DATA_ON_READ_UNIDIRECTIONAL_STREAM,
+          "Try to send data on read unidirectional stream");
+    }
     return consumed_data;
   }
 
diff --git a/net/third_party/quic/core/quic_stream.h b/net/third_party/quic/core/quic_stream.h
index b54dcd2..54c9dc9 100644
--- a/net/third_party/quic/core/quic_stream.h
+++ b/net/third_party/quic/core/quic_stream.h
@@ -58,7 +58,12 @@
   // Creates a new stream with stream_id |id| associated with |session|. If
   // |is_static| is true, then the stream will be given precedence
   // over other streams when determing what streams should write next.
-  QuicStream(QuicStreamId id, QuicSession* session, bool is_static);
+  // |type| indicates whether the stream is bidirectional, read unidirectional
+  // or write unidirectional.
+  QuicStream(QuicStreamId id,
+             QuicSession* session,
+             bool is_static,
+             StreamType type);
   QuicStream(const QuicStream&) = delete;
   QuicStream& operator=(const QuicStream&) = delete;
 
@@ -449,6 +454,10 @@
 
   // If initialized, reset this stream at this deadline.
   QuicTime deadline_;
+
+  // Indicates whether this stream is bidirectional, read unidirectional or
+  // write unidirectional.
+  const StreamType type_;
 };
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_stream_sequencer_test.cc b/net/third_party/quic/core/quic_stream_sequencer_test.cc
index 536a9735..e96b4dd 100644
--- a/net/third_party/quic/core/quic_stream_sequencer_test.cc
+++ b/net/third_party/quic/core/quic_stream_sequencer_test.cc
@@ -36,7 +36,7 @@
 class MockStream : public QuicStream {
  public:
   MockStream(QuicSession* session, QuicStreamId id)
-      : QuicStream(id, session, /*is_static=*/false) {}
+      : QuicStream(id, session, /*is_static=*/false, BIDIRECTIONAL) {}
 
   MOCK_METHOD0(OnFinRead, void());
   MOCK_METHOD0(OnDataAvailable, void());
diff --git a/net/third_party/quic/core/quic_stream_test.cc b/net/third_party/quic/core/quic_stream_test.cc
index 670bd9b..583d90f 100644
--- a/net/third_party/quic/core/quic_stream_test.cc
+++ b/net/third_party/quic/core/quic_stream_test.cc
@@ -44,8 +44,8 @@
 
 class TestStream : public QuicStream {
  public:
-  TestStream(QuicStreamId id, QuicSession* session)
-      : QuicStream(id, session, /*is_static=*/false) {}
+  TestStream(QuicStreamId id, QuicSession* session, StreamType type)
+      : QuicStream(id, session, /*is_static=*/false, type) {}
 
   void OnDataAvailable() override {}
 
@@ -83,7 +83,7 @@
     QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(
         session_->config(), initial_flow_control_window_bytes_);
 
-    stream_ = new TestStream(kTestStreamId, session_.get());
+    stream_ = new TestStream(kTestStreamId, session_.get(), BIDIRECTIONAL);
     // session_ now owns stream_.
     session_->ActivateStream(QuicWrapUnique(stream_));
     // Ignore resetting when session_ is terminated.
diff --git a/net/third_party/quic/core/quic_types.h b/net/third_party/quic/core/quic_types.h
index 00b95e3..eca1d94 100644
--- a/net/third_party/quic/core/quic_types.h
+++ b/net/third_party/quic/core/quic_types.h
@@ -537,6 +537,15 @@
   WRITE_FAILED,    // Trying to write nonexistent data of a stream
 };
 
+enum StreamType {
+  // Bidirectional streams allow for data to be sent in both directions.
+  BIDIRECTIONAL,
+
+  // Unidirectional streams carry data in one direction only.
+  WRITE_UNIDIRECTIONAL,
+  READ_UNIDIRECTIONAL,
+};
+
 }  // namespace quic
 
 #endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_TYPES_H_
diff --git a/net/third_party/quic/quartc/quartc_stream.cc b/net/third_party/quic/quartc/quartc_stream.cc
index c8fed23..3a8257a 100644
--- a/net/third_party/quic/quartc/quartc_stream.cc
+++ b/net/third_party/quic/quartc/quartc_stream.cc
@@ -9,7 +9,7 @@
 namespace quic {
 
 QuartcStream::QuartcStream(QuicStreamId id, QuicSession* session)
-    : QuicStream(id, session, /*is_static=*/false) {
+    : QuicStream(id, session, /*is_static=*/false, BIDIRECTIONAL) {
   sequencer()->set_level_triggered(true);
 }
 
diff --git a/pdf/pdfium/fuzzers/BUILD.gn b/pdf/pdfium/fuzzers/BUILD.gn
index ffac41d..124139e 100644
--- a/pdf/pdfium/fuzzers/BUILD.gn
+++ b/pdf/pdfium/fuzzers/BUILD.gn
@@ -59,23 +59,16 @@
 }
 
 fuzzer_test("pdfium_fuzzer") {
-  sources = [
-    "pdfium_fuzzer.cc",
-    "pdfium_fuzzer_helper.cc",
-    "pdfium_fuzzer_helper.h",
-  ]
+  sources = []
   deps = [
-    "//third_party/pdfium",
-    "//third_party/pdfium:test_support",
-    "//v8",
-    "//v8:v8_libplatform",
-  ]
-  additional_configs = [
-    "//third_party/pdfium:pdfium_core_config",
-    "//v8:external_startup_data",
+    "//third_party/pdfium/testing/fuzzers:pdfium_fuzzer_src",
   ]
   dict = "dicts/pdf.dict"
   seed_corpus = "//third_party/pdfium/testing/resources"
+  deps += [
+    "//third_party/pdfium",
+    "//third_party/pdfium:test_support",
+  ]
 }
 
 fuzzer_test("pdf_cmap_fuzzer") {
@@ -271,20 +264,9 @@
   }
 
   fuzzer_test("pdfium_xfa_fuzzer") {
-    sources = [
-      "pdfium_fuzzer_helper.cc",
-      "pdfium_fuzzer_helper.h",
-      "pdfium_xfa_fuzzer.cc",
-    ]
+    sources = []
     deps = [
-      "//third_party/pdfium",
-      "//third_party/pdfium:test_support",
-      "//v8",
-      "//v8:v8_libplatform",
-    ]
-    additional_configs = [
-      "//third_party/pdfium:pdfium_core_config",
-      "//v8:external_startup_data",
+      "//third_party/pdfium/testing/fuzzers:pdfium_xfa_fuzzer_src",
     ]
     dict = "dicts/pdf.dict"
     seed_corpus = "//third_party/pdfium/testing/resources"
diff --git a/pdf/pdfium/fuzzers/DEPS b/pdf/pdfium/fuzzers/DEPS
deleted file mode 100644
index aca641cc..0000000
--- a/pdf/pdfium/fuzzers/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+third_party/pdfium/testing/test_support.h",
-  "+v8/include/v8-platform.h",
-]
diff --git a/pdf/pdfium/fuzzers/pdfium_fuzzer.cc b/pdf/pdfium/fuzzers/pdfium_fuzzer.cc
deleted file mode 100644
index 1e8d9c2..0000000
--- a/pdf/pdfium/fuzzers/pdfium_fuzzer.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h"
-
-class PDFiumFuzzer : public PDFiumFuzzerHelper {
- public:
-  PDFiumFuzzer() : PDFiumFuzzerHelper() {}
-  ~PDFiumFuzzer() override = default;
-
-  int GetFormCallbackVersion() const override { return 1; }
-};
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  PDFiumFuzzer fuzzer;
-  fuzzer.RenderPdf(reinterpret_cast<const char*>(data), size);
-  return 0;
-}
diff --git a/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.cc b/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.cc
deleted file mode 100644
index a52d4cf..0000000
--- a/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.cc
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This fuzzer is simplified & cleaned up pdfium/samples/pdfium_test.cc
-
-#include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h"
-
-#include <assert.h>
-#include <limits.h>
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _WIN32
-#include <Windows.h>
-#elif defined(__APPLE__)
-#include <mach-o/dyld.h>
-#else  // Linux
-#include <unistd.h>
-#endif  // _WIN32
-
-#include <memory>
-#include <sstream>
-#include <string>
-#include <utility>
-
-#include "base/memory/free_deleter.h"
-#include "third_party/pdfium/public/cpp/fpdf_scopers.h"
-#include "third_party/pdfium/public/fpdf_dataavail.h"
-#include "third_party/pdfium/public/fpdf_text.h"
-#include "third_party/pdfium/testing/test_support.h"
-#include "v8/include/v8-platform.h"
-
-namespace {
-
-int ExampleAppAlert(IPDF_JSPLATFORM*,
-                    FPDF_WIDESTRING,
-                    FPDF_WIDESTRING,
-                    int,
-                    int) {
-  return 0;
-}
-
-int ExampleAppResponse(IPDF_JSPLATFORM*,
-                       FPDF_WIDESTRING question,
-                       FPDF_WIDESTRING title,
-                       FPDF_WIDESTRING default_value,
-                       FPDF_WIDESTRING label,
-                       FPDF_BOOL is_password,
-                       void* response,
-                       int length) {
-  // UTF-16, always LE regardless of platform.
-  uint8_t* ptr = static_cast<uint8_t*>(response);
-  ptr[0] = 'N';
-  ptr[1] = 0;
-  ptr[2] = 'o';
-  ptr[3] = 0;
-  return 4;
-}
-
-void ExampleDocGotoPage(IPDF_JSPLATFORM*, int pageNumber) {}
-
-void ExampleDocMail(IPDF_JSPLATFORM*,
-                    void* mailData,
-                    int length,
-                    FPDF_BOOL UI,
-                    FPDF_WIDESTRING To,
-                    FPDF_WIDESTRING Subject,
-                    FPDF_WIDESTRING CC,
-                    FPDF_WIDESTRING BCC,
-                    FPDF_WIDESTRING Msg) {}
-
-void ExampleUnsupportedHandler(UNSUPPORT_INFO*, int type) {}
-
-FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
-  return true;
-}
-
-void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {}
-
-std::string ProgramPath() {
-  std::string result;
-
-#ifdef _WIN32
-  char path[MAX_PATH];
-  DWORD len = GetModuleFileNameA(NULL, path, MAX_PATH);
-  if (len != 0)
-    result = std::string(path, len);
-#elif defined(__APPLE__)
-  char path[PATH_MAX];
-  unsigned int len = PATH_MAX;
-  if (!_NSGetExecutablePath(path, &len)) {
-    std::unique_ptr<char, base::FreeDeleter> resolved_path(
-        realpath(path, nullptr));
-    if (resolved_path.get())
-      result = std::string(resolved_path.get());
-  }
-#else  // Linux
-  char path[PATH_MAX];
-  ssize_t len = readlink("/proc/self/exe", path, PATH_MAX);
-  if (len > 0)
-    result = std::string(path, len);
-#endif
-  return result;
-}
-
-}  // namespace
-
-PDFiumFuzzerHelper::PDFiumFuzzerHelper() = default;
-
-PDFiumFuzzerHelper::~PDFiumFuzzerHelper() = default;
-
-bool PDFiumFuzzerHelper::OnFormFillEnvLoaded(FPDF_DOCUMENT doc) {
-  return true;
-}
-
-void PDFiumFuzzerHelper::RenderPdf(const char* pBuf, size_t len) {
-  IPDF_JSPLATFORM platform_callbacks;
-  memset(&platform_callbacks, '\0', sizeof(platform_callbacks));
-  platform_callbacks.version = 3;
-  platform_callbacks.app_alert = ExampleAppAlert;
-  platform_callbacks.app_response = ExampleAppResponse;
-  platform_callbacks.Doc_gotoPage = ExampleDocGotoPage;
-  platform_callbacks.Doc_mail = ExampleDocMail;
-
-  FPDF_FORMFILLINFO form_callbacks;
-  memset(&form_callbacks, '\0', sizeof(form_callbacks));
-  form_callbacks.version = GetFormCallbackVersion();
-  form_callbacks.m_pJsPlatform = &platform_callbacks;
-
-  TestLoader loader(pBuf, len);
-  FPDF_FILEACCESS file_access;
-  memset(&file_access, '\0', sizeof(file_access));
-  file_access.m_FileLen = static_cast<unsigned long>(len);
-  file_access.m_GetBlock = TestLoader::GetBlock;
-  file_access.m_Param = &loader;
-
-  FX_FILEAVAIL file_avail;
-  memset(&file_avail, '\0', sizeof(file_avail));
-  file_avail.version = 1;
-  file_avail.IsDataAvail = Is_Data_Avail;
-
-  FX_DOWNLOADHINTS hints;
-  memset(&hints, '\0', sizeof(hints));
-  hints.version = 1;
-  hints.AddSegment = Add_Segment;
-
-  ScopedFPDFAvail pdf_avail(FPDFAvail_Create(&file_avail, &file_access));
-
-  int nRet = PDF_DATA_NOTAVAIL;
-  bool bIsLinearized = false;
-  ScopedFPDFDocument doc;
-  if (FPDFAvail_IsLinearized(pdf_avail.get()) == PDF_LINEARIZED) {
-    doc.reset(FPDFAvail_GetDocument(pdf_avail.get(), nullptr));
-    if (doc) {
-      while (nRet == PDF_DATA_NOTAVAIL)
-        nRet = FPDFAvail_IsDocAvail(pdf_avail.get(), &hints);
-
-      if (nRet == PDF_DATA_ERROR)
-        return;
-
-      nRet = FPDFAvail_IsFormAvail(pdf_avail.get(), &hints);
-      if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL)
-        return;
-
-      bIsLinearized = true;
-    }
-  } else {
-    doc.reset(FPDF_LoadCustomDocument(&file_access, nullptr));
-  }
-
-  if (!doc)
-    return;
-
-  (void)FPDF_GetDocPermissions(doc.get());
-
-  ScopedFPDFFormHandle form(
-      FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks));
-  if (!OnFormFillEnvLoaded(doc.get()))
-    return;
-
-  FPDF_SetFormFieldHighlightColor(form.get(), FPDF_FORMFIELD_UNKNOWN, 0xFFE4DD);
-  FPDF_SetFormFieldHighlightAlpha(form.get(), 100);
-  FORM_DoDocumentJSAction(form.get());
-  FORM_DoDocumentOpenAction(form.get());
-
-  int page_count = FPDF_GetPageCount(doc.get());
-  for (int i = 0; i < page_count; ++i) {
-    if (bIsLinearized) {
-      nRet = PDF_DATA_NOTAVAIL;
-      while (nRet == PDF_DATA_NOTAVAIL)
-        nRet = FPDFAvail_IsPageAvail(pdf_avail.get(), i, &hints);
-
-      if (nRet == PDF_DATA_ERROR)
-        return;
-    }
-    RenderPage(doc.get(), form.get(), i);
-  }
-  FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC);
-}
-
-bool PDFiumFuzzerHelper::RenderPage(FPDF_DOCUMENT doc,
-                                    FPDF_FORMHANDLE form,
-                                    const int page_index) {
-  ScopedFPDFPage page(FPDF_LoadPage(doc, page_index));
-  if (!page)
-    return false;
-
-  ScopedFPDFTextPage text_page(FPDFText_LoadPage(page.get()));
-  FORM_OnAfterLoadPage(page.get(), form);
-  FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_OPEN);
-
-  const double scale = 1.0;
-  int width = static_cast<int>(FPDF_GetPageWidth(page.get()) * scale);
-  int height = static_cast<int>(FPDF_GetPageHeight(page.get()) * scale);
-  ScopedFPDFBitmap bitmap(FPDFBitmap_Create(width, height, 0));
-  if (bitmap) {
-    FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, 0xFFFFFFFF);
-    FPDF_RenderPageBitmap(bitmap.get(), page.get(), 0, 0, width, height, 0, 0);
-    FPDF_FFLDraw(form, bitmap.get(), page.get(), 0, 0, width, height, 0, 0);
-  }
-  FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_CLOSE);
-  FORM_OnBeforeClosePage(page.get(), form);
-  return !!bitmap;
-}
-
-// Initialize the library once for all runs of the fuzzer.
-struct TestCase {
-  TestCase() {
-#ifdef V8_USE_EXTERNAL_STARTUP_DATA
-    platform = InitializeV8ForPDFiumWithStartupData(
-        ProgramPath(), "", &natives_blob, &snapshot_blob);
-#else
-    platform = InitializeV8ForPDFium(ProgramPath());
-#endif
-
-    memset(&config, '\0', sizeof(config));
-    config.version = 2;
-    config.m_pUserFontPaths = nullptr;
-    config.m_pIsolate = nullptr;
-    config.m_v8EmbedderSlot = 0;
-    FPDF_InitLibraryWithConfig(&config);
-
-    memset(&unsupport_info, '\0', sizeof(unsupport_info));
-    unsupport_info.version = 1;
-    unsupport_info.FSDK_UnSupport_Handler = ExampleUnsupportedHandler;
-    FSDK_SetUnSpObjProcessHandler(&unsupport_info);
-  }
-
-  std::unique_ptr<v8::Platform> platform;
-  v8::StartupData natives_blob;
-  v8::StartupData snapshot_blob;
-  FPDF_LIBRARY_CONFIG config;
-  UNSUPPORT_INFO unsupport_info;
-};
-
-static TestCase* test_case = new TestCase();
diff --git a/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h b/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h
deleted file mode 100644
index 8a3fe8ca..0000000
--- a/pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PDF_PDFIUM_FUZZERS_PDFIUM_FUZZER_HELPER_H_
-#define PDF_PDFIUM_FUZZERS_PDFIUM_FUZZER_HELPER_H_
-
-// This fuzzer is simplified & cleaned up pdfium/samples/pdfium_test.cc
-
-#include "third_party/pdfium/public/fpdf_ext.h"
-#include "third_party/pdfium/public/fpdf_formfill.h"
-#include "third_party/pdfium/public/fpdfview.h"
-#include "v8/include/v8.h"
-
-class PDFiumFuzzerHelper {
- public:
-  virtual ~PDFiumFuzzerHelper();
-
-  void RenderPdf(const char* pBuf, size_t len);
-
-  virtual int GetFormCallbackVersion() const = 0;
-  virtual bool OnFormFillEnvLoaded(FPDF_DOCUMENT doc);
-
- protected:
-  PDFiumFuzzerHelper();
-
- private:
-  bool RenderPage(FPDF_DOCUMENT doc,
-                  FPDF_FORMHANDLE form,
-                  const int page_index);
-};
-
-#endif  // PDF_PDFIUM_FUZZERS_PDFIUM_FUZZER_HELPER_H_
diff --git a/pdf/pdfium/fuzzers/pdfium_xfa_fuzzer.cc b/pdf/pdfium/fuzzers/pdfium_xfa_fuzzer.cc
deleted file mode 100644
index bac055c..0000000
--- a/pdf/pdfium/fuzzers/pdfium_xfa_fuzzer.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "pdf/pdfium/fuzzers/pdfium_fuzzer_helper.h"
-
-class PDFiumXFAFuzzer : public PDFiumFuzzerHelper {
- public:
-  PDFiumXFAFuzzer() : PDFiumFuzzerHelper() {}
-  ~PDFiumXFAFuzzer() override {}
-
-  int GetFormCallbackVersion() const override { return 2; }
-
-  // Return false if XFA doesn't load as otherwise we're duplicating the work
-  // done by the non-xfa fuzzer.
-  bool OnFormFillEnvLoaded(FPDF_DOCUMENT doc) override {
-    int form_type = FPDF_GetFormType(doc);
-    if (form_type != FORMTYPE_XFA_FULL && form_type != FORMTYPE_XFA_FOREGROUND)
-      return false;
-    return FPDF_LoadXFA(doc);
-  }
-};
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  PDFiumXFAFuzzer fuzzer;
-  fuzzer.RenderPdf(reinterpret_cast<const char*>(data), size);
-  return 0;
-}
diff --git a/ppapi/tests/test_tcp_server_socket_private.cc b/ppapi/tests/test_tcp_server_socket_private.cc
index 7d4e7dd..1ad8994 100644
--- a/ppapi/tests/test_tcp_server_socket_private.cc
+++ b/ppapi/tests/test_tcp_server_socket_private.cc
@@ -18,6 +18,16 @@
 using pp::TCPServerSocketPrivate;
 using pp::TCPSocketPrivate;
 
+namespace {
+
+// Used by pp::CompletionCallbacks that want to delete a PP_Resource, passed as
+// |user_data|, on completion.
+void DeleteResource(void* user_data, int32_t flags) {
+  delete reinterpret_cast<PP_Resource*>(user_data);
+}
+
+}  // namespace
+
 REGISTER_TEST_CASE(TCPServerSocketPrivate);
 
 TestTCPServerSocketPrivate::TestTCPServerSocketPrivate(
@@ -58,7 +68,9 @@
   RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, Backlog, filter);
 
   RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, ListenFails, filter);
+  RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, ListenHangs, filter);
   RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, AcceptFails, filter);
+  RUN_CALLBACK_TEST(TestTCPServerSocketPrivate, AcceptHangs, filter);
 }
 
 std::string TestTCPServerSocketPrivate::GetLocalAddress(
@@ -304,6 +316,18 @@
   PASS();
 }
 
+std::string TestTCPServerSocketPrivate::TestListenHangs() {
+  TCPServerSocketPrivate socket(instance_);
+
+  uint8_t localhost_ip[4] = {127, 0, 0, 1};
+  PP_NetAddress_Private ipv4;
+  ASSERT_TRUE(
+      NetAddressPrivate::CreateFromIPv4Address(localhost_ip, 80, &ipv4));
+  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+  socket.Listen(&ipv4, 2 /* backlog */, DoNothingCallback());
+  PASS();
+}
+
 std::string TestTCPServerSocketPrivate::TestAcceptFails() {
   TCPServerSocketPrivate socket(instance_);
   uint8_t localhost_ip[4] = {127, 0, 0, 1};
@@ -325,3 +349,22 @@
 
   PASS();
 }
+
+std::string TestTCPServerSocketPrivate::TestAcceptHangs() {
+  TCPServerSocketPrivate socket(instance_);
+  uint8_t localhost_ip[4] = {127, 0, 0, 1};
+  PP_NetAddress_Private ipv4;
+  ASSERT_TRUE(
+      NetAddressPrivate::CreateFromIPv4Address(localhost_ip, 80, &ipv4));
+  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+  callback.WaitForResult(
+      socket.Listen(&ipv4, 2 /* backlog */, callback.GetCallback()));
+  CHECK_CALLBACK_BEHAVIOR(callback);
+  ASSERT_EQ(PP_OK, callback.result());
+
+  PP_Resource* resource = new PP_Resource();
+  socket.Accept(resource,
+                pp::CompletionCallback(&DeleteResource, resource,
+                                       PP_COMPLETIONCALLBACK_FLAG_OPTIONAL));
+  PASS();
+}
diff --git a/ppapi/tests/test_tcp_server_socket_private.h b/ppapi/tests/test_tcp_server_socket_private.h
index b371389..fcde64dc3 100644
--- a/ppapi/tests/test_tcp_server_socket_private.h
+++ b/ppapi/tests/test_tcp_server_socket_private.h
@@ -53,10 +53,14 @@
   std::string TestListen();
   std::string TestBacklog();
 
-  // The higher level test fixture must configure the corresponding events to
-  // fail with PP_ERROR_FAILED.
+  // The higher level test fixture is responsible for making socket methods
+  // behave in the expected manner.  The *Fails tests expect the specified event
+  // to fail with PP_ERROR_FAILED, and the *Hangs tests expect the specified
+  // operation to never complete, at least until teardown starts.
   std::string TestListenFails();
+  std::string TestListenHangs();
   std::string TestAcceptFails();
+  std::string TestAcceptHangs();
 
   std::string host_;
   uint16_t port_;
diff --git a/ppapi/tests/test_tcp_socket.cc b/ppapi/tests/test_tcp_socket.cc
index cd227677..8d309294 100644
--- a/ppapi/tests/test_tcp_socket.cc
+++ b/ppapi/tests/test_tcp_socket.cc
@@ -65,6 +65,7 @@
   RUN_CALLBACK_TEST(TestTCPSocket, UnexpectedCalls, filter);
 
   RUN_CALLBACK_TEST(TestTCPSocket, ConnectFails, filter);
+  RUN_CALLBACK_TEST(TestTCPSocket, ConnectHangs, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, WriteFails, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, ReadFails, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, SetSendBufferSizeFails, filter);
@@ -72,11 +73,15 @@
   RUN_CALLBACK_TEST(TestTCPSocket, SetNoDelayFails, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, BindFailsConnectSucceeds, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, BindFails, filter);
+  RUN_CALLBACK_TEST(TestTCPSocket, BindHangs, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, ListenFails, filter);
+  RUN_CALLBACK_TEST(TestTCPSocket, ListenHangs, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, AcceptFails, filter);
+  RUN_CALLBACK_TEST(TestTCPSocket, AcceptHangs, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, AcceptedSocketWriteFails, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, AcceptedSocketReadFails, filter);
   RUN_CALLBACK_TEST(TestTCPSocket, BindConnectFails, filter);
+  RUN_CALLBACK_TEST(TestTCPSocket, BindConnectHangs, filter);
 }
 
 std::string TestTCPSocket::TestConnect() {
@@ -495,6 +500,13 @@
   PASS();
 }
 
+std::string TestTCPSocket::TestConnectHangs() {
+  pp::TCPSocket socket(instance_);
+  TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+  socket.Connect(test_server_addr_, DoNothingCallback());
+  PASS();
+}
+
 std::string TestTCPSocket::TestWriteFails() {
   pp::TCPSocket socket(instance_);
   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
@@ -623,6 +635,12 @@
   PASS();
 }
 
+std::string TestTCPSocket::TestBindHangs() {
+  pp::TCPSocket socket(instance_);
+  socket.Bind(test_server_addr_, DoNothingCallback());
+  PASS();
+}
+
 std::string TestTCPSocket::TestListenFails() {
   pp::TCPSocket socket(instance_);
   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
@@ -643,6 +661,19 @@
   PASS();
 }
 
+std::string TestTCPSocket::TestListenHangs() {
+  pp::TCPSocket socket(instance_);
+  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+  // The address doesn't matter here, other than that it should be valid.
+  callback.WaitForResult(
+      socket.Bind(test_server_addr_, callback.GetCallback()));
+  CHECK_CALLBACK_BEHAVIOR(callback);
+  ASSERT_EQ(PP_OK, callback.result());
+
+  socket.Listen(2 /* backlog */, DoNothingCallback());
+  PASS();
+}
+
 std::string TestTCPSocket::TestAcceptFails() {
   pp::TCPSocket socket(instance_);
   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
@@ -666,6 +697,24 @@
   PASS();
 }
 
+std::string TestTCPSocket::TestAcceptHangs() {
+  pp::TCPSocket socket(instance_);
+  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+  // The address doesn't matter here, other than that it should be valid.
+  callback.WaitForResult(
+      socket.Bind(test_server_addr_, callback.GetCallback()));
+  CHECK_CALLBACK_BEHAVIOR(callback);
+  ASSERT_EQ(PP_OK, callback.result());
+
+  callback.WaitForResult(
+      socket.Listen(2 /* backlog */, callback.GetCallback()));
+  CHECK_CALLBACK_BEHAVIOR(callback);
+  ASSERT_EQ(PP_OK, callback.result());
+
+  socket.Accept(DoNothingCallbackWithOutput<pp::TCPSocket>());
+  PASS();
+}
+
 std::string TestTCPSocket::TestAcceptedSocketWriteFails() {
   pp::TCPSocket socket(instance_);
   TestCompletionCallback callback(instance_->pp_instance(), callback_type());
@@ -770,6 +819,18 @@
   PASS();
 }
 
+std::string TestTCPSocket::TestBindConnectHangs() {
+  pp::TCPSocket socket(instance_);
+  TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+
+  cb.WaitForResult(socket.Bind(test_server_addr_, cb.GetCallback()));
+  CHECK_CALLBACK_BEHAVIOR(cb);
+  ASSERT_EQ(PP_OK, cb.result());
+
+  socket.Connect(test_server_addr_, DoNothingCallback());
+  PASS();
+}
+
 std::string TestTCPSocket::ReadFirstLineFromSocket(pp::TCPSocket* socket,
                                                    std::string* s) {
   char buffer[1000];
diff --git a/ppapi/tests/test_tcp_socket.h b/ppapi/tests/test_tcp_socket.h
index 0a0e206..265f021 100644
--- a/ppapi/tests/test_tcp_socket.h
+++ b/ppapi/tests/test_tcp_socket.h
@@ -35,10 +35,12 @@
   std::string TestInterface_1_0();
   std::string TestUnexpectedCalls();
 
-  // The higher level test fixture is responsible for making the appropriate
-  // call in these tests fail with PP_ERROR_FAILED, and all prior events
-  // succeed.
+  // The higher level test fixture is responsible for making socket methods
+  // behave in the expected manner.  The *Fails tests expect the specified even
+  // to fail with PP_ERROR_FAILED, and the *Hangs test expect the specified
+  // operation to never complete, at least until teardown starts.
   std::string TestConnectFails();
+  std::string TestConnectHangs();
   std::string TestWriteFails();
   std::string TestReadFails();
   std::string TestSetSendBufferSizeFails();
@@ -49,11 +51,15 @@
   // This is needed in addition to the above test in the case where a bind
   // failure is simulated in a way that also closes the NetworkContext pipe.
   std::string TestBindFails();
+  std::string TestBindHangs();
   std::string TestListenFails();
+  std::string TestListenHangs();
   std::string TestAcceptFails();
+  std::string TestAcceptHangs();
   std::string TestAcceptedSocketWriteFails();
   std::string TestAcceptedSocketReadFails();
   std::string TestBindConnectFails();
+  std::string TestBindConnectHangs();
 
   std::string ReadFirstLineFromSocket(pp::TCPSocket* socket, std::string* s);
   std::string ReadFirstLineFromSocket_1_0(PP_Resource socket,
diff --git a/ppapi/tests/test_tcp_socket_private.cc b/ppapi/tests/test_tcp_socket_private.cc
index 5037d0b..8f9e29a 100644
--- a/ppapi/tests/test_tcp_socket_private.cc
+++ b/ppapi/tests/test_tcp_socket_private.cc
@@ -58,6 +58,7 @@
   RUN_CALLBACK_TEST(TestTCPSocketPrivate, LargeRead, filter);
 
   RUN_CALLBACK_TEST(TestTCPSocketPrivate, SSLHandshakeFails, filter);
+  RUN_CALLBACK_TEST(TestTCPSocketPrivate, SSLHandshakeHangs, filter);
   RUN_CALLBACK_TEST(TestTCPSocketPrivate, SSLWriteFails, filter);
   RUN_CALLBACK_TEST(TestTCPSocketPrivate, SSLReadFails, filter);
 }
@@ -244,6 +245,18 @@
   PASS();
 }
 
+std::string TestTCPSocketPrivate::TestSSLHandshakeHangs() {
+  pp::TCPSocketPrivate socket(instance_);
+  TestCompletionCallback cb(instance_->pp_instance(), callback_type());
+
+  cb.WaitForResult(socket.Connect("foo.test", 443, cb.GetCallback()));
+  CHECK_CALLBACK_BEHAVIOR(cb);
+  ASSERT_EQ(PP_OK, cb.result());
+
+  socket.SSLHandshake("foo.test", 443, DoNothingCallback());
+  PASS();
+}
+
 std::string TestTCPSocketPrivate::TestSSLWriteFails() {
   pp::TCPSocketPrivate socket(instance_);
   TestCompletionCallback cb(instance_->pp_instance(), callback_type());
diff --git a/ppapi/tests/test_tcp_socket_private.h b/ppapi/tests/test_tcp_socket_private.h
index 13fa1cf..f76c622 100644
--- a/ppapi/tests/test_tcp_socket_private.h
+++ b/ppapi/tests/test_tcp_socket_private.h
@@ -30,10 +30,12 @@
   std::string TestSetOption();
   std::string TestLargeRead();
 
-  // The higher level test fixture is responsible for making the appropriate
-  // call in these tests fail with PP_ERROR_FAILED, and all prior events
-  // succeed.
+  // The higher level test fixture is responsible for making socket methods
+  // behave in the expected manner.  The *Fails tests expect the specified event
+  // to fail with PP_ERROR_FAILED, and the *Hangs test expects the specified
+  // operation to never complete, at least until teardown starts.
   std::string TestSSLHandshakeFails();
+  std::string TestSSLHandshakeHangs();
   std::string TestSSLWriteFails();
   std::string TestSSLReadFails();
 
diff --git a/ppapi/tests/test_utils.cc b/ppapi/tests/test_utils.cc
index e091e68c..af5de51b 100644
--- a/ppapi/tests/test_utils.cc
+++ b/ppapi/tests/test_utils.cc
@@ -32,6 +32,8 @@
   return data.integer8[0] == 1;
 }
 
+void DoNothing(void* user_data, int32_t result) {}
+
 }  // namespace
 
 const int kActionTimeoutMs = 10000;
@@ -272,6 +274,11 @@
   static_cast<NestedEvent*>(event)->SignalOnMainThread();
 }
 
+pp::CompletionCallback DoNothingCallback() {
+  return pp::CompletionCallback(&DoNothing, NULL,
+                                PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
+}
+
 TestCompletionCallback::TestCompletionCallback(PP_Instance instance)
     : wait_for_result_called_(false),
       have_result_(false),
diff --git a/ppapi/tests/test_utils.h b/ppapi/tests/test_utils.h
index d2e641a..1611b99 100644
--- a/ppapi/tests/test_utils.h
+++ b/ppapi/tests/test_utils.h
@@ -95,6 +95,30 @@
   NestedEvent& operator=(const NestedEvent&);
 };
 
+// Returns a callback that does nothing, so can be invoked when the current
+// function is out of scope, unlike TestCompletionCallback.
+pp::CompletionCallback DoNothingCallback();
+
+template <typename OutputT>
+void DeleteStorage(void* user_data, int32_t flags) {
+  typename pp::CompletionCallbackWithOutput<OutputT>::OutputStorageType*
+      storage = reinterpret_cast<typename pp::CompletionCallbackWithOutput<
+          OutputT>::OutputStorageType*>(user_data);
+  delete storage;
+}
+
+// Same as DoNothingCallback(), but with an OutputStorageType, which it deletes
+// when the callback is invoked.
+template <typename OutputT>
+pp::CompletionCallbackWithOutput<OutputT> DoNothingCallbackWithOutput() {
+  typename pp::CompletionCallbackWithOutput<OutputT>::OutputStorageType*
+      storage = new
+      typename pp::CompletionCallbackWithOutput<OutputT>::OutputStorageType();
+  return pp::CompletionCallbackWithOutput<OutputT>(
+      &DeleteStorage<OutputT>, storage, PP_COMPLETIONCALLBACK_FLAG_OPTIONAL,
+      storage);
+}
+
 enum CallbackType { PP_REQUIRED, PP_OPTIONAL, PP_BLOCKING };
 class TestCompletionCallback {
  public:
diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h
index 23cf139..f31dc67d 100644
--- a/printing/backend/win_helper.h
+++ b/printing/backend/win_helper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -8,6 +8,13 @@
 #include <objidl.h>
 #include <prntvpt.h>
 #include <winspool.h>
+
+// Important to include wincrypt_shim.h before xpsprint.h since
+// xpsprint.h includes <wincrypt.h> (xpsprint.h -> msopc.h ->
+// wincrypt.h) which in its normal state is incompatible with
+// OpenSSL/BoringSSL.
+#include "base/win/wincrypt_shim.h"
+
 #include <xpsprint.h>
 
 #include <memory>
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn
index 13b8aba7..b6b22f4 100644
--- a/services/device/BUILD.gn
+++ b/services/device/BUILD.gn
@@ -27,6 +27,8 @@
 
   deps = [
     "//base",
+    "//device/usb/mojo",
+    "//device/usb/public/mojom",
     "//services/device/fingerprint",
     "//services/device/generic_sensor",
     "//services/device/geolocation",
diff --git a/services/device/device_service.cc b/services/device/device_service.cc
index f827384..34416635 100644
--- a/services/device/device_service.cc
+++ b/services/device/device_service.cc
@@ -11,6 +11,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "device/usb/mojo/device_manager_impl.h"
 #include "mojo/public/cpp/system/message_pipe.h"
 #include "services/device/bluetooth/bluetooth_system_factory.h"
 #include "services/device/fingerprint/fingerprint.h"
@@ -141,6 +142,8 @@
                  base::Unretained(this)));
   registry_.AddInterface<mojom::SerialIoHandler>(base::Bind(
       &DeviceService::BindSerialIoHandlerRequest, base::Unretained(this)));
+  registry_.AddInterface<mojom::UsbDeviceManager>(base::Bind(
+      &DeviceService::BindUsbDeviceManagerRequest, base::Unretained(this)));
 
 #if defined(OS_ANDROID)
   registry_.AddInterface(GetJavaInterfaceProvider()
@@ -320,6 +323,14 @@
 #endif
 }
 
+void DeviceService::BindUsbDeviceManagerRequest(
+    mojom::UsbDeviceManagerRequest request) {
+  if (!usb_device_manager_)
+    usb_device_manager_ = std::make_unique<usb::DeviceManagerImpl>();
+
+  usb_device_manager_->AddBinding(std::move(request));
+}
+
 #if defined(OS_ANDROID)
 service_manager::InterfaceProvider* DeviceService::GetJavaInterfaceProvider() {
   if (!java_interface_provider_initialized_) {
diff --git a/services/device/device_service.h b/services/device/device_service.h
index f17a5e79..b7c9d26 100644
--- a/services/device/device_service.h
+++ b/services/device/device_service.h
@@ -10,6 +10,8 @@
 
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
+#include "device/usb/mojo/device_manager_impl.h"
+#include "device/usb/public/mojom/device_manager.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/device/geolocation/geolocation_provider.h"
 #include "services/device/geolocation/geolocation_provider_impl.h"
@@ -155,11 +157,14 @@
 
   void BindSerialIoHandlerRequest(mojom::SerialIoHandlerRequest request);
 
+  void BindUsbDeviceManagerRequest(mojom::UsbDeviceManagerRequest request);
+
   std::unique_ptr<PowerMonitorMessageBroadcaster>
       power_monitor_message_broadcaster_;
   std::unique_ptr<PublicIpAddressGeolocationProvider>
       public_ip_address_geolocation_provider_;
   std::unique_ptr<TimeZoneMonitor> time_zone_monitor_;
+  std::unique_ptr<usb::DeviceManagerImpl> usb_device_manager_;
   scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
diff --git a/services/device/manifest.json b/services/device/manifest.json
index f9f3825..beac967 100644
--- a/services/device/manifest.json
+++ b/services/device/manifest.json
@@ -26,6 +26,7 @@
           "device.mojom.SerialIoHandler"
         ],
         "device:time_zone_monitor": [ "device.mojom.TimeZoneMonitor" ],
+        "device:usb": [ "device.mojom.UsbDeviceManager" ],
         "device:vibration": [ "device.mojom.VibrationManager" ],
         "device:wake_lock": [ "device.mojom.WakeLockProvider" ]
       }
diff --git a/services/identity/public/cpp/README.md b/services/identity/public/cpp/README.md
index 0bba230..71aa75c 100644
--- a/services/identity/public/cpp/README.md
+++ b/services/identity/public/cpp/README.md
@@ -7,8 +7,14 @@
 
 - Synchronous access to the information of the primary account (via caching)
 
-A cheat sheet for developers migrating from usage of //components/signin and
-//google_apis/gaia:
+Documentation on the mapping between usage of legacy signin
+classes (notably SigninManager(Base) and ProfileOAuth2TokenService) and usage of
+IdentityManager is available here:
+
+https://docs.google.com/document/d/14f3qqkDM9IE4Ff_l6wuXvCMeHfSC9TxKezXTCyeaPUY/edit#
+
+A quick inline cheat sheet for developers migrating from usage of //components/
+signin and //google_apis/gaia:
 
 - "Primary account" in IdentityManager refers to what is called the
   "authenticated account" in SigninManager, i.e., the account that has been
diff --git a/services/network/cross_origin_read_blocking.h b/services/network/cross_origin_read_blocking.h
index ea227c3..6344eca 100644
--- a/services/network/cross_origin_read_blocking.h
+++ b/services/network/cross_origin_read_blocking.h
@@ -234,6 +234,8 @@
   // not allowed by actual CORS rules by ignoring 1) credentials and 2)
   // methods. Preflight requests don't matter here since they are not used to
   // decide whether to block a response or not on the client side.
+  // TODO(crbug.com/736308) Remove this check once the kOutOfBlinkCORS feature
+  // is shipped.
   static bool IsValidCorsHeaderSet(const url::Origin& frame_origin,
                                    const std::string& access_control_origin);
   FRIEND_TEST_ALL_PREFIXES(CrossOriginReadBlockingTest, IsValidCorsHeaderSet);
diff --git a/storage/browser/quota/quota_callbacks.h b/storage/browser/quota/quota_callbacks.h
index bcf6402..ac33358 100644
--- a/storage/browser/quota/quota_callbacks.h
+++ b/storage/browser/quota/quota_callbacks.h
@@ -45,7 +45,7 @@
 using GetOriginsCallback =
     base::OnceCallback<void(const std::set<url::Origin>& origins,
                             blink::mojom::StorageType type)>;
-using GetUsageInfoCallback = base::OnceCallback<void(const UsageInfoEntries&)>;
+using GetUsageInfoCallback = base::OnceCallback<void(UsageInfoEntries)>;
 using GetOriginCallback =
     base::OnceCallback<void(const base::Optional<url::Origin>&)>;
 
diff --git a/storage/browser/quota/quota_client.h b/storage/browser/quota/quota_client.h
index 0b74ba2..268a79f 100644
--- a/storage/browser/quota/quota_client.h
+++ b/storage/browser/quota/quota_client.h
@@ -17,10 +17,12 @@
 
 namespace storage {
 
-// An abstract interface for quota manager clients.
-// Each storage API must provide an implementation of this interface and
-// register it to the quota manager.
-// All the methods are assumed to be called on the IO thread in the browser.
+// Interface between each storage API and the quota manager.
+//
+// Each storage API must register an implementation of this interface with
+// the quota manager, by calling QuotaManager::RegisterClient().
+//
+// All the methods will be called on the IO thread in the browser.
 class STORAGE_EXPORT QuotaClient {
  public:
   using GetUsageCallback = base::OnceCallback<void(int64_t usage)>;
@@ -29,7 +31,7 @@
   using DeletionCallback =
       base::OnceCallback<void(blink::mojom::QuotaStatusCode status)>;
 
-  virtual ~QuotaClient() {}
+  virtual ~QuotaClient() = default;
 
   enum ID {
     kUnknown = 1 << 0,
@@ -45,7 +47,7 @@
 
   virtual ID id() const = 0;
 
-  // Called when the quota manager is destroyed.
+  // Called when the QuotaManager is destroyed.
   virtual void OnQuotaManagerDestroyed() = 0;
 
   // Called by the QuotaManager.
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc
index a4d24bf..4ed341a7 100644
--- a/storage/browser/quota/quota_manager.cc
+++ b/storage/browser/quota/quota_manager.cc
@@ -494,7 +494,7 @@
     // crbug.com/349708
     TRACE_EVENT0("io", "QuotaManager::GetUsageInfoTask::Completed");
 
-    std::move(callback_).Run(entries_);
+    std::move(callback_).Run(std::move(entries_));
     DeleteSoon();
   }
 
@@ -508,8 +508,8 @@
     std::map<std::string, int64_t> host_usage;
     tracker->GetCachedHostsUsage(&host_usage);
     for (const auto& host_usage_pair : host_usage) {
-      entries_.push_back(
-          UsageInfo(host_usage_pair.first, type, host_usage_pair.second));
+      entries_.emplace_back(host_usage_pair.first, type,
+                            host_usage_pair.second);
     }
     if (--remaining_trackers_ == 0)
       CallCompleted();
@@ -1057,17 +1057,17 @@
   return tracker && tracker->GetClientTracker(client_id);
 }
 
-void QuotaManager::GetStatistics(
-    std::map<std::string, std::string>* statistics) {
-  DCHECK(statistics);
+std::map<std::string, std::string> QuotaManager::GetStatistics() {
+  std::map<std::string, std::string> statistics;
   if (temporary_storage_evictor_) {
     std::map<std::string, int64_t> stats;
     temporary_storage_evictor_->GetStatistics(&stats);
     for (const auto& origin_usage_pair : stats) {
-      (*statistics)[origin_usage_pair.first] =
+      statistics[origin_usage_pair.first] =
           base::Int64ToString(origin_usage_pair.second);
     }
   }
+  return statistics;
 }
 
 bool QuotaManager::IsStorageUnlimited(const url::Origin& origin,
diff --git a/storage/browser/quota/quota_manager.h b/storage/browser/quota/quota_manager.h
index 6489da7..6ff88ea7 100644
--- a/storage/browser/quota/quota_manager.h
+++ b/storage/browser/quota/quota_manager.h
@@ -90,37 +90,33 @@
                                StatusCallback callback) = 0;
 
  protected:
-  virtual ~QuotaEvictionHandler() {}
+  virtual ~QuotaEvictionHandler() = default;
 };
 
 struct UsageInfo {
-  UsageInfo(const std::string& host,
-            blink::mojom::StorageType type,
-            int64_t usage)
-      : host(host), type(type), usage(usage) {}
-  std::string host;
-  blink::mojom::StorageType type;
-  int64_t usage;
+  UsageInfo(std::string host, blink::mojom::StorageType type, int64_t usage)
+      : host(std::move(host)), type(type), usage(usage) {}
+  const std::string host;
+  const blink::mojom::StorageType type;
+  const int64_t usage;
 };
 
-// The quota manager class.  This class is instantiated per profile and
-// held by the profile.  With the exception of the constructor and the
-// proxy() method, all methods should only be called on the IO thread.
-// TODO(sashab): Refactor this class to take a url::Origin, crbug.com/598424.
+// Each StoragePartition owns exactly one QuotaManager.
+//
+// Methods must be called on the IO thread, except for the constructor and
+// proxy().
 class STORAGE_EXPORT QuotaManager
     : public QuotaTaskObserver,
       public QuotaEvictionHandler,
       public base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter> {
  public:
-  using UsageAndQuotaCallback =
-      base::OnceCallback<void(blink::mojom::QuotaStatusCode,
-                              int64_t /* usage */,
-                              int64_t /* quota */)>;
+  using UsageAndQuotaCallback = base::OnceCallback<
+      void(blink::mojom::QuotaStatusCode, int64_t usage, int64_t quota)>;
   using UsageAndQuotaWithBreakdownCallback = base::OnceCallback<void(
       blink::mojom::QuotaStatusCode,
-      int64_t /* usage */,
-      int64_t /* quota */,
-      base::flat_map<QuotaClient::ID, int64_t> /* usage breakdown */)>;
+      int64_t usage,
+      int64_t quota,
+      base::flat_map<QuotaClient::ID, int64_t> usage_breakdown)>;
 
   static const int64_t kNoLimit;
 
@@ -228,7 +224,7 @@
   bool IsTrackingHostUsage(blink::mojom::StorageType type,
                            QuotaClient::ID client_id) const;
 
-  void GetStatistics(std::map<std::string, std::string>* statistics);
+  std::map<std::string, std::string> GetStatistics();
 
   bool IsStorageUnlimited(const url::Origin& origin,
                           blink::mojom::StorageType type) const;
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc
index b5f4ebfe..6fdcffe9 100644
--- a/storage/browser/quota/quota_manager_unittest.cc
+++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -345,8 +345,8 @@
         &QuotaManagerTest::DidDumpOriginInfoTable, weak_factory_.GetWeakPtr()));
   }
 
-  void DidGetUsageInfo(const UsageInfoEntries& entries) {
-    usage_info_.insert(usage_info_.begin(), entries.begin(), entries.end());
+  void DidGetUsageInfo(UsageInfoEntries entries) {
+    usage_info_ = std::move(entries);
   }
 
   void DidGetUsageAndQuota(QuotaStatusCode status,
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 0f648c4..cc24c84 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -103,6 +103,10 @@
 
 # https://crbug.com/721403
 -ContextMenuBrowserTest.DataSaverOpenOrigImageInNewTab
+-DataReductionProxyBrowsertest.ChromeProxyEctHeaderSet
+-DataReductionProxyBrowsertest.ChromeProxyHeaderSet
+-DataReductionProxyBrowsertest.ChromeProxyHeaderSetForSubresource
+-DataReductionProxyBrowsertest.ProxyNotUsedWhenDisabled
 
 # NOTE: if adding an exclusion for an existing failure (e.g. additional test for
 # feature X that is already not working), please add it beside the existing
diff --git a/testing/buildbot/filters/webrtc_perf.browser_tests.filter b/testing/buildbot/filters/webrtc_perf.browser_tests.filter
index 73d297cf..cc99a1a 100644
--- a/testing/buildbot/filters/webrtc_perf.browser_tests.filter
+++ b/testing/buildbot/filters/webrtc_perf.browser_tests.filter
@@ -1,4 +1,3 @@
-WebRtcAudioQualityBrowserTest.*
 WebRtcInternalsPerfBrowserTest.*
 WebRtcStatsPerfBrowserTest.*
 WebRtcVideoDisplayPerfBrowserTests*
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index 74c8403..60f6ebf 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -24,7 +24,3 @@
 # because content_shell does not add the about: handler. With network service
 # enabled this fails in both content_shell and chrome.
 Bug(none) http/tests/misc/redirect-to-about-blank.html [ Timeout ]
-
-# Timeout because activation is not triggered when DevTools is opened.
-crbug.com/879069 http/tests/devtools/service-workers/service-workers-redundant.js [ Timeout ]
-crbug.com/879069 http/tests/devtools/service-workers/service-workers-force-update-on-page-load.js [ Timeout ]
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index 7fa152d..6c6a195 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -1403,6 +1403,9 @@
 crbug.com/874695 virtual/user-activation-v2/fullscreen/model/fully-exit-fullscreen-nested-iframe.html [ Slow ]
 crbug.com/874695 virtual/user-activation-v2/fullscreen/rendering/overflow.html [ Slow ]
 crbug.com/874695 virtual/video-surface-layer/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Slow ]
+crbug.com/874695 virtual/video-surface-layer/http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-in-multiple-workers.js [ Slow ]
+crbug.com/874695 virtual/video-surface-layer/http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-shifted-breakpoint.js [ Slow ]
+crbug.com/874695 virtual/video-surface-layer/http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints.js [ Slow ]
 crbug.com/874695 virtual/video-surface-layer/media/audio-controls-do-not-fade-out.html [ Slow ]
 crbug.com/874695 virtual/video-surface-layer/media/autoplay-muted.html [ Slow ]
 crbug.com/874695 virtual/video-surface-layer/media/autoplay-when-visible.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index a4a3f6b..1e6574b 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2841,6 +2841,80 @@
 
 crbug.com/875249 external/wpt/infrastructure/testdriver/bless.html [ Timeout Pass ]
 
+# text-indent percentage should be resolved against the block's own content-box inline-size
+crbug.com/884588 external/wpt/css/css-text/text-indent/text-indent-percentage-002.html [ Failure ]
+crbug.com/884588 external/wpt/css/css-text/text-indent/text-indent-percentage-003.html [ Failure ]
+crbug.com/884588 external/wpt/css/css-text/text-indent/text-indent-percentage-004.html [ Failure ]
+
+# Some control characters still not visible
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-001.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-002.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-003.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-004.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-005.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-006.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-007.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-008.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-00B.html [ Failure ]
+crbug.com/893490 external/wpt/css/css-text/white-space/control-chars-00D.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-00E.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-00F.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-010.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-011.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-012.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-013.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-014.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-015.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-016.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-017.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-018.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-019.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-01A.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-01B.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-01C.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-01D.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-01E.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-01F.html [ Failure ]
+crbug.com/893490 external/wpt/css/css-text/white-space/control-chars-07F.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-080.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-081.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-082.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-083.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-084.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-085.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-086.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-087.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-088.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-089.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-08A.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-08B.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-08C.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-08D.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-08E.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-08F.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-090.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-091.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-092.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-093.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-094.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-095.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-096.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-097.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-098.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-099.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-09A.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-09B.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-09C.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-09D.html [ Failure ]
+crbug.com/893490 [ Mac Win ] external/wpt/css/css-text/white-space/control-chars-09E.html [ Failure ]
+crbug.com/893490 [ Mac ] external/wpt/css/css-text/white-space/control-chars-09F.html [ Failure ]
+
+# needs implementation of test_driver_internal.action_sequence
+crbug.com/893480 external/wpt/infrastructure/testdriver/actions/elementPosition.html [ Timeout ]
+crbug.com/893480 external/wpt/infrastructure/testdriver/actions/elementTiming.html [ Timeout ]
+crbug.com/893480 external/wpt/infrastructure/testdriver/actions/eventOrder.html [ Timeout ]
+crbug.com/893480 external/wpt/infrastructure/testdriver/actions/multiDevice.html [ Failure ]
+
 # ====== New tests from wpt-importer added here ======
 crbug.com/626703 [ Win10 ] external/wpt/speech-api/idlharness.window.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/align_center_position_50.html [ Failure ]
@@ -4644,6 +4718,7 @@
 crbug.com/806249 external/wpt/feature-policy/picture-in-picture-allowed-by-feature-policy.https.sub.html [ Failure ]
 crbug.com/806249 external/wpt/feature-policy/picture-in-picture-default-feature-policy.https.sub.html [ Failure ]
 crbug.com/806249 external/wpt/feature-policy/reporting/picture-in-picture-reporting.html [ Failure ]
+crbug.com/806249 http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints.js [ Timeout ]
 crbug.com/806249 media/picture-in-picture/controls/picture-in-picture-button.html [ Failure ]
 crbug.com/806249 media/picture-in-picture/controls/picture-in-picture-video-with-audio-only-button.html [ Failure ]
 crbug.com/806249 media/picture-in-picture/picture-in-picture-enabled.html [ Failure ]
@@ -5112,6 +5187,7 @@
 crbug.com/827639 http/tests/intersection-observer/v2 [ Skip ]
 
 crbug.com/875884 [ Linux Win ] lifecycle/background-change-lifecycle-count.html [ Pass Failure ]
+crbug.com/875884 [ Linux Win ] virtual/threaded/lifecycle/background-change-lifecycle-count.html [ Pass Failure ]
 
 # Sheriff 2018-08-16
 crbug.com/874733 [ Android ] accessibility/aria-labelledby-on-input.html [ Crash ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index d3b07ed8..9cd79d4 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -704,6 +704,12 @@
              "--enable-display-compositor-pixel-dump"]
   },
   {
+    "prefix": "video-surface-layer",
+    "base": "http/tests/devtools/sources/debugger-breakpoints",
+    "args": ["--enable-features=UseSurfaceLayerForVideo",
+             "--enable-display-compositor-pixel-dump"]
+  },
+  {
     "prefix": "user-activation-v2",
     "base": "fast/dom/Window",
     "args": ["--enable-features=UserActivationV2"]
diff --git a/third_party/WebKit/LayoutTests/animations/events/delay-start-event-expected.txt b/third_party/WebKit/LayoutTests/animations/events/delay-start-event-expected.txt
index 49445990..fed2d6434 100644
--- a/third_party/WebKit/LayoutTests/animations/events/delay-start-event-expected.txt
+++ b/third_party/WebKit/LayoutTests/animations/events/delay-start-event-expected.txt
@@ -1,5 +1,5 @@
 Tests that the start event is fired at the correct time with different start delays.
 
-PASS: zero-delay: Start event fired immediately
 PASS: negative-delay: Start event fired immediately
+PASS: zero-delay: Start event fired immediately
 PASS: positive-delay: Start event did not fire immediately
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
index a435700..503b3ca 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST_5.json
@@ -54733,6 +54733,42 @@
      {}
     ]
    ],
+   "css/css-scoping/host-context-specificity-001.html": [
+    [
+     "/css/css-scoping/host-context-specificity-001.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/host-context-specificity-002.html": [
+    [
+     "/css/css-scoping/host-context-specificity-002.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-scoping/host-context-specificity-003.html": [
+    [
+     "/css/css-scoping/host-context-specificity-003.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/host-descendant-001.html": [
     [
      "/css/css-scoping/host-descendant-001.html",
@@ -54805,6 +54841,18 @@
      {}
     ]
    ],
+   "css/css-scoping/host-specificity-003.html": [
+    [
+     "/css/css-scoping/host-specificity-003.html",
+     [
+      [
+       "/css/css-scoping/reference/green-box.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-scoping/host-specificity.html": [
     [
      "/css/css-scoping/host-specificity.html",
@@ -60529,6 +60577,42 @@
      {}
     ]
    ],
+   "css/css-text/text-indent/text-indent-percentage-002.html": [
+    [
+     "/css/css-text/text-indent/text-indent-percentage-002.html",
+     [
+      [
+       "/css/css-text/text-indent/reference/text-indent-percentage-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/text-indent/text-indent-percentage-003.html": [
+    [
+     "/css/css-text/text-indent/text-indent-percentage-003.html",
+     [
+      [
+       "/css/css-text/text-indent/reference/text-indent-percentage-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/text-indent/text-indent-percentage-004.html": [
+    [
+     "/css/css-text/text-indent/text-indent-percentage-004.html",
+     [
+      [
+       "/css/css-text/text-indent/reference/text-indent-percentage-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-text/text-justify/text-justify-001.html": [
     [
      "/css/css-text/text-justify/text-justify-001.html",
@@ -61441,6 +61525,750 @@
      {}
     ]
    ],
+   "css/css-text/white-space/control-chars-000.html": [
+    [
+     "/css/css-text/white-space/control-chars-000.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-001.html": [
+    [
+     "/css/css-text/white-space/control-chars-001.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-002.html": [
+    [
+     "/css/css-text/white-space/control-chars-002.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-003.html": [
+    [
+     "/css/css-text/white-space/control-chars-003.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-004.html": [
+    [
+     "/css/css-text/white-space/control-chars-004.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-005.html": [
+    [
+     "/css/css-text/white-space/control-chars-005.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-006.html": [
+    [
+     "/css/css-text/white-space/control-chars-006.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-007.html": [
+    [
+     "/css/css-text/white-space/control-chars-007.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-008.html": [
+    [
+     "/css/css-text/white-space/control-chars-008.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-00B.html": [
+    [
+     "/css/css-text/white-space/control-chars-00B.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-00D.html": [
+    [
+     "/css/css-text/white-space/control-chars-00D.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-00E.html": [
+    [
+     "/css/css-text/white-space/control-chars-00E.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-00F.html": [
+    [
+     "/css/css-text/white-space/control-chars-00F.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-010.html": [
+    [
+     "/css/css-text/white-space/control-chars-010.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-011.html": [
+    [
+     "/css/css-text/white-space/control-chars-011.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-012.html": [
+    [
+     "/css/css-text/white-space/control-chars-012.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-013.html": [
+    [
+     "/css/css-text/white-space/control-chars-013.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-014.html": [
+    [
+     "/css/css-text/white-space/control-chars-014.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-015.html": [
+    [
+     "/css/css-text/white-space/control-chars-015.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-016.html": [
+    [
+     "/css/css-text/white-space/control-chars-016.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-017.html": [
+    [
+     "/css/css-text/white-space/control-chars-017.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-018.html": [
+    [
+     "/css/css-text/white-space/control-chars-018.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-019.html": [
+    [
+     "/css/css-text/white-space/control-chars-019.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-01A.html": [
+    [
+     "/css/css-text/white-space/control-chars-01A.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-01B.html": [
+    [
+     "/css/css-text/white-space/control-chars-01B.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-01C.html": [
+    [
+     "/css/css-text/white-space/control-chars-01C.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-01D.html": [
+    [
+     "/css/css-text/white-space/control-chars-01D.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-01E.html": [
+    [
+     "/css/css-text/white-space/control-chars-01E.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-01F.html": [
+    [
+     "/css/css-text/white-space/control-chars-01F.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-07F.html": [
+    [
+     "/css/css-text/white-space/control-chars-07F.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-080.html": [
+    [
+     "/css/css-text/white-space/control-chars-080.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-081.html": [
+    [
+     "/css/css-text/white-space/control-chars-081.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-082.html": [
+    [
+     "/css/css-text/white-space/control-chars-082.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-083.html": [
+    [
+     "/css/css-text/white-space/control-chars-083.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-084.html": [
+    [
+     "/css/css-text/white-space/control-chars-084.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-085.html": [
+    [
+     "/css/css-text/white-space/control-chars-085.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-086.html": [
+    [
+     "/css/css-text/white-space/control-chars-086.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-087.html": [
+    [
+     "/css/css-text/white-space/control-chars-087.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-088.html": [
+    [
+     "/css/css-text/white-space/control-chars-088.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-089.html": [
+    [
+     "/css/css-text/white-space/control-chars-089.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-08A.html": [
+    [
+     "/css/css-text/white-space/control-chars-08A.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-08B.html": [
+    [
+     "/css/css-text/white-space/control-chars-08B.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-08C.html": [
+    [
+     "/css/css-text/white-space/control-chars-08C.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-08D.html": [
+    [
+     "/css/css-text/white-space/control-chars-08D.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-08E.html": [
+    [
+     "/css/css-text/white-space/control-chars-08E.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-08F.html": [
+    [
+     "/css/css-text/white-space/control-chars-08F.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-090.html": [
+    [
+     "/css/css-text/white-space/control-chars-090.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-091.html": [
+    [
+     "/css/css-text/white-space/control-chars-091.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-092.html": [
+    [
+     "/css/css-text/white-space/control-chars-092.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-093.html": [
+    [
+     "/css/css-text/white-space/control-chars-093.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-094.html": [
+    [
+     "/css/css-text/white-space/control-chars-094.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-095.html": [
+    [
+     "/css/css-text/white-space/control-chars-095.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-096.html": [
+    [
+     "/css/css-text/white-space/control-chars-096.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-097.html": [
+    [
+     "/css/css-text/white-space/control-chars-097.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-098.html": [
+    [
+     "/css/css-text/white-space/control-chars-098.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-099.html": [
+    [
+     "/css/css-text/white-space/control-chars-099.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-09A.html": [
+    [
+     "/css/css-text/white-space/control-chars-09A.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-09B.html": [
+    [
+     "/css/css-text/white-space/control-chars-09B.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-09C.html": [
+    [
+     "/css/css-text/white-space/control-chars-09C.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-09D.html": [
+    [
+     "/css/css-text/white-space/control-chars-09D.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-09E.html": [
+    [
+     "/css/css-text/white-space/control-chars-09E.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-text/white-space/control-chars-09F.html": [
+    [
+     "/css/css-text/white-space/control-chars-09F.html",
+     [
+      [
+       "/css/css-text/white-space/reference/control-chars-000-ref.html",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-text/white-space/pre-wrap-001.html": [
     [
      "/css/css-text/white-space/pre-wrap-001.html",
@@ -136135,6 +136963,11 @@
      {}
     ]
    ],
+   "css/css-text/text-indent/reference/text-indent-percentage-002-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-text/text-justify/reference/text-justify-ref-001.html": [
     [
      {}
@@ -136520,6 +137353,11 @@
      {}
     ]
    ],
+   "css/css-text/white-space/reference/control-chars-000-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-text/white-space/reference/pre-wrap-001-ref.html": [
     [
      {}
@@ -164290,6 +165128,26 @@
      {}
     ]
    ],
+   "infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini": [
+    [
+     {}
+    ]
+   ],
+   "infrastructure/metadata/infrastructure/testdriver/actions/elementTiming.html.ini": [
+    [
+     {}
+    ]
+   ],
+   "infrastructure/metadata/infrastructure/testdriver/actions/eventOrder.html.ini": [
+    [
+     {}
+    ]
+   ],
+   "infrastructure/metadata/infrastructure/testdriver/actions/multiDevice.html.ini": [
+    [
+     {}
+    ]
+   ],
    "infrastructure/reftest-wait-ref.html": [
     [
      {}
@@ -171540,6 +172398,11 @@
      {}
     ]
    ],
+   "resources/testdriver-actions.js": [
+    [
+     {}
+    ]
+   ],
    "resources/testdriver-vendor.js.headers": [
     [
      {}
@@ -178740,6 +179603,11 @@
      {}
     ]
    ],
+   "webstorage/event_initstorageevent-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "webstorage/event_setattribute.js": [
     [
      {}
@@ -199698,6 +200566,18 @@
      {}
     ]
    ],
+   "css/css-grid/grid-items/grid-items-relative-offsets-001.html": [
+    [
+     "/css/css-grid/grid-items/grid-items-relative-offsets-001.html",
+     {}
+    ]
+   ],
+   "css/css-grid/grid-items/grid-items-relative-offsets-002.html": [
+    [
+     "/css/css-grid/grid-items/grid-items-relative-offsets-002.html",
+     {}
+    ]
+   ],
    "css/css-grid/grid-items/grid-minimum-size-grid-items-021.html": [
     [
      "/css/css-grid/grid-items/grid-minimum-size-grid-items-021.html",
@@ -200658,6 +201538,12 @@
      {}
     ]
    ],
+   "css/css-scroll-anchoring/text-anchor-in-vertical-rl.html": [
+    [
+     "/css/css-scroll-anchoring/text-anchor-in-vertical-rl.html",
+     {}
+    ]
+   ],
    "css/css-scroll-anchoring/wrapped-text.html": [
     [
      "/css/css-scroll-anchoring/wrapped-text.html",
@@ -235424,6 +236310,38 @@
      {}
     ]
    ],
+   "infrastructure/testdriver/actions/elementPosition.html": [
+    [
+     "/infrastructure/testdriver/actions/elementPosition.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
+   "infrastructure/testdriver/actions/elementTiming.html": [
+    [
+     "/infrastructure/testdriver/actions/elementTiming.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
+   "infrastructure/testdriver/actions/eventOrder.html": [
+    [
+     "/infrastructure/testdriver/actions/eventOrder.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
+   "infrastructure/testdriver/actions/multiDevice.html": [
+    [
+     "/infrastructure/testdriver/actions/multiDevice.html",
+     {
+      "testdriver": true
+     }
+    ]
+   ],
    "infrastructure/testdriver/bless.html": [
     [
      "/infrastructure/testdriver/bless.html",
@@ -328290,7 +329208,7 @@
    "reftest"
   ],
   "css/css-grid/abspos/support/grid.css": [
-   "602e114880ae6576c0d440cf524ad284f89e708f",
+   "78fdd5e975ad61d3a8c39fe4e05694a278753c37",
    "support"
   ],
   "css/css-grid/alignment/grid-alignment-implies-size-change-001.html": [
@@ -329406,7 +330324,7 @@
    "reftest"
   ],
   "css/css-grid/grid-definition/support/grid.css": [
-   "602e114880ae6576c0d440cf524ad284f89e708f",
+   "78fdd5e975ad61d3a8c39fe4e05694a278753c37",
    "support"
   ],
   "css/css-grid/grid-definition/support/testing-utils.js": [
@@ -329637,6 +330555,14 @@
    "bf38155e16f26f00e8243f32fc7a2d15fd62b2e7",
    "testharness"
   ],
+  "css/css-grid/grid-items/grid-items-relative-offsets-001.html": [
+   "cb5e8ee23b66589a622c162c065ba8f5dd88a495",
+   "testharness"
+  ],
+  "css/css-grid/grid-items/grid-items-relative-offsets-002.html": [
+   "d92fca3ebb06fc106f42da22dce9e46383fc13a5",
+   "testharness"
+  ],
   "css/css-grid/grid-items/grid-items-sizing-alignment-001-ref.html": [
    "859483cf5d19dc53c1b1d047a6a3bfac2ed753e3",
    "support"
@@ -329890,7 +330816,7 @@
    "support"
   ],
   "css/css-grid/grid-items/support/grid.css": [
-   "602e114880ae6576c0d440cf524ad284f89e708f",
+   "78fdd5e975ad61d3a8c39fe4e05694a278753c37",
    "support"
   ],
   "css/css-grid/grid-items/table-with-infinite-max-intrinsic-width.html": [
@@ -330042,7 +330968,7 @@
    "reftest"
   ],
   "css/css-grid/grid-model/support/grid.css": [
-   "602e114880ae6576c0d440cf524ad284f89e708f",
+   "78fdd5e975ad61d3a8c39fe4e05694a278753c37",
    "support"
   ],
   "css/css-grid/implicit-grids/grid-support-grid-auto-columns-rows-001.html": [
@@ -334602,7 +335528,7 @@
    "support"
   ],
   "css/css-properties-values-api/typedom.tentative.html": [
-   "98150558dae5020333dbf0bc7b8cecdbe83dfc36",
+   "1d757df168b0db1acfdbd358951b30dbb25d3016",
    "testharness"
   ],
   "css/css-properties-values-api/unit-cycles.html": [
@@ -334913,6 +335839,18 @@
    "59787f048370401e80542ba7dbb0affcaed06c2f",
    "reftest"
   ],
+  "css/css-scoping/host-context-specificity-001.html": [
+   "694087f56b76cae0a3ccf5015cc25902a1dad8cf",
+   "reftest"
+  ],
+  "css/css-scoping/host-context-specificity-002.html": [
+   "3d4d3e5b245950f15ec126909393ff5e8b3edcb8",
+   "reftest"
+  ],
+  "css/css-scoping/host-context-specificity-003.html": [
+   "7abf8847c95ed04fae77b8601457909ecd72742e",
+   "reftest"
+  ],
   "css/css-scoping/host-descendant-001.html": [
    "423beaf055b9f482dd299c055721a405df1d5d77",
    "reftest"
@@ -334949,6 +335887,10 @@
    "3132d3a3455241347d6fe421f3434c361e424493",
    "reftest"
   ],
+  "css/css-scoping/host-specificity-003.html": [
+   "54a22599d8f83f612d7fc9ff91abfe650114c6e2",
+   "reftest"
+  ],
   "css/css-scoping/host-specificity.html": [
    "3ef61d4135fe7dbf846feb82540ca1a213ce7987",
    "reftest"
@@ -335169,6 +336111,10 @@
    "c384280f10fc96e2202518cb3333da346967d1a1",
    "testharness"
   ],
+  "css/css-scroll-anchoring/text-anchor-in-vertical-rl.html": [
+   "2a56298e982888fcf1745137b9e8868bae70a76a",
+   "testharness"
+  ],
   "css/css-scroll-anchoring/wrapped-text.html": [
    "4bd2cdb3251de62aceb13504404a58023f50c044",
    "testharness"
@@ -335178,7 +336124,7 @@
    "support"
   ],
   "css/css-scroll-snap/inheritance-expected.txt": [
-   "67d9a63ab79e61eca3ec275089aa12025920e13b",
+   "150868971a33aac5981da2194e25e790c4752879",
    "support"
   ],
   "css/css-scroll-snap/inheritance.html": [
@@ -340885,10 +341831,26 @@
    "546ba57a9889b553047986f1cb1eee76af733a60",
    "support"
   ],
+  "css/css-text/text-indent/reference/text-indent-percentage-002-ref.html": [
+   "5b3bc918d15f1737cd8e1518a8503425a4ee1d72",
+   "support"
+  ],
   "css/css-text/text-indent/text-indent-percentage-001.xht": [
    "ae2478579d216761bc4cff5155bfb225e49e87bd",
    "reftest"
   ],
+  "css/css-text/text-indent/text-indent-percentage-002.html": [
+   "65969260c5ee8467016545ba084bf4f7f886d6db",
+   "reftest"
+  ],
+  "css/css-text/text-indent/text-indent-percentage-003.html": [
+   "f81390da873dc27beb17533269b0464bfa5eff69",
+   "reftest"
+  ],
+  "css/css-text/text-indent/text-indent-percentage-004.html": [
+   "73f4c219558bf13fff6fc72ea208d0e52eb502f9",
+   "reftest"
+  ],
   "css/css-text/text-justify/reference/text-justify-ref-001.html": [
    "2a214057611f9b3aa43b3eb74c775214bb307ffd",
    "support"
@@ -341517,6 +342479,254 @@
    "58ec3f3cbd94b01dc15531308355cab3c42cc318",
    "reftest"
   ],
+  "css/css-text/white-space/control-chars-000.html": [
+   "b038fe9a90d3b8b9cb3bde7fd46396c7121688c9",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-001.html": [
+   "e43fda55431dee4a1406e5fcf04016e38db0defd",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-002.html": [
+   "a81a30723aab7523542a1ef6cede6f00e27a59ec",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-003.html": [
+   "e0d156a97958ebd80a3fee9cfe97a736fc58881f",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-004.html": [
+   "b33c4475ba9aef992f00f3cf27bba9afbacce2f5",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-005.html": [
+   "d14e86b80b28ffaebac49d35805be7ca43b8d1a9",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-006.html": [
+   "2b05272fec80075eab706f89b84fc299926329ac",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-007.html": [
+   "60587d9abdba433fd8762699b1160ef7ba520353",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-008.html": [
+   "fbe91aae05570156c11fbd8dac8a5114c7f931fc",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-00B.html": [
+   "6cdf0b35cf142cac701d54e7dceb635fdd9be24e",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-00D.html": [
+   "b7d1d44b0cc50f2761697de86f6ec3f2cf8904c1",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-00E.html": [
+   "826b4bb0d6aeeb24bf7852f2096a8280f9a63687",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-00F.html": [
+   "53618a8b79d189eb8e75c872b15643e4c3e8288a",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-010.html": [
+   "52c663876951ecf2d8f612367ea0269bc75928cf",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-011.html": [
+   "8aa8d94b91822e34ee220d83db4d233c23cb564d",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-012.html": [
+   "9300ae3a903aabd8d0b4869bb3954329e37d0db3",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-013.html": [
+   "f0e2b547cee43277ffbc2baaaee39c8243800e3a",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-014.html": [
+   "e8c776a9d7db7d3b2ce4a2d2635dd1e931f0d895",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-015.html": [
+   "718909dd47657575df18bd3f476d96dc00e81463",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-016.html": [
+   "2ba460c03c5a2ba8887b423c1af19386ab45ee21",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-017.html": [
+   "b4c96ca6523b600a8baebddc0e823162b2edbb23",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-018.html": [
+   "3a4c59e18a05f18e614ea6b7fb7bb762d515431c",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-019.html": [
+   "9517e79e4aa7acb7ab50d68b1fefc09c3af30404",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-01A.html": [
+   "4f61bcb7538f5da61932079a3b578917a0c1cd7e",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-01B.html": [
+   "fe9842b9ac0b5a204243b96cad8e9800681999f1",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-01C.html": [
+   "aadc1a9138dc1f8a0ecbe6841b50faf152d37165",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-01D.html": [
+   "266d30084efdf9b2e47b806a1f0c0ece4359b7ba",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-01E.html": [
+   "8cd3ddff5111353fdd5824a048c76099f5872864",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-01F.html": [
+   "61db980951db7aae3178721355c79c74479a2b46",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-07F.html": [
+   "27d5f02c4b2643beb55eb16cc84e5d90e07522bc",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-080.html": [
+   "ceedd013611c352fbabbfef24f686ebc4f79f5ee",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-081.html": [
+   "0e16b010461b9d97bc384ac55b44d04f4a784fe1",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-082.html": [
+   "c8461a7b2eacd409856138f609d5a5fea0c2711e",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-083.html": [
+   "ec723809ff063e0d4efc9f78f4647dcf1ae1fe1b",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-084.html": [
+   "249368173855c78449706549eddd7e45686b7855",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-085.html": [
+   "52dba2a1b61527b1764b989b597753b9baca331a",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-086.html": [
+   "39b132c588583d89131f7bd4859e7fe80072bfaf",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-087.html": [
+   "2320088a7fc741ef44439b0daf5eb0efb21d32fd",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-088.html": [
+   "12acc233258bf37eaae4c896b50c98aec3b08e05",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-089.html": [
+   "367503c88c4d5d932556e525e924af9ac9512bcd",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-08A.html": [
+   "1a21992d9709897e8d481e2d0f64adedd5099e79",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-08B.html": [
+   "1ed441a455446e01ab09545c50d77ab3d5053714",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-08C.html": [
+   "0c63ee54b609b2e65f5c1b81f004318c90a2d812",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-08D.html": [
+   "e908f8e1a898f33f9ad89ecab3119434fd894b90",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-08E.html": [
+   "55e87a556b8e1fef272d9ab285b66e0e06f9e730",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-08F.html": [
+   "2d9bac9730964efd54f5a80e5726d3cdbd5020b7",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-090.html": [
+   "c93258878c5e4705b306906da877a9b25f5fa440",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-091.html": [
+   "a21f8779add0aa36d8ee2d2e783c0640224bffb0",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-092.html": [
+   "5304eac57e69e853f41e651d787d9f6fb6a61605",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-093.html": [
+   "a092e873066d7d3d0b7f670edf73aa8ee0051fd9",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-094.html": [
+   "9005e8d098e84a7a53e476ba57e7551a8533b6e6",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-095.html": [
+   "6befbaa1bb15c7b728584cc6acf0ac39bd9043f8",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-096.html": [
+   "75e69d976b926f7562ca418ea1ecfcb3b2690fb0",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-097.html": [
+   "8a2c4467ae879525c2d947c7b7e0681e8268e900",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-098.html": [
+   "47e097789b6fdceca049f42a2ff5a6f535b9f8f9",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-099.html": [
+   "73a6ea6f225bd218c77fa76defe336a99d7f9b80",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-09A.html": [
+   "b34f9dc146e5a3dd208e62d84be66118a4a2cad0",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-09B.html": [
+   "4c5fcdd45a723490964448c776f5b1255bf1f161",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-09C.html": [
+   "6056a1c3de6f691cf3923c113d6f9bacbaf4a0ed",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-09D.html": [
+   "850d2696c4ea4b6f65c1f2025b349bacd3b73638",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-09E.html": [
+   "9613f9d01e2b005f81f17b627d2df1092c747fd9",
+   "reftest"
+  ],
+  "css/css-text/white-space/control-chars-09F.html": [
+   "44f6f83f2d110ac24d99de9eccaa6321903d931f",
+   "reftest"
+  ],
   "css/css-text/white-space/pre-wrap-001.html": [
    "31486f8f77c4c77188d94e9c21e9a8d5003e1bc4",
    "reftest"
@@ -341565,6 +342775,10 @@
    "f9063c98767e70c3899bc9a59b50b42a61240ae4",
    "reftest"
   ],
+  "css/css-text/white-space/reference/control-chars-000-ref.html": [
+   "9d5fcb27147a8c53e410d08511cb5035b612f80c",
+   "support"
+  ],
   "css/css-text/white-space/reference/pre-wrap-001-ref.html": [
    "8a8b5132db197bb9a76b1b44e461405f4cd9d1bc",
    "support"
@@ -362926,7 +364140,7 @@
    "support"
   ],
   "css/support/grid.css": [
-   "602e114880ae6576c0d440cf524ad284f89e708f",
+   "78fdd5e975ad61d3a8c39fe4e05694a278753c37",
    "support"
   ],
   "css/support/import-green.css": [
@@ -395725,6 +396939,22 @@
    "0d1b9bade95d7b101c8dbf51547ffbaec2260c27",
    "support"
   ],
+  "infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini": [
+   "9bd48305dab6849efa007f8db564edc9ec384445",
+   "support"
+  ],
+  "infrastructure/metadata/infrastructure/testdriver/actions/elementTiming.html.ini": [
+   "fb901118e94d341f1c2de66cb2b9f2ffd9f6a079",
+   "support"
+  ],
+  "infrastructure/metadata/infrastructure/testdriver/actions/eventOrder.html.ini": [
+   "a09be6fee0af54cfd34ffd302d06d436d2e7ece2",
+   "support"
+  ],
+  "infrastructure/metadata/infrastructure/testdriver/actions/multiDevice.html.ini": [
+   "df705dd73eb201eff3da8f2b46e18d45ebd60239",
+   "support"
+  ],
   "infrastructure/reftest-wait-ref.html": [
    "6772c2c460e79993979688ddf46e2045b14f7d71",
    "support"
@@ -395865,6 +397095,22 @@
    "ea7973a62e0ee9cdc874879fd844b2309e944e61",
    "testharness"
   ],
+  "infrastructure/testdriver/actions/elementPosition.html": [
+   "145852e7b51bd0cdc9e7b4ef5ebddcbf1c0235c5",
+   "testharness"
+  ],
+  "infrastructure/testdriver/actions/elementTiming.html": [
+   "cdfdff55f33ba591d5068ed0aea644527b12bc4e",
+   "testharness"
+  ],
+  "infrastructure/testdriver/actions/eventOrder.html": [
+   "c85b861c7fd9b199ce7baa5c9eac49525db4754b",
+   "testharness"
+  ],
+  "infrastructure/testdriver/actions/multiDevice.html": [
+   "5cab1206dbec8bc307fbdfed1bf3002cc02c299a",
+   "testharness"
+  ],
   "infrastructure/testdriver/bless.html": [
    "b8a1c2e7d6000050351453a14a8bfb80d8af0c76",
    "testharness"
@@ -418365,12 +419611,16 @@
    "9d7fa76a7d65f63ce8a3844920388ffb39b83bc3",
    "support"
   ],
+  "resources/testdriver-actions.js": [
+   "46c68858e4574646ad3efaa5a6dba10127b27a29",
+   "support"
+  ],
   "resources/testdriver-vendor.js.headers": [
    "5e8f640c6659d176eaca4c71cc1798b7285540b7",
    "support"
   ],
   "resources/testdriver.js": [
-   "42ec824d015ab53e1de21aa4e86564b9cd5ed094",
+   "e0741e8d61d4d67c99ccbfc860f65e796c44c78a",
    "support"
   ],
   "resources/testdriver.js.headers": [
@@ -431337,6 +432587,10 @@
    "fe7fca77a93c7adec48dc31e7926331e427b969b",
    "testharness"
   ],
+  "webstorage/event_initstorageevent-expected.txt": [
+   "0650fd5671d0792d5a501571a11b22ae87e0cff7",
+   "support"
+  ],
   "webstorage/event_initstorageevent.html": [
    "2fe893143614ca6d44becd027f6befba82e18ad1",
    "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-allowed.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-allowed.html
index 6c05478..7b4b455 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-allowed.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-allowed.html
@@ -1,14 +1,13 @@
 <!DOCTYPE html>
 
 <head>
-<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
 
 <body>
 <script>
-  var t = async_test("Test that the child can navigate the parent because the relevant policy belongs to the navigation initiator (in this case the child)");
+  var t = async_test("Test that the child can navigate the parent because the relevant policy belongs to the navigation initiator (in this case the child, which has the policy `navigate-to 'self'`)");
   window.onmessage = t.step_func_done(function(e) {
     assert_equals(e.data.result, 'success');
   });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-blocked.sub.html
index 2acf417a..4e50617e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/child-navigates-parent-blocked.sub.html
@@ -6,7 +6,14 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child can't navigate the parent because the relevant policy belongs to the navigation initiator (in this case the child which has the policy `navigate-to 'none'`)");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
 <iframe srcdoc="<iframe src='support/navigate_parent.sub.html?csp=navigate-to%20%27none%27&report_id={{$id:uuid()}}'>"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27none%27&reportID={{$id}}'></script>
-</body>
\ No newline at end of file
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html
index 452b88182..458373f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-allows.html
@@ -12,5 +12,5 @@
     assert_equals(e.data.result, 'success');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html">
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html
index 44dcc51..3ed4815 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-allows-navigate-to-blocks.html
@@ -12,5 +12,5 @@
     assert_equals(e.data.result, 'success');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html">
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27self%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html
index 5e6557d..f3f7896e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-allows.html
@@ -13,5 +13,5 @@
     assert_equals(e.data.violatedDirective, 'form-action');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html">
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html
index 9f9c803d..08e0cbe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-action/form-action-blocks-navigate-to-blocks.html
@@ -13,5 +13,5 @@
     assert_equals(e.data.violatedDirective, 'form-action');
   });
 </script>
-<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html">
+<iframe src="../support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27%3B%20form-action%20%27none%27%3B&action=post_message_to_frame_owner.html&report_id=dummy">
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-blocked.sub.html
index beb22214..72db7b8d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-blocked.sub.html
@@ -6,6 +6,13 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
 <iframe src="support/form_action_navigation.sub.html?csp=navigate-to%20%27none%27&report_id={{$id:uuid()}}&action=post_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27none%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-cross-origin-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-cross-origin-blocked.sub.html
index 49fe958..be5f70c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-cross-origin-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-cross-origin-blocked.sub.html
@@ -6,6 +6,13 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
 <iframe src="support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&action=http%3A%2F%2F{{domains[www1]}}:{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27self%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-redirected-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-redirected-blocked.sub.html
index 6adc9ef..d60b8a7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-redirected-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/form-redirected-blocked.sub.html
@@ -6,6 +6,14 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
+
 <iframe src="support/form_action_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&action=redirect_to_post_message_to_frame_owner.py%3Flocation%3Dhttp%3A%2F%2F{{domains[www1]}}%3A{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27self%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-blocked.sub.html
index 6aef250e..721f055c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-blocked.sub.html
@@ -7,6 +7,12 @@
 
 <body>
 <script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+
   window.open("support/href_location_navigation.sub.html?csp=navigate-to%20%27none%27&report_id={{$id:uuid()}}&target=post_message_to_frame_owner.html", "_blank");
 </script>
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-cross-origin-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-cross-origin-blocked.sub.html
index 894719b3..cd0cd91 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-cross-origin-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-cross-origin-blocked.sub.html
@@ -7,6 +7,12 @@
 
 <body>
 <script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+
   window.open("support/href_location_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&target=http%3A%2F%2F{{domains[www1]}}:{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html", "_blank");
 </script>
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-redirected-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-redirected-blocked.sub.html
index b91c473..5d8fafb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-redirected-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/href-location-redirected-blocked.sub.html
@@ -7,6 +7,12 @@
 
 <body>
 <script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+
   window.open("support/href_location_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&target=redirect_to_post_message_to_frame_owner.py%3Flocation%3Dhttp%3A%2F%2F{{domains[www1]}}%3A{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html", "_blank");
 </script>
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-allowed.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-allowed.html
index 667a3a5..977b85d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-allowed.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-allowed.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 
 <head>
-<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-blocked.sub.html
index 0ad9826..29686fc 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-blocked.sub.html
@@ -6,7 +6,14 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
 <iframe src="support/link_click_navigation.sub.html?csp=navigate-to%20%27none%27&report_id={{$id:uuid()}}&target=post_message_to_frame_owner.html"></iframe>
 
-<script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27none%27&reportID={{$id}}'></script>
+<script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27self%27&reportID={{$id}}'></script>
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-allowed.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-allowed.sub.html
index 2f9f0e2a..4381bcb 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-allowed.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-allowed.sub.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 
 <head>
-<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-blocked.sub.html
index 970f5a2d..f2b106c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-cross-origin-blocked.sub.html
@@ -1,12 +1,19 @@
 <!DOCTYPE html>
 
 <head>
-<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
+
 <iframe src="support/link_click_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&target=http%3A%2F%2F{{domains[www1]}}:{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27self%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-allowed.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-allowed.html
index 81c4f4e1..87dea95 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-allowed.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-allowed.html
@@ -1,7 +1,6 @@
 <!DOCTYPE html>
 
 <head>
-<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-blocked.sub.html
index bb6112624..9b9205a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/link-click-redirected-blocked.sub.html
@@ -1,12 +1,18 @@
 <!DOCTYPE html>
 
 <head>
-<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
 <iframe src="support/link_click_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&target=redirect_to_post_message_to_frame_owner.py%3Flocation%3Dhttp%3A%2F%2F{{domains[www1]}}%3A{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27self%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-blocked.sub.html
index d4d52a5..1292c9b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-blocked.sub.html
@@ -6,6 +6,14 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
+
 <iframe src="support/meta_refresh_navigation.sub.html?csp=navigate-to%20%27none%27&report_id={{$id:uuid()}}&target=post_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27none%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-cross-origin-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-cross-origin-blocked.sub.html
index 2118b27..d7ccd33 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-cross-origin-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-cross-origin-blocked.sub.html
@@ -6,6 +6,14 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
+
 <iframe src="support/meta_refresh_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&target=http%3A%2F%2F{{domains[www1]}}:{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27self%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-redirected-blocked.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-redirected-blocked.sub.html
index 55e3295..0734473e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-redirected-blocked.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/meta-refresh-redirected-blocked.sub.html
@@ -6,6 +6,14 @@
 </head>
 
 <body>
+<script>
+  var t = async_test("Test that the child iframe navigation is not allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+</script>
+
 <iframe src="support/meta_refresh_navigation.sub.html?csp=navigate-to%20%27self%27&report_id={{$id:uuid()}}&target=redirect_to_post_message_to_frame_owner.py%3Flocation%3Dhttp%3A%2F%2F{{domains[www1]}}%3A{{ports[http][0]}}%2Fcontent-security-policy%2Fnavigate-to%2Fsupport%2Fpost_message_to_frame_owner.html"></iframe>
 
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20%27self%27&reportID={{$id}}'></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-allowed.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-allowed.html
index e5455ce..47a6611 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-allowed.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-allowed.html
@@ -7,7 +7,7 @@
 
 <body>
 <script>
-  var t = async_test("Test that the parent can navigate the child because the relevant policy belongs to the navigation initiator (in this case the parent)");
+  var t = async_test("Test that the parent can navigate the child because the relevant policy belongs to the navigation initiator (in this case the parent, which has the policy `navigate-to 'self'`)");
   window.onmessage = t.step_func_done(function(e) {
     assert_equals(e.data.result, 'success');
   });
@@ -23,4 +23,4 @@
   i.src = "support/wait_for_navigation.html?csp=navigate-to%20%none%27";
   document.body.appendChild(i);
 </script>
-</body>
\ No newline at end of file
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-blocked.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-blocked.html
index fc549b47..c662da9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-blocked.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/parent-navigates-child-blocked.html
@@ -7,6 +7,12 @@
 
 <body>
 <script>
+  var t = async_test("Test that the parent can't navigate the child because the relevant policy belongs to the navigation initiator (in this case the parent, which has the policy `navigate-to support/wait_for_navigation.html;`)");
+  window.onmessage = t.unreached_func("Should not have received a message as the navigation should not have been successful");
+  window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
+    assert_equals(e.violatedDirective, 'navigate-to');
+  }));
+
   var i = document.createElement('iframe');
   var src_changed = false;
   i.onload = function() {
@@ -17,5 +23,6 @@
   i.src = "support/wait_for_navigation.html?csp=navigate-to%20%27self%27";
   document.body.appendChild(i);
 </script>
+
 <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=navigate-to%20support%2Fwait_for_navigation.html'></script>
-</body>
\ No newline at end of file
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/spv-only-sent-to-initiator.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/spv-only-sent-to-initiator.html
new file mode 100644
index 0000000..a09057e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/spv-only-sent-to-initiator.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<!-- This tests that a navigation initiator that has been replaced by the time
+     the navigation it initiates is blocked, will not receive the SPV event.
+
+     An iframe will navigate another iframe and the navigate itself.
+     The second iframe's navigation response will be delayed by the server but will
+     eventually be blocked by the CSP of the first iframe.
+     By the time this happens the first iframe should be an entirely different
+     document and it should not receive a SPV event -->
+<script>
+  var t = async_test("Test that no spv event is raised");
+  window.onmessage = t.step_func(function(e) {
+    if (e.data == "end_test") t.done();
+    else assert_unreached("Should not have raised a spv event");
+  });
+
+  var frames_loaded_count = 0;
+  var frame_loaded = function() {
+    if (++frames_loaded_count == 2) {
+      // both child frame have loaded we can start the
+      // test now, send a message to iframe1 so it knows to start
+      document.getElementById('iframe1').contentWindow.postMessage('start_test', '*');
+    }
+  }
+  var i1 = document.createElement('iframe');
+  i1.src = "support/spv-test-iframe1.sub.html?report_id={{$id:uuid()}}";
+  i1.id = "iframe1";
+  i1.name = "iframe1";
+  i1.onload = frame_loaded;
+  document.body.appendChild(i1);
+
+  var i2 = document.createElement('iframe');
+  i2.src = "support/spv-test-iframe2.sub.html";
+  i2.id = "iframe2";
+  i2.name = "iframe2";
+  i2.onload = frame_loaded;
+  document.body.appendChild(i2);
+</script>
+
+<script async defer src='../support/checkReport.sub.js?reportExists=false&reportID={{$id}}'></script>
+
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/delayed_frame.py b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/delayed_frame.py
new file mode 100644
index 0000000..21886c7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/delayed_frame.py
@@ -0,0 +1,12 @@
+import time
+def main(request, response):
+    time.sleep(1)
+    headers = [("Content-Type", "text/html")]
+    return headers, '''
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+    DELAYED FRAME
+</body
+'''
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/href_location_navigation.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/href_location_navigation.sub.html
index c577e93..15b1365 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/href_location_navigation.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/href_location_navigation.sub.html
@@ -6,6 +6,10 @@
 
 <body>
 <script>
+  window.addEventListener('securitypolicyviolation', function(e) {
+    opener.postMessage({result: 'fail', violatedDirective: e.violatedDirective}, '*');
+  });
+
   try {
     location.href = "{{GET[target]}}";
   } catch(ex) {}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/link_click_navigation.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/link_click_navigation.sub.html
index f1b42428..24342712 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/link_click_navigation.sub.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/link_click_navigation.sub.html
@@ -7,6 +7,10 @@
 <body>
 <a href="{{GET[target]}}" id="link">dummy link</a>
 <script>
+  window.addEventListener('securitypolicyviolation', function(e) {
+    top.postMessage({result: 'fail', violatedDirective: e.violatedDirective}, '*');
+  });
+
   document.getElementById('link').click();
 </script>
 </body>
\ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/redirect_to_post_message_to_frame_owner.py b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/redirect_to_post_message_to_frame_owner.py
index 652f9a5..d22e9202 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/redirect_to_post_message_to_frame_owner.py
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/redirect_to_post_message_to_frame_owner.py
@@ -3,4 +3,4 @@
     if "location" in request.GET:
         response.headers.set("Location", request.GET["location"])
     else:
-        response.headers.set("Location", "post_message_to_frame_owner.html")
\ No newline at end of file
+        response.headers.set("Location", "post_message_to_frame_owner.html")
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe1.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe1.sub.html
new file mode 100644
index 0000000..9e26c02
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe1.sub.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+  <script>
+    window.onmessage = function(e) {
+      if (e.data == "start_test") {
+        document.getElementById('link').click();
+        location.href = "{{location[server]}}/content-security-policy/navigate-to/support/spv-test-iframe3.sub.html";
+      }
+    }
+    window.addEventListener('securitypolicyviolation', function(e) {
+      top.postMessage({iframe: 'iframe1', violatedDirective: e.violatedDirective}, '*');
+    });
+  </script>
+</head>
+
+<body>
+  <a href="{{location[server]}}/content-security-policy/navigate-to/support/delayed_frame.py" id="link" target="iframe2">dummy link</a>
+  IFRAME 1
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe1.sub.html.sub.headers b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe1.sub.html.sub.headers
new file mode 100644
index 0000000..50d77dc7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe1.sub.html.sub.headers
@@ -0,0 +1,4 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Pragma: no-cache
+Content-Security-Policy: navigate-to {{location[server]}}/content-security-policy/navigate-to/support/spv-test-iframe3.sub.html 'unsafe-allow-redirects'; report-uri /content-security-policy/support/report.py?op=put&reportID={{GET[report_id]}}
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe2.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe2.sub.html
new file mode 100644
index 0000000..1329683
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe2.sub.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+  <script>
+    window.addEventListener('securitypolicyviolation', function(e) {
+      top.postMessage({iframe: 'iframe1', violatedDirective: e.violatedDirective}, '*');
+    });
+    setTimeout(function() {
+      top.postMessage("end_test", "*");
+    }, 4000);
+  </script>
+  IFRAME 2
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe3.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe3.sub.html
new file mode 100644
index 0000000..09dbf686
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/support/spv-test-iframe3.sub.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<head>
+  <script>
+    window.addEventListener('securitypolicyviolation', function(e) {
+      top.postMessage({iframe: 'iframe3', violatedDirective: e.violatedDirective}, '*');
+    });
+  </script>
+</head>
+
+<body>
+  IFRAME 3
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain-because-of-same-origin.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain-because-of-same-origin.sub.html
new file mode 100644
index 0000000..1924772
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain-because-of-same-origin.sub.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+<script>
+  var t = async_test("Test that the child iframe navigation is allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'success');
+  });
+
+  // the iframe will navigate to:
+  //    [www2]/..../redirect.py (which is not in the navigate-to source list) which will in turn navigate to
+  //    [www1]/..../post_message_to_frame_owner.html which is not exactly in
+  // the list but the check should be reduced to an origin check since there has been a redirect.
+  // Because of 'unsafe-allow-redirects' only the second one is checked since the first is a redirect
+
+  var i = document.createElement('iframe');
+  i.src = "../support/link_click_navigation.sub.html" +
+    "?csp=" + encodeURIComponent("navigate-to {{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/some-path/ 'unsafe-allow-redirects'") +
+    "&target=" + encodeURIComponent("{{location[scheme]}}://{{domains[www2]}}:{{location[port]}}/common/redirect.py?location=" +
+                                     encodeURIComponent("{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/content-security-policy/navigate-to/support/post_message_to_frame_owner.html"));
+  document.body.appendChild(i);
+</script>
+
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain.sub.html
new file mode 100644
index 0000000..74fe8f2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/allowed-end-of-chain.sub.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+<script>
+  var t = async_test("Test that the child iframe navigation is allowed");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'success');
+  });
+
+  // the iframe will navigate to:
+  //    [www2]/..../redirect.py (which is not in the navigate-to source list) which will in turn navigate to
+  //    [www1]/..../post_message_to_frame_owner.html which is in the list
+  // because of 'unsafe-allow-redirects' only the second one is checked since the first is a redirect
+
+  var i = document.createElement('iframe');
+  i.src = "../support/link_click_navigation.sub.html" +
+    "?csp=" + encodeURIComponent("navigate-to {{location[scheme]}}://{{domains[www1]}}:{{location[port]}} 'unsafe-allow-redirects'") +
+    "&target=" + encodeURIComponent("{{location[scheme]}}://{{domains[www2]}}:{{location[port]}}/common/redirect.py?location=" +
+                                     encodeURIComponent("{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/content-security-policy/navigate-to/support/post_message_to_frame_owner.html"));
+  document.body.appendChild(i);
+</script>
+
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/blocked-end-of-chain.sub.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/blocked-end-of-chain.sub.html
new file mode 100644
index 0000000..86e54b3d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/navigate-to/unsafe-allow-redirects/blocked-end-of-chain.sub.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+<script>
+  var t = async_test("Test that the child iframe navigation is blocked");
+  window.onmessage = t.step_func_done(function(e) {
+    assert_equals(e.data.result, 'fail');
+    assert_equals(e.data.violatedDirective, 'navigate-to');
+  });
+
+  // the iframe will navigate to:
+  //    [www2]/..../redirect.py (which is not in the navigate-to source list) which will in turn navigate to
+  //    [www2]/..../post_message_to_frame_owner.html which is also not in the list
+  // because of 'unsafe-allow-redirects' only the second one is checked since the first is a redirect
+
+  var i = document.createElement('iframe');
+  i.src = "../support/link_click_navigation.sub.html" +
+    "?csp=" + encodeURIComponent("navigate-to {{location[scheme]}}://{{domains[www1]}}:{{location[port]}} 'unsafe-allow-redirects'") +
+    "&target=" + encodeURIComponent("{{location[scheme]}}://{{domains[www2]}}:{{location[port]}}/common/redirect.py?location=" +
+                                     encodeURIComponent("{{location[scheme]}}://{{domains[www2]}}:{{location[port]}}/content-security-policy/navigate-to/support/post_message_to_frame_owner.html"));
+  document.body.appendChild(i);
+</script>
+
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt
index 684b6a74..b3260fa 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-animations/Document-getAnimations.tentative-expected.txt
@@ -2,8 +2,8 @@
 PASS getAnimations for non-animated content
 PASS getAnimations for CSS Animations
 FAIL Order of CSS Animations - within an element assert_equals: Order of first animation returned expected (string) "animLeft" but got (undefined) undefined
-FAIL Order of CSS Animations - across elements assert_equals: Order of first animation returned expected Element node <div style="animation: animLeft 100s"></div> but got Element node <div style="animation: animLeft 100s"></div>
-FAIL Order of CSS Animations - across and within elements assert_equals: Target of animation in position 0 expected Element node <div style="animation: animLeft 100s, animTop 100s"></div> but got Element node <div style="animation: animBottom 100s"></div>
+FAIL Order of CSS Animations - across elements assert_equals: Order of second animation returned after tree surgery expected Element node <div style="animation: animLeft 100s"></div> but got Element node <div style="animation: animLeft 100s"></div>
+FAIL Order of CSS Animations - across and within elements assert_equals: Name of animation in position 0 expected (string) "animLeft" but got (undefined) undefined
 FAIL Order of CSS Animations - markup-bound vs free animations assert_equals: Originally, animLeft animation comes first expected (string) "animLeft" but got (undefined) undefined
 FAIL Order of CSS Animations - free animations assert_equals: getAnimations returns free animations expected 2 but got 0
 FAIL Order of CSS Animations and CSS Transitions assert_equals: Transition comes first expected "[object CSSTransition]" but got "[object Animation]"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/support/grid.css
index 602e114..78fdd5e9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/support/grid.css
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/abspos/support/grid.css
@@ -68,6 +68,12 @@
   grid-row: 3;
 }
 
+.thirdRowThirdColumn {
+  background-color: salmon;
+  grid-column: 3;
+  grid-row: 3;
+}
+
 .firstRowThirdColumn {
   background-color: magenta;
   grid-column: 3;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/support/grid.css
index 602e114..78fdd5e9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/support/grid.css
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-definition/support/grid.css
@@ -68,6 +68,12 @@
   grid-row: 3;
 }
 
+.thirdRowThirdColumn {
+  background-color: salmon;
+  grid-column: 3;
+  grid-row: 3;
+}
+
 .firstRowThirdColumn {
   background-color: magenta;
   grid-column: 3;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/support/grid.css
index 602e114..78fdd5e9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/support/grid.css
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/grid-model/support/grid.css
@@ -68,6 +68,12 @@
   grid-row: 3;
 }
 
+.thirdRowThirdColumn {
+  background-color: salmon;
+  grid-column: 3;
+  grid-row: 3;
+}
+
 .firstRowThirdColumn {
   background-color: magenta;
   grid-column: 3;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/registered-property-type.https.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/registered-property-type.https.html
index 6ff7ce4..8f020083 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/registered-property-type.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-paint-api/registered-property-type.https.html
@@ -27,16 +27,42 @@
     paint(ctx, geom, styleMap) {
       ctx.strokeStyle = 'green';
       for (let prop of props) {
-        let first = styleMap.get(prop.name);
-        let all = styleMap.getAll(prop.name);
+        // Read values using get, getAll and iterator:
+        let valueFromGet = styleMap.get(prop.name);
+        let valueFromGetAll = styleMap.getAll(prop.name);
+        let valueFromIterator = Array.from(styleMap).filter(e => e[0] == prop.name)[0][1];
+
+        // Serialize 'actual'-values for all three cases:
         let serialize = v => v.constructor.name + '=' + v.toString()
-        let actual = all.map(serialize).join(',');
-        let expected = prop.expected.join(',');
-        let pass = actual === expected
-            && serialize(first) === prop.expected[0];
+        let actualFromGet = serialize(valueFromGet);
+        let actualFromGetAll = valueFromGetAll.map(serialize).join(',');
+        let actualFromIterator = valueFromIterator.map(serialize).join(',');
+
+        // Create 'expected'-values for all three cases:
+        let expectedForGet = prop.expected[0];
+        let expectedForGetAll = prop.expected.join(',');
+        let expectedForIterator = expectedForGetAll;
+
+        let pass = true;
+
+        // Assertions:
+        if (actualFromGet !== expectedForGet) {
+          debugLog(`FAIL: StylePropertyMap.get: actual: ${actualFromGet}  expected: ${expectedForGet}`);
+          pass = false;
+        }
+        if (actualFromGetAll !== expectedForGetAll) {
+          debugLog(`FAIL: StylePropertyMap.getAll: actual: ${actualFromGetAll}  expected: ${expectedForGetAll}`);
+          pass = false;
+        }
+        if (actualFromIterator !== expectedForIterator) {
+          debugLog(`FAIL: StylePropertyMap iterator: actual: ${actualFromIterator}  expected: ${expectedForIterator}`);
+          pass = false;
+        }
+
         if (!pass)
           ctx.strokeStyle = 'red';
-        debugLog(pass ? 'PASS' : 'FAIL', prop.syntax, actual, expected);
+        else
+          debugLog('PASS', prop.syntax, actualFromGetAll, expectedForGetAll);
       }
       ctx.lineWidth = 4;
       ctx.strokeRect(0, 0, geom.width, geom.height);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html
index 1d757df1..6d0623b 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-properties-values-api/typedom.tentative.html
@@ -33,6 +33,13 @@
     return name;
 }
 
+// Cleans style rules used for testing between every test.
+add_result_callback(function(){
+    target.attributeStyleMap.clear();
+    // Clears 'div' rule in #style:
+    style.sheet.rules[0].styleMap.clear();
+});
+
 // On the target element, verify that computed value of 'name' is an instance
 // of 'expected' and not an instance of CSSUnparsedValue.
 //
@@ -594,4 +601,124 @@
     }
 }, 'Direct CSSStyleValue instances are tied to their associated property');
 
+// StylePropertyMapReadOnly iteration
+
+test(function(){
+    let name = gen_prop('<length>', '10px');
+    let result = Array.from(target.computedStyleMap()).filter(e => e[0] == name)[0];
+    assert_true(typeof(result) !== 'undefined');
+}, 'Registered property with initial value show up on iteration of computedStyleMap');
+
+// Verifies that iterating a StylePropertyMap[ReadOnly] yields correctly
+// typed objects for a given syntax/value.
+function test_iteration_type_for_property_map(propertyMapName, propertyMap, options) {
+    test(function(){
+        let name = gen_prop(options.syntax, options.initialValue);
+        if (propertyMap instanceof StylePropertyMap) {
+            // Only set the value if the propertyMap is mutable.
+            propertyMap.set(name, options.value);
+        }
+        let result = Array.from(propertyMap).filter(e => e[0] == name)[0];
+        let value = result[1];
+        assert_true(options.expect(value));
+    }, `Iteration on ${propertyMapName} produces correct type for ${options.syntax}`);
+}
+
+function test_iteration_type(options) {
+    test_iteration_type_for_property_map('computedStyleMap', target.computedStyleMap(), options);
+    test_iteration_type_for_property_map('attributeStyleMap', target.attributeStyleMap, options);
+    test_iteration_type_for_property_map('styleMap', style.sheet.rules[0].styleMap, options);
+}
+
+test_iteration_type({
+    syntax: '*',
+    initialValue: 'none',
+    value: 'thing',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnparsedValue,
+});
+
+test_iteration_type({
+    syntax: '<angle>',
+    initialValue: '0deg',
+    value: '42deg',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
+test_iteration_type({
+    syntax: '<custom-ident>',
+    initialValue: 'none',
+    value: 'thing',
+    expect: v => v.length == 1 && v[0] instanceof CSSKeywordValue,
+});
+
+test_iteration_type({
+    syntax: '<image>',
+    initialValue: 'url(a)',
+    value: 'url(b)',
+    expect: v => v.length == 1 && v[0] instanceof CSSImageValue,
+});
+
+test_iteration_type({
+    syntax: '<integer>',
+    initialValue: '0',
+    value: '100',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
+test_iteration_type({
+    syntax: '<length>',
+    initialValue: '0px',
+    value: '10px',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
+test_iteration_type({
+    syntax: '<number>',
+    initialValue: '0',
+    value: '42',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
+test_iteration_type({
+    syntax: '<percentage>',
+    initialValue: '0%',
+    value: '10%',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
+test_iteration_type({
+    syntax: '<resolution>',
+    initialValue: '0dpi',
+    value: '300dpi',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
+test_iteration_type({
+    syntax: '<time>',
+    initialValue: '0s',
+    value: '10s',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
+test_iteration_type({
+    syntax: '<url>',
+    initialValue: 'url(a)',
+    value: 'url(b)',
+    expect: v => v.length == 1 && v[0].constructor === CSSStyleValue,
+});
+
+test_iteration_type({
+    syntax: 'none | thing | THING',
+    initialValue: 'none',
+    value: 'THING',
+    expect: v => v.length == 1 && v[0] instanceof CSSKeywordValue,
+});
+
+test_iteration_type({
+    syntax: '<angle> | <length>',
+    initialValue: '0deg',
+    value: '10px',
+    expect: v => v.length == 1 && v[0] instanceof CSSUnitValue,
+});
+
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/reference/text-indent-percentage-002-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/reference/text-indent-percentage-002-ref.html
new file mode 100644
index 0000000..5b3bc91
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/reference/text-indent-percentage-002-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset="utf-8">
+<title>CSS Text Test reference</title>
+<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
+<style>
+div { padding-left: 50px; }
+</style>
+
+<p>Test passes if there is a single black X below and no red.
+<div>X</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-002.html
new file mode 100644
index 0000000..6596926
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-002.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset="utf-8">
+<title>CSS Text Test: text-indent percentage resolution basis</title>
+<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#text-indent-property">
+<meta name="flags" content="">
+<link rel="match" href="reference/text-indent-percentage-002-ref.html">
+<meta name="assert" content="Percentages in text-indent refer to width of the element's content box">
+<style>
+section { position: absolute; }
+section, div {
+  border-right: 10px solid white;
+  margin-right: 10px;
+  padding-right: 10px;
+}
+div {
+  box-sizing: border-box;
+  width: 120px;
+}
+.test div { text-indent: 50%; color: red; }
+.ref div { text-indent: 50px; }
+</style>
+
+<p>Test passes if there is a single black X below and no red.
+<section class=test><div>X</div></section>
+<section class=ref><div>X</div></section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-003.html
new file mode 100644
index 0000000..f81390da8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-003.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset="utf-8">
+<title>CSS Text Test: text-indent percentage resolution basis</title>
+<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#text-indent-property">
+<meta name="flags" content="">
+<link rel="match" href="reference/text-indent-percentage-002-ref.html">
+<meta name="assert" content="Percentages in text-indent refer to width of the element's content box">
+<style>
+section { position: absolute; }
+section, div {
+  border-right: 10px solid white;
+  margin-right: 10px;
+  padding-right: 10px;
+}
+div {
+  box-sizing: border-box;
+  width: 120px;
+}
+.test div { text-indent: 50%; color: red; overflow: hidden; } /* overflow:hidden should not make any difference, but it does in some browsers */
+.ref div { text-indent: 50px; }
+</style>
+
+<p>Test passes if there is a single black X below and no red.
+<section class=test><div>X</div></section>
+<section class=ref><div>X</div></section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-004.html
new file mode 100644
index 0000000..73f4c21
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/text-indent/text-indent-percentage-004.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset="utf-8">
+<title>CSS Text Test: text-indent percentage resolution basis, in a calc expressiong</title>
+<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#text-indent-property">
+<meta name="flags" content="">
+<link rel="match" href="reference/text-indent-percentage-002-ref.html">
+<meta name="assert" content="Percentages in text-indent refer to width of the element's content box, when used in a calc expression">
+<style>
+section { position: absolute; }
+section, div {
+  border-right: 10px solid white;
+  margin-right: 10px;
+  padding-right: 10px;
+}
+div {
+  box-sizing: border-box;
+  width: 120px;
+}
+.test div { text-indent: calc(25px + 25%); color: red; }
+.ref div { text-indent: 50px; }
+</style>
+
+<p>Test passes if there is a single black X below and no red.
+<section class=test><div>X</div></section>
+<section class=ref><div>X</div></section>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-000.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-000.html
new file mode 100644
index 0000000..b038fe9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-000.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0000</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0000, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0000" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-001.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-001.html
new file mode 100644
index 0000000..e43fda5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-001.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0001</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0001, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0001" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-002.html
new file mode 100644
index 0000000..a81a3072
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-002.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0002</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0002, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0002" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-003.html
new file mode 100644
index 0000000..e0d156a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-003.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0003</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0003, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0003" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-004.html
new file mode 100644
index 0000000..b33c4475
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-004.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0004</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0004, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0004" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-005.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-005.html
new file mode 100644
index 0000000..d14e86b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-005.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0005</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0005, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0005" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-006.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-006.html
new file mode 100644
index 0000000..2b05272
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-006.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0006</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0006, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0006" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-007.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-007.html
new file mode 100644
index 0000000..60587d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-007.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0007</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0007, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0007" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-008.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-008.html
new file mode 100644
index 0000000..fbe91aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-008.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0008</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0008, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0008" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00B.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00B.html
new file mode 100644
index 0000000..6cdf0b35
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00B.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+000B</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+000B, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\000B" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00D.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00D.html
new file mode 100644
index 0000000..b7d1d44b0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00D.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+000D</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+000D, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\000D" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00E.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00E.html
new file mode 100644
index 0000000..826b4bb0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00E.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+000E</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+000E, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\000E" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00F.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00F.html
new file mode 100644
index 0000000..53618a8b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-00F.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+000F</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+000F, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\000F" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-010.html
new file mode 100644
index 0000000..52c6638
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-010.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0010</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0010, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0010" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-011.html
new file mode 100644
index 0000000..8aa8d94b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-011.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0011</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0011, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0011" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-012.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-012.html
new file mode 100644
index 0000000..9300ae3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-012.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0012</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0012, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0012" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-013.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-013.html
new file mode 100644
index 0000000..f0e2b54
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-013.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0013</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0013, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0013" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-014.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-014.html
new file mode 100644
index 0000000..e8c776a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-014.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0014</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0014, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0014" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-015.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-015.html
new file mode 100644
index 0000000..718909d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-015.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0015</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0015, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0015" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-016.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-016.html
new file mode 100644
index 0000000..2ba460c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-016.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0016</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0016, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0016" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-017.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-017.html
new file mode 100644
index 0000000..b4c96ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-017.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0017</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0017, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0017" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-018.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-018.html
new file mode 100644
index 0000000..3a4c59e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-018.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0018</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0018, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0018" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-019.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-019.html
new file mode 100644
index 0000000..9517e79
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-019.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0019</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0019, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0019" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01A.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01A.html
new file mode 100644
index 0000000..4f61bcb7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01A.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+001A</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+001A, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\001A" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01B.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01B.html
new file mode 100644
index 0000000..fe9842b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01B.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+001B</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+001B, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\001B" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01C.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01C.html
new file mode 100644
index 0000000..aadc1a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01C.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+001C</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+001C, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\001C" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01D.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01D.html
new file mode 100644
index 0000000..266d300
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01D.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+001D</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+001D, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\001D" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01E.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01E.html
new file mode 100644
index 0000000..8cd3ddf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01E.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+001E</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+001E, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\001E" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01F.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01F.html
new file mode 100644
index 0000000..61db980
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-01F.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+001F</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+001F, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\001F" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-07F.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-07F.html
new file mode 100644
index 0000000..27d5f02c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-07F.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+007F</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+007F, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\007F" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-080.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-080.html
new file mode 100644
index 0000000..ceedd01
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-080.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0080</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0080, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0080" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-081.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-081.html
new file mode 100644
index 0000000..0e16b01
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-081.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0081</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0081, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0081" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-082.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-082.html
new file mode 100644
index 0000000..c8461a7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-082.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0082</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0082, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0082" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-083.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-083.html
new file mode 100644
index 0000000..ec72380
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-083.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0083</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0083, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0083" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-084.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-084.html
new file mode 100644
index 0000000..2493681
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-084.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0084</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0084, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0084" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-085.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-085.html
new file mode 100644
index 0000000..52dba2a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-085.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0085</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0085, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0085" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-086.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-086.html
new file mode 100644
index 0000000..39b132c5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-086.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0086</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0086, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0086" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-087.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-087.html
new file mode 100644
index 0000000..2320088
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-087.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0087</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0087, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0087" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-088.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-088.html
new file mode 100644
index 0000000..12acc233
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-088.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0088</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0088, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0088" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-089.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-089.html
new file mode 100644
index 0000000..367503c8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-089.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0089</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0089, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0089" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08A.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08A.html
new file mode 100644
index 0000000..1a21992d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08A.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+008A</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+008A, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\008A" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08B.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08B.html
new file mode 100644
index 0000000..1ed441a4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08B.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+008B</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+008B, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\008B" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08C.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08C.html
new file mode 100644
index 0000000..0c63ee5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08C.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+008C</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+008C, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\008C" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08D.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08D.html
new file mode 100644
index 0000000..e908f8e1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08D.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+008D</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+008D, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\008D" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08E.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08E.html
new file mode 100644
index 0000000..55e87a5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08E.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+008E</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+008E, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\008E" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08F.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08F.html
new file mode 100644
index 0000000..2d9bac9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-08F.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+008F</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+008F, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\008F" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-090.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-090.html
new file mode 100644
index 0000000..c9325887
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-090.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0090</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0090, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0090" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-091.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-091.html
new file mode 100644
index 0000000..a21f877
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-091.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0091</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0091, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0091" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-092.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-092.html
new file mode 100644
index 0000000..5304eac
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-092.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0092</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0092, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0092" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-093.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-093.html
new file mode 100644
index 0000000..a092e87
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-093.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0093</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0093, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0093" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-094.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-094.html
new file mode 100644
index 0000000..9005e8d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-094.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0094</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0094, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0094" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-095.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-095.html
new file mode 100644
index 0000000..6befbaa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-095.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0095</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0095, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0095" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-096.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-096.html
new file mode 100644
index 0000000..75e69d9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-096.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0096</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0096, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0096" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-097.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-097.html
new file mode 100644
index 0000000..8a2c446
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-097.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0097</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0097, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0097" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-098.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-098.html
new file mode 100644
index 0000000..47e0977
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-098.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0098</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0098, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0098" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-099.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-099.html
new file mode 100644
index 0000000..73a6ea6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-099.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+0099</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+0099, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\0099" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09A.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09A.html
new file mode 100644
index 0000000..b34f9dc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09A.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+009A</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+009A, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\009A" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09B.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09B.html
new file mode 100644
index 0000000..4c5fcdd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09B.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+009B</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+009B, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\009B" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09C.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09C.html
new file mode 100644
index 0000000..6056a1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09C.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+009C</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+009C, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\009C" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09D.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09D.html
new file mode 100644
index 0000000..850d269
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09D.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+009D</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+009D, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\009D" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09E.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09E.html
new file mode 100644
index 0000000..9613f9d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09E.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+009E</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+009E, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\009E" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09F.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09F.html
new file mode 100644
index 0000000..44f6f83f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/control-chars-09F.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Control charcters must be visible: U+009F</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel=help href="https://drafts.csswg.org/css-text-3/#white-space-processing">
+<link rel=mismatch href="reference/control-chars-000-ref.html">
+<meta name=flags content="">
+<meta name=assert content="U+009F, which is in the unicode category CC, must be visible">
+<style>
+div {
+  font-size: 4em;
+}
+div::after { content: "\009F" } /* Injecting via CSS, to avoid any mangling by the html parser */
+</style>
+
+<p>Test passes if there is a visible character below.
+
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/control-chars-000-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/control-chars-000-ref.html
new file mode 100644
index 0000000..9d5fcb2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/white-space/reference/control-chars-000-ref.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSS test mismatch reference</title>
+<link rel=author title="Florian Rivoal" href="https://florian.rivoal.net">
+
+<p>Test passes if there is a visible character below.
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/support/grid.css b/third_party/WebKit/LayoutTests/external/wpt/css/support/grid.css
index 602e114..78fdd5e9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/support/grid.css
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/support/grid.css
@@ -68,6 +68,12 @@
   grid-row: 3;
 }
 
+.thirdRowThirdColumn {
+  background-color: salmon;
+  grid-column: 3;
+  grid-row: 3;
+}
+
 .firstRowThirdColumn {
   background-color: magenta;
   grid-column: 3;
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini
new file mode 100644
index 0000000..9bd4830
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini
@@ -0,0 +1,3 @@
+[elementPosition.html]
+  expected:
+    if product == "chrome" or product == "chrome_webdriver": ERROR
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementTiming.html.ini b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementTiming.html.ini
new file mode 100644
index 0000000..fb901118
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/elementTiming.html.ini
@@ -0,0 +1,3 @@
+[elementTiming.html]
+  expected:
+    if product == "chrome" or product == "chrome_webdriver": ERROR
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/eventOrder.html.ini b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/eventOrder.html.ini
new file mode 100644
index 0000000..a09be6f
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/eventOrder.html.ini
@@ -0,0 +1,3 @@
+[eventOrder.html]
+  expected:
+    if product == "chrome" or product == "chrome_webdriver": ERROR
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/multiDevice.html.ini b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/multiDevice.html.ini
new file mode 100644
index 0000000..df705dd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/metadata/infrastructure/testdriver/actions/multiDevice.html.ini
@@ -0,0 +1,3 @@
+[multiDevice.html]
+  expected:
+    if product == "chrome" or product == "chrome_webdriver": ERROR
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/elementPosition.html b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/elementPosition.html
new file mode 100644
index 0000000..145852e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/elementPosition.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>TestDriver actions: element position</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+div#test {
+  position: fixed;
+  left: -100px;
+  top: -25px;
+  width: 200px;
+  height: 75px;
+  background-color:blue;
+}
+</style>
+
+<div id="test">
+</div>
+
+<script>
+let events = [];
+
+async_test(t => {
+  let test = document.getElementById("test");
+  test.addEventListener("click", e => {
+    events.push(e.clientX);
+    events.push(e.clientY)
+  });
+
+  let div = document.getElementById("test");
+  let actions = new test_driver.Actions()
+    .pointerMove(0, 0, {origin: test})
+    .pointerDown()
+    .pointerUp()
+    .send()
+    .then(t.step_func_done(() => assert_array_equals(events, [50, 25])))
+    .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/elementTiming.html b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/elementTiming.html
new file mode 100644
index 0000000..cdfdff5
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/elementTiming.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>TestDriver actions: element timing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+div#test1, div#test2 {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100px;
+  height: 100px;
+  background-color: blue;
+}
+
+div#test2 {
+  display: none;
+  left: -100px;
+  background-color: green;
+}
+</style>
+
+<div id="test1">
+</div>
+
+<div id="test2">
+</div>
+
+<script>
+let events = [];
+
+async_test(t => {
+  let test1 = document.getElementById("test1");
+  let test2 = document.getElementById("test2");
+  document.getElementById("test1").addEventListener("click",
+    () => {test2.style.display = "block"; test2.style.top = "100px"; test2.style.left = "0"});
+  document.getElementById("test2").addEventListener("click",
+    e => {events.push(e.clientX); events.push(e.clientY)});
+
+  let div = document.getElementById("backing");
+  let actions = new test_driver.Actions()
+    .pointerMove(0, 0, {origin: test1})
+    .pointerDown()
+    .pointerUp()
+    .pointerMove(0, 0, {origin: test2})
+    .pointerDown()
+    .pointerUp()
+    .send()
+    .then(t.step_func_done(() => assert_array_equals(events, [50, 150])))
+    .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/eventOrder.html b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/eventOrder.html
new file mode 100644
index 0000000..c85b861c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/eventOrder.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>TestDriver actions: event order</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<button id="a">Button a</button>
+<button id="b">Button b</button>
+
+<script>
+// Pointer 1 is added before Pointer 2 so it comes first in the list of sources
+// Therefore its actions happen first
+let events = [];
+
+async_test(t => {
+  Array.prototype.forEach.call(document.getElementsByTagName("button"),
+                               (x) => x.addEventListener("mousedown", () => {events.push(x.id)}));
+
+  let button_a = document.getElementById("a");
+  let button_b = document.getElementById("b");
+  let actions = new test_driver.Actions()
+    .addPointer("pointer1")
+    .addPointer("pointer2")
+    .pointerMove(0, 0, {origin: button_a, sourceName: "pointer1"})
+    .pointerMove(0, 0, {origin: button_b, sourceName: "pointer2"})
+    .pointerDown({sourceName: "pointer2"})
+    .pointerDown({sourceName: "pointer1"})
+    .pointerUp({sourceName: "pointer2"})
+    .pointerUp({sourceName: "pointer1"})
+    .send()
+    .then(t.step_func_done(() => assert_array_equals(events, ["a", "b"])))
+    .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/multiDevice.html b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/multiDevice.html
new file mode 100644
index 0000000..5cab120
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/infrastructure/testdriver/actions/multiDevice.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>TestDriver actions: multiple devices</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<input type="text" id="text"></input>
+
+<script>
+async_test(t => {
+  let text_box = document.getElementById("text");
+  let actions = new test_driver.Actions()
+    .pointerMove(0, 0, {origin: text_box})
+    .pointerDown()
+    .pointerUp()
+    .addTick()
+    .keyDown("p")
+    .keyUp("p")
+    .keyDown("a")
+    .keyUp("a")
+    .keyDown("s")
+    .keyUp("s")
+    .keyDown("s")
+    .keyUp("s");
+
+  actions.send()
+    .then(() => {
+      assert_true(text_box.value == "pass");
+      t.done();
+    })
+    .catch(t.unreached_func("Actions sequence failed"));
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/input-events/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/input-events/OWNERS
index 1580295..51e8f5c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/input-events/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/input-events/OWNERS
@@ -1,4 +1,4 @@
 # TEAM: input-dev@chromium.org
 # COMPONENT: Blink>Input
-chongz@chromium.org
+nzolghadr@chromium.org
 yosin@chromium.org
diff --git a/third_party/WebKit/LayoutTests/external/wpt/pointerlock/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/pointerlock/OWNERS
index ffe070f..d9907e1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/pointerlock/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/pointerlock/OWNERS
@@ -1,3 +1,3 @@
 # TEAM: input-dev@chromium.org
 # COMPONENT: Blink>Input
-chongz@chromium.org
+eirage@chromium.org
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/testdriver-actions.js b/third_party/WebKit/LayoutTests/external/wpt/resources/testdriver-actions.js
new file mode 100644
index 0000000..46c6885
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/testdriver-actions.js
@@ -0,0 +1,391 @@
+(function() {
+  let sourceNameIdx = 0;
+
+  /**
+   * Builder for creating a sequence of actions
+   */
+  function Actions() {
+    this.sourceTypes = new Map([["key", KeySource],
+                                ["pointer", PointerSource],
+                                ["general", GeneralSource]]);
+    this.sources = new Map();
+    this.sourceOrder = [];
+    for (let sourceType of this.sourceTypes.keys()) {
+      this.sources.set(sourceType, new Map());
+    }
+    this.currentSources = new Map();
+    for (let sourceType of this.sourceTypes.keys()) {
+      this.currentSources.set(sourceType, null);
+    }
+    this.createSource("general");
+    this.tickIdx = 0;
+  }
+
+  Actions.prototype = {
+    /**
+     * Generate the action sequence suitable for passing to
+     * test_driver.action_sequence
+     *
+     * @returns {Array} Array of WebDriver-compatible actions sequences
+     */
+    serialize: function() {
+      let actions = [];
+      for (let [sourceType, sourceName] of this.sourceOrder) {
+        let source = this.sources.get(sourceType).get(sourceName);
+        let serialized = source.serialize(this.tickIdx + 1);
+        if (serialized) {
+          serialized.id = sourceName;
+          actions.push(serialized);
+        }
+      }
+      return actions;
+    },
+
+    /**
+     * Generate and send the action sequence
+     *
+     * @returns {Promise} fulfilled after the sequence is executed,
+     *                    rejected if any actions fail.
+     */
+    send: function() {
+      let actions;
+      try {
+        actions = this.serialize();
+      } catch(e) {
+        return Promise.reject(e);
+      }
+      return test_driver.action_sequence(actions);
+    },
+
+    /**
+     * Get the action source with a particular source type and name.
+     * If no name is passed, a new source with the given type is
+     * created.
+     *
+     * @param {String} type - Source type ('general', 'key', or 'pointer')
+     * @param {String?} name - Name of the source
+     * @returns {Source} Source object for that source.
+     */
+    getSource: function(type, name) {
+      if (!this.sources.has(type)) {
+        throw new Error(`${type} is not a valid action type`);
+      }
+      if (name === null || name === undefined) {
+        name = this.currentSources.get(type);
+      }
+      if (name === null || name === undefined) {
+        return this.createSource(type, null);
+      }
+      return this.sources.get(type).get(name);
+    },
+
+    setSource: function(type, name) {
+      if (!this.sources.has(type)) {
+        throw new Error(`${type} is not a valid action type`);
+      }
+      if (!this.sources.get(type).has(name)) {
+        throw new Error(`${name} is not a valid source for ${type}`);
+      }
+      this.currentSources.set(type, name);
+      return this;
+    },
+
+    /**
+     * Add a new key input source with the given name
+     *
+     * @param {String} name - Name of the key source
+     * @param {Bool} set - Set source as the default key source
+     * @returns {Actions}
+     */
+    addKeyboard: function(name, set=true) {
+      this.createSource("key", name, true);
+      if (set) {
+        this.setKeyboard(name);
+      }
+      return this;
+    },
+
+    /**
+     * Set the current default key source
+     *
+     * @param {String} name - Name of the key source
+     * @returns {Actions}
+     */
+    setKeyboard: function(name) {
+      this.setSource("key", name);
+      return this;
+    },
+
+    /**
+     * Add a new pointer input source with the given name
+     *
+     * @param {String} type - Name of the key source
+     * @param {String} pointerType - Type of pointing device
+     * @param {Bool} set - Set source as the default key source
+     * @returns {Actions}
+     */
+    addPointer: function(name, pointerType="mouse", set=true) {
+      this.createSource("pointer", name, true, {pointerType: pointerType});
+      if (set) {
+        this.setPointer(name);
+      }
+      return this;
+    },
+
+    /**
+     * Set the current default pointer source
+     *
+     * @param {String} name - Name of the pointer source
+     * @returns {Actions}
+     */
+    setPointer: function(name) {
+      this.setSource("pointer", name);
+      return this;
+    },
+
+    createSource: function(type, name, parameters={}) {
+      if (!this.sources.has(type)) {
+        throw new Error(`${type} is not a valid action type`);
+      }
+      let sourceNames = new Set();
+      for (let [_, name] of this.sourceOrder) {
+        sourceNames.add(name);
+      }
+      if (!name) {
+        do {
+          name = "" + sourceNameIdx++;
+        } while (sourceNames.has(name))
+      } else {
+        if (sourceNames.has(name)) {
+          throw new Error(`Alreay have a source of type ${type} named ${name}.`);
+        }
+      }
+      this.sources.get(type).set(name, new (this.sourceTypes.get(type))(parameters));
+      this.currentSources.set(type, name);
+      this.sourceOrder.push([type, name]);
+      return this.sources.get(type).get(name);
+    },
+
+    /**
+     * Insert a new actions tick
+     *
+     * @param {Number?} duration - Minimum length of the tick in ms.
+     * @returns {Actions}
+     */
+    addTick: function(duration) {
+      this.tickIdx += 1;
+      if (duration) {
+        this.pause(duration);
+      }
+      return this;
+    },
+
+    /**
+     * Add a pause to the current tick
+     *
+     * @param {Number?} duration - Minimum length of the tick in ms.
+     * @returns {Actions}
+     */
+    pause: function(duration) {
+      this.getSource("general").addPause(this, duration);
+      return this;
+    },
+
+    /**
+     * Create a keyDown event for the current default key source
+     *
+     * @param {String} key - Key to press
+     * @param {String?} sourceName - Named key source to use or null for the default key source
+     * @returns {Actions}
+     */
+    keyDown: function(key, {sourceName=null}={}) {
+      let source = this.getSource("key", sourceName);
+      source.keyDown(this, key);
+      return this;
+    },
+
+    /**
+     * Create a keyDown event for the current default key source
+     *
+     * @param {String} key - Key to release
+     * @param {String?} sourceName - Named key source to use or null for the default key source
+     * @returns {Actions}
+     */
+    keyUp: function(key, {sourceName=null}={}) {
+      let source = this.getSource("key", sourceName);
+      source.keyUp(this, key);
+      return this;
+    },
+
+    /**
+     * Create a pointerDown event for the current default pointer source
+     *
+     * @param {String} button - Button to press
+     * @param {String?} sourceName - Named pointer source to use or null for the default
+     *                               pointer source
+     * @returns {Actions}
+     */
+    pointerDown: function({button=0, sourceName=null}={}) {
+      let source = this.getSource("pointer", sourceName);
+      source.pointerDown(this, button);
+      return this;
+    },
+
+    /**
+     * Create a pointerUp event for the current default pointer source
+     *
+     * @param {String} button - Button to release
+     * @param {String?} sourceName - Named pointer source to use or null for the default pointer
+     *                               source
+     * @returns {Actions}
+     */
+    pointerUp: function({button=0, sourceName=null}={}) {
+      let source = this.getSource("pointer", sourceName);
+      source.pointerUp(this, button);
+      return this;
+    },
+
+    /**
+     * Create a move event for the current default pointer source
+     *
+     * @param {Number} x - Destination x coordinate
+     * @param {Number} y - Destination y coordinate
+     * @param {String|Element} origin - Origin of the coordinate system.
+     *                                  Either "pointer", "viewport" or an Element
+     * @param {Number?} duration - Time in ms for the move
+     * @param {String?} sourceName - Named pointer source to use or null for the default pointer
+     *                               source
+     * @returns {Actions}
+     */
+    pointerMove: function(x, y,
+                          {origin="viewport", duration, sourceName=null}={}) {
+      let source = this.getSource("pointer", sourceName);
+      source.pointerMove(this, x, y, duration, origin);
+      return this;
+    },
+  };
+
+  function GeneralSource() {
+    this.actions = new Map();
+  }
+
+  GeneralSource.prototype = {
+    serialize: function(tickCount) {
+      if (!this.actions.size) {
+        return undefined;
+      }
+      let actions = [];
+      let data = {"type": "none", "actions": actions};
+      for (let i=0; i<tickCount; i++) {
+        if (this.actions.has(i)) {
+          actions.push(this.actions.get(i));
+        } else {
+          actions.push({"type": "pause"});
+        }
+      }
+      return data;
+    },
+
+    addPause: function(actions, duration) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        throw new Error(`Already have a pause action for the current tick`);
+      }
+      this.actions.set(tick, {type: "pause", duration: duration});
+    },
+  };
+
+  function KeySource() {
+    this.actions = new Map();
+  }
+
+  KeySource.prototype = {
+    serialize: function(tickCount) {
+      if (!this.actions.size) {
+        return undefined;
+      }
+      let actions = [];
+      let data = {"type": "key", "actions": actions};
+      for (let i=0; i<tickCount; i++) {
+        if (this.actions.has(i)) {
+          actions.push(this.actions.get(i));
+        } else {
+          actions.push({"type": "pause"});
+        }
+      }
+      return data;
+    },
+
+    keyDown: function(actions, key) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "keyDown", value: key});
+    },
+
+    keyUp: function(actions, key) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "keyUp", value: key});
+    },
+  };
+
+  function PointerSource(parameters={pointerType: "mouse"}) {
+    let pointerType = parameters.pointerType || "mouse";
+    if (!["mouse", "pen", "touch"].includes(pointerType)) {
+      throw new Error(`Invalid pointerType ${pointerType}`);
+    }
+    this.type = pointerType;
+    this.actions = new Map();
+  }
+
+  PointerSource.prototype = {
+    serialize: function(tickCount) {
+      if (!this.actions.size) {
+        return undefined;
+      }
+      let actions = [];
+      let data = {"type": "pointer", "actions": actions, "parameters": {"pointerType": this.type}};
+      for (let i=0; i<tickCount; i++) {
+        if (this.actions.has(i)) {
+          actions.push(this.actions.get(i));
+        } else {
+          actions.push({"type": "pause"});
+        }
+      }
+      return data;
+    },
+
+    pointerDown: function(actions, button) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "pointerDown", button});
+    },
+
+    pointerUp: function(actions, button) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "pointerUp", button});
+    },
+
+    pointerMove: function(actions, x, y, duration, origin) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "pointerMove", x, y, origin});
+      if (duration) {
+        this.actions.get(tick).duration = duration;
+      }
+    },
+  };
+
+  test_driver.Actions = Actions;
+})();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/testdriver.js b/third_party/WebKit/LayoutTests/external/wpt/resources/testdriver.js
index 42ec824..e0741e8d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/testdriver.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/testdriver.js
@@ -171,6 +171,29 @@
          */
         freeze: function() {
             return window.test_driver_internal.freeze();
+        },
+
+        /**
+         * Send a sequence of actions
+         *
+         * This function sends a sequence of actions to the top level window
+         * to perform. It is modeled after the behaviour of {@link
+         * https://w3c.github.io/webdriver/#actions|WebDriver Actions Command}
+         *
+         * @param {Array} actions - an array of actions. The format is the same as the actions
+                                    property of the WebDriver command {@link
+                                    https://w3c.github.io/webdriver/#perform-actions|Perform
+                                    Actions} command. Each element is an object representing an
+                                    input source and each input source itself has an actions
+                                    property detailing the behaviour of that source at each timestep
+                                    (or tick). Authors are not expected to construct the actions
+                                    sequence by hand, but to use the builder api provided in
+                                    testdriver-actions.js
+         * @returns {Promise} fufiled after the actions are performed, or rejected in
+         *                    the cases the WebDriver command errors
+         */
+        action_sequence(actions) {
+            return window.test_driver_internal.action_sequence(actions);
         }
     };
 
@@ -205,6 +228,16 @@
          */
         freeze: function() {
             return Promise.reject(new Error("unimplemented"));
+        },
+
+        /**
+         * Send a sequence of pointer actions
+         *
+         * @returns {Promise} fufilled after actions are sent, rejected if any actions
+         *                    fail
+         */
+        action_sequence: function(actions) {
+            return Promise.reject(new Error("unimplemented"));
         }
     };
 })();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-audio-tainting.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-audio-tainting.https.html
new file mode 100644
index 0000000..9821759b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-audio-tainting.https.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/test-helpers.sub.js?pipe=sub"></script>
+<script>
+promise_test(async (t) => {
+    const SCOPE = 'resources/empty.html';
+    const SCRIPT = 'resources/fetch-rewrite-worker.js';
+    const host_info = get_host_info();
+    const REMOTE_ORIGIN = host_info.HTTPS_REMOTE_ORIGIN;
+
+    const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
+    await wait_for_state(t, reg.installing, 'activated');
+    const frame = await with_iframe(SCOPE);
+
+    const doc = frame.contentDocument;
+    const win = frame.contentWindow;
+
+    const context = new win.AudioContext();
+    try {
+      context.suspend();
+      const audio = doc.createElement('audio');
+      audio.autoplay = true;
+      const source = context.createMediaElementSource(audio);
+      const spn = context.createScriptProcessor(16384, 1, 1);
+      source.connect(spn).connect(context.destination);
+      const url = `${REMOTE_ORIGIN}/webaudio/resources/sin_440Hz_-6dBFS_1s.wav`;
+      audio.src = '/test?url=' + encodeURIComponent(url);
+      doc.body.appendChild(audio);
+
+      await new Promise((resolve) => {
+        audio.addEventListener('playing', resolve);
+      });
+      await context.resume();
+      const event = await new Promise((resolve) => {
+        spn.addEventListener('audioprocess', resolve);
+      });
+      const data = event.inputBuffer.getChannelData(0);
+      for (const e of data) {
+        assert_equals(e, 0);
+      }
+    } finally {
+      context.close();
+    }
+  }, 'Verify CORS XHR of fetch() in a Service Worker');
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https-expected.txt
deleted file mode 100644
index 319648d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video-cache.https-expected.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-This is a testharness.js-based test.
-PASS initialize global state
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&reject" with crossOrigin "" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&reject" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&reject" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&ignore" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&ignore" with crossOrigin "" should be TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&ignore" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&ACAOrigin=https://web-platform.test:8444&ignore" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&ACAOrigin=https://web-platform.test:8444&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&ACAOrigin=https://web-platform.test:8444&ACACredentials=true&ignore" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&Auth&ignore" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&Auth&ignore" with crossOrigin "" should be TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&Auth&ignore" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&Auth&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&Auth&ACAOrigin=https://web-platform.test:8444&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&Auth&ACAOrigin=https://web-platform.test:8444&ACACredentials=true&ignore" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "use-credentials" should be NOT_TAINTED
-FAIL url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "" should be NOT_TAINTED assert_equals: expected "NOT_TAINTED" but got "TAINTED"
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "" should be TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "" should be TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&credentials=same-origin&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACACredentials%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be LOAD_ERROR
-FAIL url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&credentials=same-origin&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be NOT_TAINTED assert_equals: expected "NOT_TAINTED" but got "TAINTED"
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&cache=true&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26cache%3Dtrue%26ACACredentials%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS restore global state
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https-expected.txt
deleted file mode 100644
index 58697c0..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-canvas-tainting-video.https-expected.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-This is a testharness.js-based test.
-PASS initialize global state
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&reject" with crossOrigin "" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&reject" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&reject" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&ignore" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&ignore" with crossOrigin "" should be TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&ignore" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&ACAOrigin=https://web-platform.test:8444&ignore" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&ACAOrigin=https://web-platform.test:8444&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&ACAOrigin=https://web-platform.test:8444&ACACredentials=true&ignore" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&Auth&ignore" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&Auth&ignore" with crossOrigin "" should be TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&Auth&ignore" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&Auth&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&Auth&ACAOrigin=https://web-platform.test:8444&ignore" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&Auth&ACAOrigin=https://web-platform.test:8444&ACACredentials=true&ignore" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "use-credentials" should be NOT_TAINTED
-FAIL url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "" should be NOT_TAINTED assert_equals: expected "NOT_TAINTED" but got "TAINTED"
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=same-origin&url=https%3A%2F%2Fweb-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "" should be TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "" should be TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "anonymous" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=no-cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&credentials=same-origin&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACACredentials%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be LOAD_ERROR
-FAIL url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&credentials=same-origin&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "" should be NOT_TAINTED assert_equals: expected "NOT_TAINTED" but got "TAINTED"
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "anonymous" should be NOT_TAINTED
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be LOAD_ERROR
-PASS url "https://www1.web-platform.test:8444/service-workers/service-worker/resources/fetch-access-control.py?VIDEO&mode=cors&url=https%3A%2F%2Fwww1.web-platform.test%3A8444%2Fservice-workers%2Fservice-worker%2Fresources%2Ffetch-access-control.py%3FVIDEO%26ACACredentials%3Dtrue%26ACAOrigin%3Dhttps%3A%2F%2Fweb-platform.test%3A8444" with crossOrigin "use-credentials" should be NOT_TAINTED
-PASS restore global state
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/touch-events/OWNERS b/third_party/WebKit/LayoutTests/external/wpt/touch-events/OWNERS
index ffe070f..e830748 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/touch-events/OWNERS
+++ b/third_party/WebKit/LayoutTests/external/wpt/touch-events/OWNERS
@@ -1,3 +1,3 @@
 # TEAM: input-dev@chromium.org
 # COMPONENT: Blink>Input
-chongz@chromium.org
+nzolghadr@chromium.org
diff --git a/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object-expected.html b/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object-expected.html
index 5608482..0aca8d2 100644
--- a/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object-expected.html
+++ b/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object-expected.html
@@ -10,4 +10,4 @@
     height: 100%;
 }
 </style>
-<object type="application/x-shockwave-flash" data="../../plugins/resources/simple_blank.swf"></object>
+<object width="200" type="image/svg+xml" data="../../svg/as-image/resources/circle.svg"></object>
diff --git a/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object.html b/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object.html
index f9a3046..17206cc 100644
--- a/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object.html
+++ b/third_party/WebKit/LayoutTests/fullscreen/rendering/backdrop-object.html
@@ -6,7 +6,7 @@
   background: green;
 }
 </style>
-<object type="application/x-shockwave-flash" data="../../plugins/resources/simple_blank.swf"></object>
+<object width="200" type="image/svg+xml" data="../../svg/as-image/resources/circle.svg"></object>
 <script>
 testRunner.waitUntilDone();
 var t = { step_func: func => func() };
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt
index bc465b9f..c3b3fb4 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-choose-preview-view-expected.txt
@@ -114,9 +114,9 @@
 Testing with MimeType: image/png, and StatusCode: 200
 Content: 
 
-ResourceType(xhr): widget vbox empty-view-scroller
-ResourceType(fetch): widget vbox empty-view-scroller
-ResourceType(document): widget vbox empty-view-scroller
-ResourceType(other): widget vbox empty-view-scroller
+ResourceType(xhr): widget vbox image-view
+ResourceType(fetch): widget vbox image-view
+ResourceType(document): widget vbox image-view
+ResourceType(other): widget vbox image-view
 
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints-expected.txt
new file mode 100644
index 0000000..a012bde
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints-expected.txt
@@ -0,0 +1,24 @@
+Tests Picture-in-Picture event listener breakpoints.
+
+
+Running: testPlayVideoEventBreakpoint
+Script execution paused.
+Call stack:
+    0) onVideoPlay (picture-in-picture-event-listener-breakpoints.js:22)
+Event target: VIDEO
+Script execution resumed.
+
+Running: testEnterPictureInPictureEventBreakpoint
+Script execution paused.
+Call stack:
+    0) onEnterPictureInPicture (picture-in-picture-event-listener-breakpoints.js:34)
+Event target: VIDEO
+Script execution resumed.
+
+Running: testLeavePictureInPictureEventBreakpoint
+Script execution paused.
+Call stack:
+    0) onLeavePictureInPicture (picture-in-picture-event-listener-breakpoints.js:46)
+Event target: VIDEO
+Script execution resumed.
+
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints.js
new file mode 100644
index 0000000..3048d1c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints.js
@@ -0,0 +1,100 @@
+// Copyright 2018 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.
+
+(async function() {
+  TestRunner.addResult(`Tests Picture-in-Picture event listener breakpoints.\n`);
+  await TestRunner.loadModule('sources_test_runner');
+  await TestRunner.showPanel('sources');
+  await TestRunner.loadHTML(`
+      <video id="video" src="../../../media/resources/test.ogv"></video>
+    `);
+  await TestRunner.evaluateInPagePromise(`
+      function playVideo()
+      {
+          var video = document.getElementById("video");
+          video.addEventListener("play", onVideoPlay, false);
+          video.play();
+      }
+
+      function onVideoPlay()
+      {
+          return 0;
+      }
+
+      function requestPictureInPicture()
+      {
+          var video = document.getElementById("video");
+          video.addEventListener("enterpictureinpicture", onEnterPictureInPicture, false);
+          video.requestPictureInPicture();
+      }
+
+      function onEnterPictureInPicture()
+      {
+          return 0;
+      }
+
+      function exitPictureInPicture()
+      {
+          var video = document.getElementById("video");
+          video.addEventListener("leavepictureinpicture", onLeavePictureInPicture, false);
+          document.exitPictureInPicture();
+      }
+
+      function onLeavePictureInPicture()
+      {
+          return 0;
+      }
+  `);
+
+  var testFunctions = [
+    function testPlayVideoEventBreakpoint(next) {
+      SourcesTestRunner.setEventListenerBreakpoint('listener:play', true, 'video');
+      SourcesTestRunner.waitUntilPaused(paused);
+      TestRunner.evaluateInPageWithTimeout('playVideo()');
+
+      function paused(callFrames, reason, breakpointIds, asyncStackTrace, auxData) {
+        SourcesTestRunner.captureStackTrace(callFrames);
+        printEventTargetName(auxData);
+        SourcesTestRunner.setEventListenerBreakpoint('listener:play', false, 'video');
+        SourcesTestRunner.resumeExecution(next);
+      }
+    },
+
+    function testEnterPictureInPictureEventBreakpoint(next) {
+      SourcesTestRunner.setEventListenerBreakpoint('listener:enterpictureinpicture', true, 'video');
+      SourcesTestRunner.waitUntilPaused(paused);
+      TestRunner.evaluateInPageWithTimeout('requestPictureInPicture()', true /* userGesture */);
+
+      function paused(callFrames, reason, breakpointIds, asyncStackTrace, auxData) {
+        SourcesTestRunner.captureStackTrace(callFrames);
+        printEventTargetName(auxData);
+        SourcesTestRunner.setEventListenerBreakpoint('listener:enterpictureinpicture', false, 'video');
+        SourcesTestRunner.resumeExecution(next);
+      }
+    },
+
+    function testLeavePictureInPictureEventBreakpoint(next) {
+      SourcesTestRunner.setEventListenerBreakpoint('listener:leavepictureinpicture', true, 'video');
+      SourcesTestRunner.waitUntilPaused(paused);
+      TestRunner.evaluateInPageWithTimeout('exitPictureInPicture()');
+
+      function paused(callFrames, reason, breakpointIds, asyncStackTrace, auxData) {
+        SourcesTestRunner.captureStackTrace(callFrames);
+        printEventTargetName(auxData);
+        SourcesTestRunner.setEventListenerBreakpoint('listener:leavepictureinpicture', false, 'video');
+        SourcesTestRunner.resumeExecution(next);
+      }
+    }
+  ];
+
+  SourcesTestRunner.runDebuggerTestSuite(testFunctions);
+
+  function printEventTargetName(auxData) {
+    var targetName = auxData && auxData.targetName;
+    if (targetName)
+      TestRunner.addResult('Event target: ' + targetName);
+    else
+      TestRunner.addResult('FAIL: No event target name received!');
+  }
+})();
diff --git a/third_party/WebKit/LayoutTests/virtual/video-surface-layer/http/tests/devtools/sources/debugger-breakpoints/README.txt b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/http/tests/devtools/sources/debugger-breakpoints/README.txt
new file mode 100644
index 0000000..c87fdcf
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/http/tests/devtools/sources/debugger-breakpoints/README.txt
@@ -0,0 +1 @@
+This suite runs Picture-in-Picture DevTools tests with the UseSurfaceLayerForVideo feature enabled.
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index ebb56c7..3a66905 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -30,6 +30,7 @@
     "filesystem/file_system.mojom",
     "filesystem/file_writer.mojom",
     "frame/find_in_page.mojom",
+    "frame/navigation_initiator.mojom",
     "indexeddb/indexeddb.mojom",
     "leak_detector/leak_detector.mojom",
     "loader/code_cache.mojom",
diff --git a/third_party/blink/public/mojom/frame/navigation_initiator.mojom b/third_party/blink/public/mojom/frame/navigation_initiator.mojom
new file mode 100644
index 0000000..293a1c8d
--- /dev/null
+++ b/third_party/blink/public/mojom/frame/navigation_initiator.mojom
@@ -0,0 +1,66 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module blink.mojom;
+
+// Represents the disposition of a CSP violation's policy as defined in:
+// https://w3c.github.io/webappsec-csp/#policy-disposition
+enum WebContentSecurityPolicyType {
+  WebContentSecurityPolicyTypeReport,
+  WebContentSecurityPolicyTypeEnforce
+};
+
+// Represents the source location of a CSP violation which contains the
+// three fields in:
+// https://w3c.github.io/webappsec-csp/#violation-source-file
+// https://w3c.github.io/webappsec-csp/#violation-line-number
+// https://w3c.github.io/webappsec-csp/#violation-column-number
+struct SourceLocation {
+  string url;
+  uint32 line_number;
+  uint32 column_number;
+};
+
+// Roughly represents the necessary information to build a CSP violation
+// event and send it, as defined in:
+// https://w3c.github.io/webappsec-csp/#violation-events
+struct CSPViolationParams {
+
+  // The name of the directive that violates the policy.
+  string directive;
+
+  // The name of the effective directive that was checked against.
+  string effective_directive;
+
+  // The console message to be displayed to the user.
+  string console_message;
+
+  // The URL that was blocked by the policy.
+  string blocked_url;
+
+  // The set of endpoints where a report of the violation should be sent.
+  // Based on 'use_reporting_api' it can be either a set of group_names (when
+  // 'use_reporting_api' = true) or a set of URLs. This means that it's not
+  // possible to use both methods of reporting. This is by design.
+  array<string> report_endpoints;
+
+  // Whether to use the reporting api or not.
+  bool use_reporting_api;
+
+  // The raw content security policy header that was violated.
+  string header;
+
+  // The associated disposition, which is either "enforce" or "report".
+  WebContentSecurityPolicyType disposition;
+
+  // Whether or not the violation happened after a redirect.
+  bool after_redirect;
+
+  // The source code location that triggered the blocked navigation.
+  SourceLocation source_location;
+};
+
+interface NavigationInitiator {
+  SendViolationReport(CSPViolationParams violation_params);
+};
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom
index 5896243..742536d 100644
--- a/third_party/blink/public/platform/web_feature.mojom
+++ b/third_party/blink/public/platform/web_feature.mojom
@@ -2038,6 +2038,7 @@
   kCSSValueAppearancePushButtonForOthersRendered = 2585,
   kCSSValueAppearanceSquareButtonRendered = 2586,
   kCSSValueAppearanceSquareButtonForOthersRendered = 2587,
+  kGetComputedStyleForWebkitAppearance = 2588,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_media_player.h b/third_party/blink/public/platform/web_media_player.h
index d2c9e64..a1e82caf 100644
--- a/third_party/blink/public/platform/web_media_player.h
+++ b/third_party/blink/public/platform/web_media_player.h
@@ -207,9 +207,10 @@
 
   virtual bool DidLoadingProgress() = 0;
 
-  virtual bool DidGetOpaqueResponseFromServiceWorker() const = 0;
-  virtual bool HasSingleSecurityOrigin() const = 0;
-  virtual bool DidPassCORSAccessCheck() const = 0;
+  // Returns true if the response is CORS-cross-origin and so we shouldn't be
+  // allowing media to play through webaudio.
+  // This should be called after the response has arrived.
+  virtual bool WouldTaintOrigin() const = 0;
 
   virtual double MediaTimeForTimeValue(double time_value) const = 0;
 
diff --git a/third_party/blink/public/platform/web_url_request.h b/third_party/blink/public/platform/web_url_request.h
index 428826d..50ded709 100644
--- a/third_party/blink/public/platform/web_url_request.h
+++ b/third_party/blink/public/platform/web_url_request.h
@@ -291,7 +291,7 @@
 
   // This is the navigation relevant CSP to be used during request and response
   // checks.
-  BLINK_PLATFORM_EXPORT const WebContentSecurityPolicyList& GetNavigationCSP()
+  BLINK_PLATFORM_EXPORT const WebContentSecurityPolicyList& GetInitiatorCSP()
       const;
 
   // Should be set to true if this request (including redirects) should be
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 9ef6306..75af736 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -405,8 +405,10 @@
   virtual void DidCreateDocumentLoader(WebDocumentLoader*) {}
 
   // A new provisional load has been started.
-  virtual void DidStartProvisionalLoad(WebDocumentLoader* document_loader,
-                                       WebURLRequest& request) {}
+  virtual void DidStartProvisionalLoad(
+      WebDocumentLoader* document_loader,
+      WebURLRequest& request,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) {}
 
   // The provisional load failed. The WebHistoryCommitType is the commit type
   // that would have been used had the load succeeded.
diff --git a/third_party/blink/renderer/core/animation/pending_animations.cc b/third_party/blink/renderer/core/animation/pending_animations.cc
index b0df78b..315fb5a 100644
--- a/third_party/blink/renderer/core/animation/pending_animations.cc
+++ b/third_party/blink/renderer/core/animation/pending_animations.cc
@@ -63,13 +63,7 @@
   HeapVector<Member<Animation>> animations;
   HeapVector<Member<Animation>> deferred;
   animations.swap(pending_);
-  int compositor_group = ++compositor_group_;
-  while (compositor_group == 0 || compositor_group == 1) {
-    // Wrap around, skipping 0, 1.
-    // * 0 is reserved for automatic assignment
-    // * 1 is used for animations with a specified start time
-    compositor_group = ++compositor_group_;
-  }
+  int compositor_group = NextCompositorGroup();
 
   for (auto& animation : animations) {
     bool had_compositor_animation =
@@ -97,17 +91,13 @@
   // remaining synchronized animations need to wait for the synchronized
   // start time. Otherwise they may start immediately.
   if (started_synchronized_on_compositor) {
-    for (auto& animation : waiting_for_start_time) {
-      if (!animation->startTime()) {
-        waiting_for_compositor_animation_start_.push_back(animation);
-      }
-    }
+    waiting_for_compositor_animation_start_.AppendVector(
+        waiting_for_start_time);
   } else {
     for (auto& animation : waiting_for_start_time) {
-      if (!animation->startTime()) {
-        animation->NotifyCompositorStartTime(
-            animation->TimelineInternal()->CurrentTimeInternal());
-      }
+      DCHECK(!animation->startTime());
+      animation->NotifyCompositorStartTime(
+          animation->TimelineInternal()->CurrentTimeInternal());
     }
   }
 
@@ -166,6 +156,17 @@
   }
 }
 
+int PendingAnimations::NextCompositorGroup() {
+  do {
+    // Wrap around, skipping 0, 1.
+    // * 0 is reserved for automatic assignment
+    // * 1 is used for animations with a specified start time
+    ++compositor_group_;
+  } while (compositor_group_ == 0 || compositor_group_ == 1);
+
+  return compositor_group_;
+}
+
 void PendingAnimations::Trace(blink::Visitor* visitor) {
   visitor->Trace(pending_);
   visitor->Trace(waiting_for_compositor_animation_start_);
diff --git a/third_party/blink/renderer/core/animation/pending_animations.h b/third_party/blink/renderer/core/animation/pending_animations.h
index e9933d5..651e38a 100644
--- a/third_party/blink/renderer/core/animation/pending_animations.h
+++ b/third_party/blink/renderer/core/animation/pending_animations.h
@@ -66,8 +66,26 @@
         compositor_group_(1) {}
 
   void Add(Animation*);
-  // Returns whether we are waiting for an animation to start and should
-  // service again on the next frame.
+
+  // Attempts to start/update pending composited and non-composited animations.
+  // At the end of this process all pending animations will fall into one of the
+  // following buckets:
+  // - pending: already composited animations that cannot be restarted this
+  //   cycle and are deferred to be tried next cycle.
+  // - started on compositor: animations that could be composited and are
+  //   successfully started on compositor.
+  // - waiting on start time: animations whose start time needs to be
+  //   synchronized with compositor. These may include non-composited
+  //   animations.
+  // - notified of start time: animations whose start time does not need to be
+  //   synchronized with compositor and thus can be immediately notified.
+  // - ignored: animations that are not started and don't need to be notified
+  //   are simply ignored. This allows the rest of animation machinery to add
+  //   animations to the pending list eagerly knowing that the logic here
+  //   ignores them if no action needs to be taken.
+  //
+  // Returns whether we are waiting for an animation to start and should service
+  // again on the next frame.
   bool Update(const base::Optional<CompositorElementIdSet>&,
               bool start_on_compositor = true);
   void NotifyCompositorAnimationStarted(double monotonic_animation_start_time,
@@ -79,6 +97,7 @@
   void TimerFired(TimerBase*) {
     Update(base::Optional<CompositorElementIdSet>(), false);
   }
+  int NextCompositorGroup();
 
   HeapVector<Member<Animation>> pending_;
   HeapVector<Member<Animation>> waiting_for_compositor_animation_start_;
diff --git a/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc b/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
index a490828..4df98db 100644
--- a/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
+++ b/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc
@@ -84,6 +84,22 @@
     }
   }
 
+  // Registered properties with initial values are not stored explicitly on
+  // each computed style. Their initialness is instead indicated by the
+  // absence of that property on the computed style. This means that registered
+  // properties with an implicit initial value will not appear in the result of
+  // Style[Non]InheritedVariables::GetCustomPropertyNames, so we need to
+  // iterate though all registrations and add the initial values, if necessary.
+  if (registry) {
+    for (const auto& entry : *registry) {
+      if (variables.Contains(entry.key))
+        continue;
+      const CSSValue* initial = entry.value->Initial();
+      if (initial)
+        variables.Set(entry.key, initial);
+    }
+  }
+
   return variables;
 }
 
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
index dac867d..5af1c199 100644
--- a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
+++ b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
@@ -381,6 +381,11 @@
 
 String CSSComputedStyleDeclaration::GetPropertyValue(
     CSSPropertyID property_id) const {
+  // allow_visited_style_ is true only for access from DevTools.
+  if (!allow_visited_style_ && property_id == CSSPropertyWebkitAppearance) {
+    UseCounter::Count(node_->GetDocument(),
+                      WebFeature::kGetComputedStyleWebkitAppearance);
+  }
   const CSSValue* value = GetPropertyCSSValue(CSSProperty::Get(property_id));
   if (value)
     return value->CssText();
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
index 7141586..2a8d480 100644
--- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
+++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
@@ -134,19 +134,32 @@
 }
 
 StylePropertyMapReadOnly::IterationSource*
-StylePropertyMapReadOnly::StartIteration(ScriptState*, ExceptionState&) {
+StylePropertyMapReadOnly::StartIteration(ScriptState* script_state,
+                                         ExceptionState&) {
   HeapVector<StylePropertyMapReadOnly::StylePropertyMapEntry> result;
 
-  ForEachProperty([&result](const String& property_name,
-                            const CSSValue& css_value) {
+  const ExecutionContext& execution_context =
+      *ExecutionContext::From(script_state);
+
+  ForEachProperty([&result, &execution_context](const String& property_name,
+                                                const CSSValue& css_value) {
     const auto property_id = cssPropertyID(property_name);
 
-    AtomicString custom_property_name = property_id == CSSPropertyVariable
-                                            ? AtomicString(property_name)
-                                            : g_null_atom;
+    const CSSValue* value = &css_value;
+    AtomicString custom_property_name = g_null_atom;
+
+    if (property_id == CSSPropertyVariable) {
+      custom_property_name = AtomicString(property_name);
+
+      const auto* document = DynamicTo<Document>(execution_context);
+      if (document) {
+        value = PropertyRegistry::ParseIfRegistered(
+            *document, custom_property_name, value);
+      }
+    }
 
     auto values = StyleValueFactory::CssValueToStyleValueVector(
-        property_id, custom_property_name, css_value);
+        property_id, custom_property_name, *value);
     result.emplace_back(property_name, std::move(values));
   });
 
diff --git a/third_party/blink/renderer/core/css/property_registry.cc b/third_party/blink/renderer/core/css/property_registry.cc
index 6910a968..28ff581 100644
--- a/third_party/blink/renderer/core/css/property_registry.cc
+++ b/third_party/blink/renderer/core/css/property_registry.cc
@@ -18,6 +18,16 @@
   return registrations_.at(name);
 }
 
+PropertyRegistry::RegistrationMap::const_iterator PropertyRegistry::begin()
+    const {
+  return registrations_.begin();
+}
+
+PropertyRegistry::RegistrationMap::const_iterator PropertyRegistry::end()
+    const {
+  return registrations_.end();
+}
+
 const CSSValue* PropertyRegistry::ParseIfRegistered(
     const Document& document,
     const AtomicString& property_name,
diff --git a/third_party/blink/renderer/core/css/property_registry.h b/third_party/blink/renderer/core/css/property_registry.h
index 4b76a74..b9dc7a1 100644
--- a/third_party/blink/renderer/core/css/property_registry.h
+++ b/third_party/blink/renderer/core/css/property_registry.h
@@ -13,12 +13,18 @@
 
 class CORE_EXPORT PropertyRegistry : public GarbageCollected<PropertyRegistry> {
  public:
+  using RegistrationMap =
+      HeapHashMap<AtomicString, Member<PropertyRegistration>>;
+
   static PropertyRegistry* Create() { return new PropertyRegistry(); }
 
   void RegisterProperty(const AtomicString&, PropertyRegistration&);
   const PropertyRegistration* Registration(const AtomicString&) const;
   size_t RegistrationCount() const { return registrations_.size(); }
 
+  RegistrationMap::const_iterator begin() const;
+  RegistrationMap::const_iterator end() const;
+
   void Trace(blink::Visitor* visitor) { visitor->Trace(registrations_); }
 
   // Parse the incoming value and return the parsed result, if:
@@ -31,7 +37,7 @@
                                            const CSSValue*);
 
  private:
-  HeapHashMap<AtomicString, Member<PropertyRegistration>> registrations_;
+  RegistrationMap registrations_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/container_node.cc b/third_party/blink/renderer/core/dom/container_node.cc
index d313efc..f94b4d2 100644
--- a/third_party/blink/renderer/core/dom/container_node.cc
+++ b/third_party/blink/renderer/core/dom/container_node.cc
@@ -1394,7 +1394,7 @@
   DCHECK(change >= kUpdatePseudoElements || ChildNeedsStyleRecalc());
   DCHECK(!NeedsStyleRecalc());
 
-  for (Node* child = lastChild(); child; child = child->previousSibling()) {
+  for (Node* child = firstChild(); child; child = child->nextSibling()) {
     if (child->IsTextNode()) {
       ToText(child)->RecalcTextStyle(change);
     } else if (child->IsElementNode()) {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 5bc37f9..882a1f35 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -7662,6 +7662,36 @@
       line_number, column_number);
 }
 
+void Document::SendViolationReport(
+    mojom::blink::CSPViolationParamsPtr violation_params) {
+  std::unique_ptr<SourceLocation> source_location = SourceLocation::Create(
+      violation_params->source_location->url,
+      violation_params->source_location->line_number,
+      violation_params->source_location->column_number, nullptr);
+
+  Vector<String> report_endpoints;
+  for (const WebString& end_point : violation_params->report_endpoints)
+    report_endpoints.push_back(end_point);
+
+  AddConsoleMessage(ConsoleMessage::Create(kSecurityMessageSource,
+                                           kErrorMessageLevel,
+                                           violation_params->console_message));
+  GetContentSecurityPolicy()->ReportViolation(
+      violation_params->directive,
+      ContentSecurityPolicy::GetDirectiveType(
+          violation_params->effective_directive),
+      violation_params->console_message, KURL(violation_params->blocked_url),
+      report_endpoints, violation_params->use_reporting_api,
+      violation_params->header,
+      static_cast<ContentSecurityPolicyHeaderType>(
+          violation_params->disposition),
+      ContentSecurityPolicy::ViolationType::kURLViolation,
+      std::move(source_location), nullptr /* LocalFrame */,
+      violation_params->after_redirect ? RedirectStatus::kFollowedRedirect
+                                       : RedirectStatus::kNoRedirect,
+      nullptr /* Element */);
+}
+
 template class CORE_TEMPLATE_EXPORT Supplement<Document>;
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index bc4131e..a78b81b 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -34,6 +34,8 @@
 #include <utility>
 
 #include "base/memory/scoped_refptr.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h"
 #include "third_party/blink/public/platform/web_focus_type.h"
 #include "third_party/blink/public/platform/web_insecure_request_policy.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -258,7 +260,8 @@
                              public ExecutionContext,
                              public DocumentShutdownNotifier,
                              public SynchronousMutationNotifier,
-                             public Supplementable<Document> {
+                             public Supplementable<Document>,
+                             public mojom::blink::NavigationInitiator {
   DEFINE_WRAPPERTYPEINFO();
   USING_GARBAGE_COLLECTED_MIXIN(Document);
 
@@ -1471,6 +1474,13 @@
   bool IsVerticalScrollEnforced() const { return is_vertical_scroll_enforced_; }
   bool IsLazyLoadPolicyEnforced() const;
 
+  void SendViolationReport(
+      mojom::blink::CSPViolationParamsPtr violation_params) override;
+  void BindNavigationInitiatorRequest(
+      mojom::blink::NavigationInitiatorRequest request) {
+    navigation_initiator_bindings_.AddBinding(this, std::move(request));
+  }
+
   LazyLoadImageObserver& EnsureLazyLoadImageObserver();
 
   // TODO(binji): See http://crbug.com/798572. This implementation shares the
@@ -1920,6 +1930,12 @@
   // This is set through feature policy 'vertical-scroll'.
   bool is_vertical_scroll_enforced_ = false;
 
+  // A list of all the navigation_initiator bindings owned by this document.
+  // Used to report CSP violations that result from CSP blocking
+  // navigation requests that were initiated by this document.
+  mojo::BindingSet<mojom::blink::NavigationInitiator>
+      navigation_initiator_bindings_;
+
   Member<LazyLoadImageObserver> lazy_load_image_observer_;
 
   // https://tc39.github.io/ecma262/#sec-agent-clusters
diff --git a/third_party/blink/renderer/core/events/input_event.cc b/third_party/blink/renderer/core/events/input_event.cc
index d172866..77342f8 100644
--- a/third_party/blink/renderer/core/events/input_event.cc
+++ b/third_party/blink/renderer/core/events/input_event.cc
@@ -73,7 +73,7 @@
 }
 
 InputEvent::InputType ConvertStringToInputType(const String& string_name) {
-  // TODO(chongz): Use binary search if the map goes larger.
+  // TODO(input-dev): Use binary search if the map goes larger.
   for (const auto& entry : kInputTypeStringNameMap) {
     if (string_name == entry.string_name)
       return entry.input_type;
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
index 5aa6477..469daa2 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -442,11 +442,13 @@
 
 void LocalFrameClientImpl::DispatchDidStartProvisionalLoad(
     DocumentLoader* loader,
-    ResourceRequest& request) {
+    ResourceRequest& request,
+    mojo::ScopedMessagePipeHandle navigation_initiator_handle) {
   if (web_frame_->Client()) {
     WrappedResourceRequest wrapped_request(request);
     web_frame_->Client()->DidStartProvisionalLoad(
-        WebDocumentLoaderImpl::FromDocumentLoader(loader), wrapped_request);
+        WebDocumentLoaderImpl::FromDocumentLoader(loader), wrapped_request,
+        std::move(navigation_initiator_handle));
   }
 }
 
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.h b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
index 857eb21..f0095ae 100644
--- a/third_party/blink/renderer/core/exported/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.h
@@ -96,8 +96,10 @@
                                        WebHistoryCommitType,
                                        bool content_initiated) override;
   void DispatchWillCommitProvisionalLoad() override;
-  void DispatchDidStartProvisionalLoad(DocumentLoader*,
-                                       ResourceRequest&) override;
+  void DispatchDidStartProvisionalLoad(
+      DocumentLoader*,
+      ResourceRequest&,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) override;
   void DispatchDidReceiveTitle(const String&) override;
   void DispatchDidChangeIcons(IconType) override;
   void DispatchDidCommitLoad(HistoryItem*,
diff --git a/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc b/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc
index f7300aa..81e4f85 100644
--- a/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc
+++ b/third_party/blink/renderer/core/exported/web_document_subresource_filter_test.cc
@@ -75,8 +75,10 @@
 class SubresourceFilteringWebFrameClient
     : public FrameTestHelpers::TestWebFrameClient {
  public:
-  void DidStartProvisionalLoad(WebDocumentLoader* data_source,
-                               WebURLRequest& request) override {
+  void DidStartProvisionalLoad(
+      WebDocumentLoader* data_source,
+      WebURLRequest& request,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) override {
     // Normally, the filter should be set when the load is committed. For
     // the sake of this test, however, inject it earlier to verify that it
     // is not consulted for the main resource load.
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index f968f22..b9ced29 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -7838,8 +7838,10 @@
   ~TestHistoryChildWebFrameClient() override = default;
 
   // FrameTestHelpers::TestWebFrameClient:
-  void DidStartProvisionalLoad(WebDocumentLoader* document_loader,
-                               WebURLRequest& request) override {
+  void DidStartProvisionalLoad(
+      WebDocumentLoader* document_loader,
+      WebURLRequest& request,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) override {
     replaces_current_history_item_ =
         document_loader->ReplacesCurrentHistoryItem();
   }
@@ -10650,7 +10652,10 @@
     EXPECT_EQ(0, callback_count_++);
     FrameTestHelpers::TestWebFrameClient::DidStartLoading();
   }
-  void DidStartProvisionalLoad(WebDocumentLoader*, WebURLRequest&) override {
+  void DidStartProvisionalLoad(
+      WebDocumentLoader*,
+      WebURLRequest&,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) override {
     EXPECT_EQ(1, callback_count_++);
   }
   void DidCommitProvisionalLoad(const WebHistoryItem&,
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 2980460..586be34 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -657,7 +657,7 @@
     SecurityViolationReportingPolicy reporting_policy) const {
   if (document.GetContentSecurityPolicy() &&
       !document.GetContentSecurityPolicy()->AllowPluginType(
-          type, type_attribute, url))
+          type, type_attribute, url, reporting_policy))
     return false;
 
   // CSP says that a plugin document in a nested browsing context should
@@ -671,7 +671,8 @@
                                             .Parent()
                                             ->GetSecurityContext()
                                             ->GetContentSecurityPolicy();
-    if (parent_csp && !parent_csp->AllowPluginType(type, type_attribute, url))
+    if (parent_csp && !parent_csp->AllowPluginType(type, type_attribute, url,
+                                                   reporting_policy))
       return false;
   }
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index c9e8f87..db016b0e 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -131,8 +131,10 @@
                                                WebHistoryCommitType,
                                                bool content_initiated) {}
   virtual void DispatchWillCommitProvisionalLoad() = 0;
-  virtual void DispatchDidStartProvisionalLoad(DocumentLoader*,
-                                               ResourceRequest&) = 0;
+  virtual void DispatchDidStartProvisionalLoad(
+      DocumentLoader*,
+      ResourceRequest&,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) = 0;
   virtual void DispatchDidReceiveTitle(const String&) = 0;
   virtual void DispatchDidChangeIcons(IconType) = 0;
   virtual void DispatchDidCommitLoad(HistoryItem*,
diff --git a/third_party/blink/renderer/core/html/html_element.idl b/third_party/blink/renderer/core/html/html_element.idl
index e646d88..6e1bef02 100644
--- a/third_party/blink/renderer/core/html/html_element.idl
+++ b/third_party/blink/renderer/core/html/html_element.idl
@@ -59,8 +59,8 @@
     [Affects=Nothing, SameObject, PerWorldBindings, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
 
     // Non-standard APIs
-    [Affects=Nothing, CEReactions, CustomElementCallbacks, RaisesException=Setter, MeasureAs=HTMLElementInnerText] attribute [TreatNullAs=NullString] DOMString innerText;
-    [Affects=Nothing, CEReactions, CustomElementCallbacks, RaisesException=Setter, MeasureAs=HTMLElementOuterText] attribute [TreatNullAs=NullString] DOMString outerText;
+    [Affects=Nothing, CEReactions, CustomElementCallbacks, RaisesException=Setter, MeasureAs=HTMLElementInnerText] attribute [TreatNullAs=EmptyString] DOMString innerText;
+    [Affects=Nothing, CEReactions, CustomElementCallbacks, RaisesException=Setter, MeasureAs=HTMLElementOuterText] attribute [TreatNullAs=EmptyString] DOMString outerText;
 };
 
 HTMLElement implements GlobalEventHandlers;
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index 0c6c66e7..ad708c86 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -1506,30 +1506,14 @@
 
 bool HTMLMediaElement::IsMediaDataCORSSameOrigin(
     const SecurityOrigin* origin) const {
-  // If a service worker handled the request, we don't know if the origin in the
-  // src is the same as the actual response URL so can't rely on URL checks
-  // alone. So detect an opaque response via
-  // DidGetOpaqueResponseFromServiceWorker().
-  if (GetWebMediaPlayer() &&
-      GetWebMediaPlayer()->DidGetOpaqueResponseFromServiceWorker()) {
-    return false;
-  }
+  if (!GetWebMediaPlayer())
+    return true;
 
-  // At this point, either a service worker was not used, or it didn't provide
-  // an opaque response, so continue with the normal checks.
-
-  // HasSingleSecurityOrigin() tells us whether the origin in the src
-  // is the same as the actual request (i.e. after redirects).
-  if (!HasSingleSecurityOrigin())
+  const auto network_state = GetWebMediaPlayer()->GetNetworkState();
+  if (network_state == WebMediaPlayer::kNetworkStateNetworkError)
     return false;
 
-  // DidPassCORSAccessCheck() means it was a successful CORS-enabled fetch (vs.
-  // non-CORS-enabled or failed). CanReadContent() does CheckAccess() on the
-  // URL plus allows data sources, to ensure that it is not a URL that requires
-  // CORS (basically same origin).
-  return (GetWebMediaPlayer() &&
-          GetWebMediaPlayer()->DidPassCORSAccessCheck()) ||
-         origin->CanReadContent(currentSrc());
+  return !GetWebMediaPlayer()->WouldTaintOrigin();
 }
 
 bool HTMLMediaElement::IsInCrossOriginFrame() const {
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h
index d2a28f3..f2d50264 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -268,11 +268,6 @@
   // of one of them here.
   using HTMLElement::GetExecutionContext;
 
-  bool HasSingleSecurityOrigin() const {
-    return GetWebMediaPlayer() ? GetWebMediaPlayer()->HasSingleSecurityOrigin()
-                               : true;
-  }
-
   bool IsFullscreen() const;
   virtual bool UsesOverlayFullscreenVideo() const { return false; }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.cc
index 09fff586..0899ba1 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.cc
@@ -25,12 +25,6 @@
 
 NGBaseFragmentBuilder::~NGBaseFragmentBuilder() = default;
 
-NGBaseFragmentBuilder& NGBaseFragmentBuilder::SetStyleVariant(
-    NGStyleVariant style_variant) {
-  style_variant_ = style_variant;
-  return *this;
-}
-
 NGBaseFragmentBuilder& NGBaseFragmentBuilder::SetStyle(
     scoped_refptr<const ComputedStyle> style,
     NGStyleVariant style_variant) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.h
index 62dcd951..5d8c610 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_base_fragment_builder.h
@@ -25,7 +25,10 @@
     DCHECK(style_);
     return *style_;
   }
-  NGBaseFragmentBuilder& SetStyleVariant(NGStyleVariant);
+  NGBaseFragmentBuilder& SetStyleVariant(NGStyleVariant style_variant) {
+    style_variant_ = style_variant;
+    return *this;
+  }
   NGBaseFragmentBuilder& SetStyle(scoped_refptr<const ComputedStyle>,
                                   NGStyleVariant);
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
index c951081..eddb206 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -20,33 +20,6 @@
 
 NGContainerFragmentBuilder::~NGContainerFragmentBuilder() = default;
 
-NGContainerFragmentBuilder& NGContainerFragmentBuilder::SetInlineSize(
-    LayoutUnit inline_size) {
-  DCHECK_GE(inline_size, LayoutUnit());
-  size_.inline_size = inline_size;
-  return *this;
-}
-
-NGContainerFragmentBuilder& NGContainerFragmentBuilder::SetEndMarginStrut(
-    const NGMarginStrut& end_margin_strut) {
-  end_margin_strut_ = end_margin_strut;
-  return *this;
-}
-
-NGContainerFragmentBuilder& NGContainerFragmentBuilder::SetExclusionSpace(
-    NGExclusionSpace&& exclusion_space) {
-  exclusion_space_ = std::move(exclusion_space);
-  return *this;
-}
-
-NGContainerFragmentBuilder&
-NGContainerFragmentBuilder::SetUnpositionedListMarker(
-    const NGUnpositionedListMarker& marker) {
-  DCHECK(!unpositioned_list_marker_ || !marker);
-  unpositioned_list_marker_ = marker;
-  return *this;
-}
-
 NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddChild(
     const NGLayoutResult& child,
     const NGLogicalOffset& child_offset) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
index 0db8023..43fc62a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -38,7 +38,11 @@
   LayoutUnit InlineSize() const { return size_.inline_size; }
   LayoutUnit BlockSize() const { return size_.block_size; }
   const NGLogicalSize& Size() const { return size_; }
-  NGContainerFragmentBuilder& SetInlineSize(LayoutUnit);
+  NGContainerFragmentBuilder& SetInlineSize(LayoutUnit inline_size) {
+    DCHECK_GE(inline_size, LayoutUnit());
+    size_.inline_size = inline_size;
+    return *this;
+  }
   void SetBlockSize(LayoutUnit block_size) { size_.block_size = block_size; }
 
   LayoutUnit BfcLineOffset() const { return bfc_line_offset_; }
@@ -61,16 +65,27 @@
     return *this;
   }
 
-  NGContainerFragmentBuilder& SetEndMarginStrut(const NGMarginStrut&);
+  NGContainerFragmentBuilder& SetEndMarginStrut(
+      const NGMarginStrut& end_margin_strut) {
+    end_margin_strut_ = end_margin_strut;
+    return *this;
+  }
 
   NGContainerFragmentBuilder& SetExclusionSpace(
-      NGExclusionSpace&& exclusion_space);
+      NGExclusionSpace&& exclusion_space) {
+    exclusion_space_ = std::move(exclusion_space);
+    return *this;
+  }
 
   const NGUnpositionedListMarker& UnpositionedListMarker() const {
     return unpositioned_list_marker_;
   }
   NGContainerFragmentBuilder& SetUnpositionedListMarker(
-      const NGUnpositionedListMarker&);
+      const NGUnpositionedListMarker& marker) {
+    DCHECK(!unpositioned_list_marker_ || !marker);
+    unpositioned_list_marker_ = marker;
+    return *this;
+  }
 
   virtual NGContainerFragmentBuilder& AddChild(const NGLayoutResult&,
                                                const NGLogicalOffset&);
@@ -123,7 +138,7 @@
       LayoutObject* inline_container);
 
   NGContainerFragmentBuilder& AddOutOfFlowDescendant(
-      NGOutOfFlowPositionedDescendant);
+      NGOutOfFlowPositionedDescendant descendant);
 
   void GetAndClearOutOfFlowDescendantCandidates(
       Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
index e9cebab5..f6a909a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
@@ -65,33 +65,6 @@
 
 NGFragmentBuilder::~NGFragmentBuilder() = default;
 
-NGFragmentBuilder& NGFragmentBuilder::SetIntrinsicBlockSize(
-    LayoutUnit intrinsic_block_size) {
-  intrinsic_block_size_ = intrinsic_block_size;
-  return *this;
-}
-
-NGFragmentBuilder& NGFragmentBuilder::SetBorders(const NGBoxStrut& border) {
-  DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
-  borders_ = border;
-  return *this;
-}
-
-NGFragmentBuilder& NGFragmentBuilder::SetPadding(const NGBoxStrut& padding) {
-  DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
-  padding_ = padding;
-  return *this;
-}
-
-NGFragmentBuilder& NGFragmentBuilder::SetPadding(
-    const NGLineBoxStrut& padding) {
-  DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
-  // Convert to flow-relative, because ToInlineBoxFragment() will convert
-  // the padding to physical coordinates using flow-relative writing-mode.
-  padding_ = NGBoxStrut(padding, IsFlippedLinesWritingMode(GetWritingMode()));
-  return *this;
-}
-
 NGContainerFragmentBuilder& NGFragmentBuilder::AddChild(
     scoped_refptr<const NGPhysicalFragment> child,
     const NGLogicalOffset& child_offset) {
@@ -244,17 +217,6 @@
   return BoxTypeFromLayoutObject(layout_object_);
 }
 
-NGFragmentBuilder& NGFragmentBuilder::SetBoxType(
-    NGPhysicalFragment::NGBoxType box_type) {
-  box_type_ = box_type;
-  return *this;
-}
-
-NGFragmentBuilder& NGFragmentBuilder::SetIsOldLayoutRoot() {
-  is_old_layout_root_ = true;
-  return *this;
-}
-
 void NGFragmentBuilder::AddBaseline(NGBaselineRequest request,
                                     LayoutUnit offset) {
 #if DCHECK_IS_ON()
@@ -269,18 +231,6 @@
   return JoinFragmentainerBreakValues(previous_break_after_, break_before);
 }
 
-scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToBoxFragment() {
-  DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
-  return ToBoxFragment(GetWritingMode());
-}
-
-scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToInlineBoxFragment() {
-  // The logical coordinate for inline box uses line-relative writing-mode, not
-  // flow-relative.
-  DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
-  return ToBoxFragment(ToLineWritingMode(GetWritingMode()));
-}
-
 scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToBoxFragment(
     WritingMode block_or_line_writing_mode) {
   DCHECK_EQ(offsets_.size(), children_.size());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
index a8940d7..cf662d0 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.h
@@ -39,10 +39,27 @@
 
   ~NGFragmentBuilder() override;
 
-  NGFragmentBuilder& SetIntrinsicBlockSize(LayoutUnit);
-  NGFragmentBuilder& SetBorders(const NGBoxStrut&);
-  NGFragmentBuilder& SetPadding(const NGBoxStrut&);
-  NGFragmentBuilder& SetPadding(const NGLineBoxStrut&);
+  NGFragmentBuilder& SetIntrinsicBlockSize(LayoutUnit intrinsic_block_size) {
+    intrinsic_block_size_ = intrinsic_block_size;
+    return *this;
+  }
+  NGFragmentBuilder& SetBorders(const NGBoxStrut& border) {
+    DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
+    borders_ = border;
+    return *this;
+  }
+  NGFragmentBuilder& SetPadding(const NGBoxStrut& padding) {
+    DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
+    padding_ = padding;
+    return *this;
+  }
+  NGFragmentBuilder& SetPadding(const NGLineBoxStrut& padding) {
+    DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
+    // Convert to flow-relative, because ToInlineBoxFragment() will convert
+    // the padding to physical coordinates using flow-relative writing-mode.
+    padding_ = NGBoxStrut(padding, IsFlippedLinesWritingMode(GetWritingMode()));
+    return *this;
+  }
 
   using NGContainerFragmentBuilder::AddChild;
 
@@ -123,8 +140,17 @@
   // do not provide a setter here.
 
   // Creates the fragment. Can only be called once.
-  scoped_refptr<NGLayoutResult> ToBoxFragment();
-  scoped_refptr<NGLayoutResult> ToInlineBoxFragment();
+  scoped_refptr<NGLayoutResult> ToBoxFragment() {
+    DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
+    return ToBoxFragment(GetWritingMode());
+  }
+  scoped_refptr<NGLayoutResult> ToInlineBoxFragment() {
+    // The logical coordinate for inline box uses line-relative writing-mode,
+    // not
+    // flow-relative.
+    DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
+    return ToBoxFragment(ToLineWritingMode(GetWritingMode()));
+  }
 
   scoped_refptr<NGLayoutResult> Abort(NGLayoutResult::NGLayoutResultStatus);
 
@@ -133,12 +159,18 @@
   OffsetVector& MutableOffsets() { return offsets_; }
 
   NGPhysicalFragment::NGBoxType BoxType() const;
-  NGFragmentBuilder& SetBoxType(NGPhysicalFragment::NGBoxType);
+  NGFragmentBuilder& SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
+    box_type_ = box_type;
+    return *this;
+  }
   NGFragmentBuilder& SetIsFieldsetContainer() {
     is_fieldset_container_ = true;
     return *this;
   }
-  NGFragmentBuilder& SetIsOldLayoutRoot();
+  NGFragmentBuilder& SetIsOldLayoutRoot() {
+    is_old_layout_root_ = true;
+    return *this;
+  }
 
   bool DidBreak() const { return did_break_; }
 
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index 63e1b57..5ab9ea7a 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -251,8 +251,10 @@
 
   void DispatchDidHandleOnloadEvents() override {}
   void DispatchWillCommitProvisionalLoad() override {}
-  void DispatchDidStartProvisionalLoad(DocumentLoader*,
-                                       ResourceRequest&) override {}
+  void DispatchDidStartProvisionalLoad(
+      DocumentLoader*,
+      ResourceRequest&,
+      mojo::ScopedMessagePipeHandle navigation_initiator_handle) override {}
   void DispatchDidReceiveTitle(const String&) override {}
   void DispatchDidChangeIcons(IconType) override {}
   void DispatchDidCommitLoad(HistoryItem*,
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index 5de13a0..d9460d4 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -44,6 +44,7 @@
 #include "base/unguessable_token.h"
 #include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink.h"
 #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
 #include "third_party/blink/public/platform/task_type.h"
@@ -911,12 +912,18 @@
       frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
                             : network::mojom::RequestContextFrameType::kNested);
 
+  mojo::ScopedMessagePipeHandle navigation_initiator_handle;
   if (origin_document && origin_document->GetContentSecurityPolicy()
                              ->ExperimentalFeaturesEnabled()) {
     WebContentSecurityPolicyList initiator_csp =
         origin_document->GetContentSecurityPolicy()
             ->ExposeForNavigationalChecks();
     resource_request.SetInitiatorCSP(initiator_csp);
+    mojom::blink::NavigationInitiatorPtr navigation_initiator;
+    auto request = mojo::MakeRequest(&navigation_initiator);
+    origin_document->BindNavigationInitiatorRequest(std::move(request));
+    navigation_initiator_handle =
+        navigation_initiator.PassInterface().PassHandle();
   }
 
   // Record the latest requiredCSP value that will be used when sending this
@@ -1000,8 +1007,9 @@
   // TODO(ananta):
   // We should get rid of the dependency on the DocumentLoader in consumers of
   // the DidStartProvisionalLoad() notification.
-  Client()->DispatchDidStartProvisionalLoad(provisional_document_loader_,
-                                            resource_request);
+  Client()->DispatchDidStartProvisionalLoad(
+      provisional_document_loader_, resource_request,
+      std::move(navigation_initiator_handle));
   probe::didStartProvisionalLoad(frame_);
   virtual_time_pauser_.PauseVirtualTime();
   DCHECK(provisional_document_loader_);
@@ -1096,7 +1104,8 @@
 
   frame_->GetFrameScheduler()->DidStartProvisionalLoad(frame_->IsMainFrame());
   Client()->DispatchDidStartProvisionalLoad(provisional_document_loader_,
-                                            resource_request);
+                                            resource_request,
+                                            mojo::ScopedMessagePipeHandle());
   probe::didStartProvisionalLoad(frame_);
   virtual_time_pauser_.PauseVirtualTime();
 
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
index 5b5a735..5c804456 100644
--- a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
+++ b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -425,12 +425,12 @@
    */
   static async _copyResponse(request) {
     const contentData = await request.contentData();
-    let content = contentData.content;
-    if (contentData.encoded) {
-      content = Common.ContentProvider.contentAsDataURL(
-          contentData.content, request.mimeType, contentData.encoded, contentData.encoded ? 'utf-8' : null);
-    }
-    InspectorFrontendHost.copyText(content || '');
+    let content = contentData.content || '';
+    if (!request.contentType().isTextType())
+      content = Common.ContentProvider.contentAsDataURL(content, request.mimeType, contentData.encoded);
+    else if (contentData.encoded)
+      content = window.atob(content);
+    InspectorFrontendHost.copyText(content);
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js b/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js
index 7c9d3d67..a0ad048 100644
--- a/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js
+++ b/third_party/blink/renderer/devtools/front_end/network/RequestPreviewView.js
@@ -63,8 +63,10 @@
     if (!whitelist.has(this.request.mimeType))
       return null;
 
+    const content = contentData.encoded ? window.atob(contentData.content) : contentData.content;
+
     // http://crbug.com/767393 - DevTools should recognize JSON regardless of the content type
-    const jsonView = await SourceFrame.JSONView.createView(contentData.content);
+    const jsonView = await SourceFrame.JSONView.createView(content);
     if (jsonView)
       return jsonView;
 
diff --git a/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js b/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js
index ff36c807..7f5d9017 100644
--- a/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js
+++ b/third_party/blink/renderer/devtools/front_end/network/RequestResponseView.js
@@ -78,9 +78,8 @@
       return null;
     }
 
-    const contentProvider = new Network.DecodingContentProvider(request);
     const highlighterType = request.resourceType().canonicalMimeType() || request.mimeType;
-    sourceView = SourceFrame.ResourceSourceFrame.createSearchableView(contentProvider, highlighterType);
+    sourceView = SourceFrame.ResourceSourceFrame.createSearchableView(request, highlighterType);
     request[Network.RequestResponseView._sourceViewSymbol] = sourceView;
     return sourceView;
   }
@@ -137,59 +136,3 @@
 };
 
 Network.RequestResponseView._sourceViewSymbol = Symbol('RequestResponseSourceView');
-
-/**
- * @implements {Common.ContentProvider}
- */
-Network.DecodingContentProvider = class {
-  /**
-   * @param {!SDK.NetworkRequest} request
-   */
-  constructor(request) {
-    this._request = request;
-  }
-
-  /**
-   * @override
-   * @return {string}
-   */
-  contentURL() {
-    return this._request.contentURL();
-  }
-
-  /**
-   * @override
-   * @return {!Common.ResourceType}
-   */
-  contentType() {
-    return this._request.resourceType();
-  }
-
-  /**
-   * @override
-   * @return {!Promise<boolean>}
-   */
-  contentEncoded() {
-    return Promise.resolve(false);
-  }
-
-  /**
-   * @override
-   * @return {!Promise<?string>}
-   */
-  async requestContent() {
-    const contentData = await this._request.contentData();
-    return contentData.encoded ? window.atob(contentData.content || '') : contentData.content;
-  }
-
-  /**
-   * @override
-   * @param {string} query
-   * @param {boolean} caseSensitive
-   * @param {boolean} isRegex
-   * @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>}
-   */
-  searchInContent(query, caseSensitive, isRegex) {
-    return this._request.searchInContent(query, caseSensitive, isRegex);
-  }
-};
diff --git a/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js b/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
index cee68f46..526b4c5d 100644
--- a/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
+++ b/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -168,7 +168,9 @@
     const selectedNode = /** @type {!Network.ResourceWebSocketFrameNode} */ (event.data);
     this._currentSelectedNode = selectedNode;
     const contentProvider = selectedNode.contentProvider();
-    const content = await contentProvider.requestContent();
+    let content = await contentProvider.requestContent();
+    if (await contentProvider.contentEncoded())
+      content = window.atob(content);
     const jsonView = await SourceFrame.JSONView.createView(content);
     if (this._currentSelectedNode !== selectedNode)
       return;
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js b/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
index 5cb13a9..e8a5fc0 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
@@ -602,6 +602,9 @@
         ],
         ['audio', 'video']);
     this._createEventListenerBreakpoints(
+        Common.UIString('Picture-in-Picture'), ['enterpictureinpicture', 'leavepictureinpicture'], ['video']);
+    this._createEventListenerBreakpoints(Common.UIString('Picture-in-Picture'), ['resize'], ['PictureInPictureWindow']);
+    this._createEventListenerBreakpoints(
         Common.UIString('Clipboard'), ['copy', 'cut', 'paste', 'beforecopy', 'beforecut', 'beforepaste'], ['*']);
     this._createEventListenerBreakpoints(
         Common.UIString('Control'),
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js b/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
index 49251c8..a00645cc6 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
@@ -1073,9 +1073,12 @@
     if (!this._contentDataProvider)
       return SDK.NetworkManager.searchInRequest(this, query, caseSensitive, isRegex);
 
-    const content = await this.requestContent();
+    const contentData = await this.contentData();
+    let content = contentData.content;
     if (!content)
       return [];
+    if (contentData.encoded)
+      content = window.atob(content);
     return Common.ContentProvider.performSearchInContent(content, query, caseSensitive, isRegex);
   }
 
@@ -1145,19 +1148,15 @@
   /**
    * @param {!Element} image
    */
-  populateImageSource(image) {
-    /**
-     * @param {?string} content
-     * @this {SDK.NetworkRequest}
-     */
-    function onResourceContent(content) {
-      let imageSrc = Common.ContentProvider.contentAsDataURL(content, this._mimeType, true);
-      const cacheControl = this.responseHeaderValue('cache-control');
-      if (imageSrc === null && (!cacheControl || !cacheControl.includes('no-cache')))
+  async populateImageSource(image) {
+    const {content, encoded} = await this.contentData();
+    let imageSrc = Common.ContentProvider.contentAsDataURL(content, this._mimeType, encoded);
+    if (imageSrc === null) {
+      const cacheControl = this.responseHeaderValue('cache-control') || '';
+      if (!cacheControl.includes('no-cache'))
         imageSrc = this._url;
-      image.src = imageSrc;
     }
-    this.requestContent().then(onResourceContent.bind(this));
+    image.src = imageSrc;
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/Resource.js b/third_party/blink/renderer/devtools/front_end/sdk/Resource.js
index 8f0c412..10a26572 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/Resource.js
+++ b/third_party/blink/renderer/devtools/front_end/sdk/Resource.js
@@ -229,19 +229,10 @@
   /**
    * @param {!Element} image
    */
-  populateImageSource(image) {
-    /**
-     * @param {?string} content
-     * @this {SDK.Resource}
-     */
-    function onResourceContent(content) {
-      let imageSrc = Common.ContentProvider.contentAsDataURL(content, this._mimeType, true);
-      if (imageSrc === null)
-        imageSrc = this._url;
-      image.src = imageSrc;
-    }
-
-    this.requestContent().then(onResourceContent.bind(this));
+  async populateImageSource(image) {
+    const content = await this.requestContent();
+    const encoded = this._contentEncoded;
+    image.src = Common.ContentProvider.contentAsDataURL(content, this._mimeType, encoded) || this._url;
   }
 
   _requestFinished() {
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js b/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
index f8fc1210..bed1ce2 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
@@ -98,12 +98,13 @@
 
     const contentEncoded = await this._contentProvider.contentEncoded();
     this._cachedContent = content;
-    let imageSrc = 'data:' + this._mimeType + (contentEncoded ? ';base64,' : ',') + content;
+    let imageSrc = Common.ContentProvider.contentAsDataURL(content, this._mimeType, contentEncoded);
     if (content === null)
       imageSrc = this._url;
     const loadPromise = new Promise(x => this._imagePreviewElement.onload = x);
     this._imagePreviewElement.src = imageSrc;
-    this._sizeLabel.setText(Number.bytesToString(this._base64ToSize(content)));
+    const size = content && !contentEncoded ? content.length : this._base64ToSize(content);
+    this._sizeLabel.setText(Number.bytesToString(size));
     await loadPromise;
     this._dimensionsLabel.setText(
         Common.UIString('%d × %d', this._imagePreviewElement.naturalWidth, this._imagePreviewElement.naturalHeight));
@@ -114,10 +115,10 @@
    * @return {number}
    */
   _base64ToSize(content) {
-    if (!content || !content.length)
+    if (!content)
       return 0;
-    let size = (content.length || 0) * 3 / 4;
-    if (content.length > 0 && content[content.length - 1] === '=')
+    let size = content.length * 3 / 4;
+    if (content[content.length - 1] === '=')
       size--;
     if (content.length > 1 && content[content.length - 2] === '=')
       size--;
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js b/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js
index eaa9bd58..8d27446 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/PreviewFactory.js
@@ -9,10 +9,6 @@
    * @returns {!Promise<?UI.Widget>}
    */
   static async createPreview(provider, mimeType) {
-    const content = await provider.requestContent();
-    if (!content)
-      return new UI.EmptyWidget(Common.UIString('Nothing to preview'));
-
     let resourceType = Common.ResourceType.fromMimeType(mimeType);
     if (resourceType === Common.resourceTypes.Other)
       resourceType = provider.contentType();
@@ -24,6 +20,13 @@
         return new SourceFrame.FontView(mimeType, provider);
     }
 
+    let content = await provider.requestContent();
+    if (!content)
+      return new UI.EmptyWidget(Common.UIString('Nothing to preview'));
+
+    if (await provider.contentEncoded())
+      content = window.atob(content);
+
     const parsedXML = SourceFrame.XMLView.parseXML(content, mimeType);
     if (parsedXML)
       return SourceFrame.XMLView.createSearchableView(parsedXML);
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js b/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js
index 32af2b9..707fd8c 100644
--- a/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js
+++ b/third_party/blink/renderer/devtools/front_end/source_frame/ResourceSourceFrame.js
@@ -36,7 +36,12 @@
    * @param {boolean=} autoPrettyPrint
    */
   constructor(resource, autoPrettyPrint) {
-    super(resource.requestContent.bind(resource));
+    super(async () => {
+      let content = await resource.requestContent();
+      if (await resource.contentEncoded())
+        content = window.atob(content);
+      return content;
+    });
     this._resource = resource;
     this.setCanPrettyPrint(this._resource.contentType().isDocumentOrScriptOrStyleSheet(), autoPrettyPrint);
   }
diff --git a/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js b/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js
index 034aa81a..38f6d19 100644
--- a/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js
+++ b/third_party/blink/renderer/devtools/front_end/test_runner/TestRunner.js
@@ -412,10 +412,12 @@
  * Doesn't append sourceURL to snippets evaluated in inspected page
  * to avoid churning test expectations
  * @param {string} code
+ * @param {boolean=} userGesture
  * @return {!Promise<*>}
  */
-TestRunner.evaluateInPageAnonymously = async function(code) {
-  const response = await TestRunner.RuntimeAgent.invoke_evaluate({expression: code, objectGroup: 'console'});
+TestRunner.evaluateInPageAnonymously = async function(code, userGesture) {
+  const response =
+      await TestRunner.RuntimeAgent.invoke_evaluate({expression: code, objectGroup: 'console', userGesture});
   if (!response[Protocol.Error])
     return response.result.value;
   TestRunner.addResult(
@@ -461,10 +463,11 @@
 
 /**
  * @param {string} code
+ * @param {boolean=} userGesture
  */
-TestRunner.evaluateInPageWithTimeout = function(code) {
+TestRunner.evaluateInPageWithTimeout = function(code, userGesture) {
   // FIXME: we need a better way of waiting for chromium events to happen
-  TestRunner.evaluateInPageAnonymously('setTimeout(unescape(\'' + escape(code) + '\'), 1)');
+  TestRunner.evaluateInPageAnonymously('setTimeout(unescape(\'' + escape(code) + '\'), 1)', userGesture);
 };
 
 /**
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc
index 0526f81..ce6c4f4 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_impl.cc
@@ -10,7 +10,7 @@
 
 P2PQuicStreamImpl::P2PQuicStreamImpl(quic::QuicStreamId id,
                                      quic::QuicSession* session)
-    : quic::QuicStream(id, session, /*is_static=*/false) {}
+    : quic::QuicStream(id, session, /*is_static=*/false, quic::BIDIRECTIONAL) {}
 
 P2PQuicStreamImpl::~P2PQuicStreamImpl() {}
 
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
index fb348f02..8cf3a92 100644
--- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -958,21 +958,4 @@
   }
 }
 
-bool BaseAudioContext::WouldTaintOrigin(const KURL& url) const {
-  // Data URLs don't taint the origin.
-  if (url.ProtocolIsData()) {
-    return false;
-  }
-
-  Document* document = GetDocument();
-  if (document && document->GetSecurityOrigin()) {
-    // The origin is tainted if and only if we cannot read content from the URL.
-    return !document->GetSecurityOrigin()->CanRequest(url);
-  }
-
-  // Be conservative and assume it's tainted if it's not a data url and if we
-  // can't get the security origin of the document.
-  return true;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
index d0a57608..ae933f2 100644
--- a/third_party/blink/renderer/modules/webaudio/base_audio_context.h
+++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
@@ -296,13 +296,6 @@
   // Does nothing when the worklet global scope does not exist.
   void UpdateWorkletGlobalScopeOnRenderingThread();
 
-  // Returns true if the URL would taint the origin so that we shouldn't be
-  // allowing media to played through webaudio.
-  // TODO(crbug.com/845913): This should really be on an AudioContext.  Move
-  // this when we move the media stuff from BaseAudioContext to AudioContext, as
-  // requried by the spec.
-  bool WouldTaintOrigin(const KURL& url) const;
-
  protected:
   enum ContextType { kRealtimeContext, kOfflineContext };
 
diff --git a/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc b/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc
index 67289c4..d7b07b5f 100644
--- a/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc
@@ -136,19 +136,7 @@
 }
 
 bool MediaElementAudioSourceHandler::WouldTaintOrigin() {
-  // If we're cross-origin and allowed access vie CORS, we're not tainted.
-  if (MediaElement()->GetWebMediaPlayer()->DidPassCORSAccessCheck()) {
-    return false;
-  }
-
-  // Handles the case where the url is a redirect to another site that we're not
-  // allowed to access.
-  if (!MediaElement()->HasSingleSecurityOrigin()) {
-    return true;
-  }
-
-  // Test to see if the current media URL taint the origin of the audio context?
-  return Context()->WouldTaintOrigin(MediaElement()->currentSrc());
+  return MediaElement()->GetWebMediaPlayer()->WouldTaintOrigin();
 }
 
 void MediaElementAudioSourceHandler::PrintCORSMessage(const String& message) {
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc
index e93ecb8..00b17b6 100644
--- a/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -391,7 +391,7 @@
   return resource_request_->IsAdResource();
 }
 
-const WebContentSecurityPolicyList& WebURLRequest::GetNavigationCSP() const {
+const WebContentSecurityPolicyList& WebURLRequest::GetInitiatorCSP() const {
   return resource_request_->GetInitiatorCSP();
 }
 
diff --git a/third_party/blink/renderer/platform/testing/empty_web_media_player.h b/third_party/blink/renderer/platform/testing/empty_web_media_player.h
index 89981be1..6e577183 100644
--- a/third_party/blink/renderer/platform/testing/empty_web_media_player.h
+++ b/third_party/blink/renderer/platform/testing/empty_web_media_player.h
@@ -50,9 +50,7 @@
   ReadyState GetReadyState() const override { return kReadyStateHaveNothing; }
   WebString GetErrorMessage() const override;
   bool DidLoadingProgress() override { return false; }
-  bool DidGetOpaqueResponseFromServiceWorker() const override { return false; }
-  bool HasSingleSecurityOrigin() const override { return true; }
-  bool DidPassCORSAccessCheck() const override { return true; }
+  bool WouldTaintOrigin() const override { return false; }
   double MediaTimeForTimeValue(double time_value) const override {
     return time_value;
   };
diff --git a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
index 87cb0a9..56e04fa 100644
--- a/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
+++ b/tools/android/customtabs_benchmark/java/src/org/chromium/customtabs/test/MainActivity.java
@@ -51,7 +51,8 @@
     private static final int NONE = -1;
     // Common key between the benchmark modes.
     private static final String URL_KEY = "url";
-
+    private static final String PARALLEL_URL_KEY = "parallel_url";
+    private static final String DEFAULT_REFERRER_URL = "https://www.google.com";
     // Keys for the WebView / Custom Tabs comparison.
     static final String INTENT_SENT_EXTRA = "intent_sent_ms";
     private static final String USE_WEBVIEW_KEY = "use_webview";
@@ -62,6 +63,15 @@
     private static final String SET_SPECULATION_MODE = "setSpeculationModeForSession";
     private static final String SET_IGNORE_URL_FRAGMENTS_FOR_SESSION =
             "setIgnoreUrlFragmentsForSession";
+
+    private static final String ADD_VERIFIED_ORIGN = "addVerifiedOriginForSession";
+    private static final String ENABLE_PARALLEL_REQUEST = "enableParallelRequestForSession";
+    private static final String PARALLEL_REQUEST_REFERRER_KEY =
+            "android.support.customtabs.PARALLEL_REQUEST_REFERRER";
+    private static final String PARALLEL_REQUEST_URL_KEY =
+            "android.support.customtabs.PARALLEL_REQUEST_URL";
+    private static final int PARALLEL_REQUEST_MIN_DELAY_AFTER_WARMUP = 3000;
+
     private static final int NO_SPECULATION = 0;
     private static final int PRERENDER = 2;
     private static final int HIDDEN_TAB = 3;
@@ -72,6 +82,8 @@
     private RadioButton mChromeRadioButton;
     private RadioButton mWebViewRadioButton;
     private CheckBox mWarmupCheckbox;
+    private CheckBox mParallelUrlCheckBox;
+    private EditText mParallelUrlEditText;
     private long mIntentSentMs;
 
     @Override
@@ -100,12 +112,17 @@
         mChromeRadioButton = (RadioButton) findViewById(R.id.radio_chrome);
         mWebViewRadioButton = (RadioButton) findViewById(R.id.radio_webview);
         mWarmupCheckbox = (CheckBox) findViewById(R.id.warmup_checkbox);
+        mParallelUrlCheckBox = (CheckBox) findViewById(R.id.parallel_url_checkbox);
+        mParallelUrlEditText = (EditText) findViewById(R.id.parallel_url_text);
+
         Button goButton = (Button) findViewById(R.id.go_button);
 
         mUrlEditText.setOnClickListener(this);
         mChromeRadioButton.setOnClickListener(this);
         mWebViewRadioButton.setOnClickListener(this);
         mWarmupCheckbox.setOnClickListener(this);
+        mParallelUrlCheckBox.setOnClickListener(this);
+        mParallelUrlEditText.setOnClickListener(this);
         goButton.setOnClickListener(this);
     }
 
@@ -117,9 +134,14 @@
         boolean useChrome = mChromeRadioButton.isChecked();
         boolean useWebView = mWebViewRadioButton.isChecked();
         String url = mUrlEditText.getText().toString();
+        boolean willRequestParallelUrl = mParallelUrlCheckBox.isChecked();
+        String parallelUrl = null;
+        if (willRequestParallelUrl) {
+            parallelUrl = mParallelUrlEditText.getText().toString();
+        }
 
         if (id == R.id.go_button) {
-            customTabsWebViewBenchmark(url, useChrome, useWebView, warmup);
+            customTabsWebViewBenchmark(url, useChrome, useWebView, warmup, parallelUrl);
         }
     }
 
@@ -139,17 +161,18 @@
     private void startCustomTabsWebViewBenchmark(Intent intent) {
         Bundle extras = intent.getExtras();
         String url = extras.getString(URL_KEY);
+        String parallelUrl = extras.getString(PARALLEL_URL_KEY);
         boolean useWebView = extras.getBoolean(USE_WEBVIEW_KEY);
         boolean useChrome = !useWebView;
         boolean warmup = extras.getBoolean(WARMUP_KEY);
-        customTabsWebViewBenchmark(url, useChrome, useWebView, warmup);
+        customTabsWebViewBenchmark(url, useChrome, useWebView, warmup, parallelUrl);
     }
 
     /** Start the CustomTabs / WebView comparison benchmark. */
     private void customTabsWebViewBenchmark(
-            String url, boolean useChrome, boolean useWebView, boolean warmup) {
+            String url, boolean useChrome, boolean useWebView, boolean warmup, String parallelUrl) {
         if (useChrome) {
-            launchChrome(url, warmup);
+            launchChrome(url, warmup, parallelUrl);
         } else {
             assert useWebView;
             launchWebView(url);
@@ -164,11 +187,11 @@
         startActivity(intent);
     }
 
-    private void launchChrome(final String url, final boolean warmup) {
+    private void launchChrome(final String url, final boolean warmup, String parallelUrl) {
         CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
             @Override
             public void onCustomTabsServiceConnected(ComponentName name, CustomTabsClient client) {
-                launchChromeIntent(url, warmup, client);
+                launchChromeIntent(url, warmup, client, parallelUrl);
             }
 
             @Override
@@ -177,7 +200,35 @@
         CustomTabsClient.bindCustomTabsService(this, DEFAULT_PACKAGE, connection);
     }
 
-    private void launchChromeIntent(String url, boolean warmup, CustomTabsClient client) {
+    private static void maybePrepareParallelUrlRequest(String parallelUrl, CustomTabsClient client,
+            CustomTabsIntent intent, IBinder sessionBinder) {
+        if (parallelUrl == null || parallelUrl.length() == 0) {
+            Log.w(TAG, "null or empty parallelUrl");
+            return;
+        }
+
+        Uri parallelUri = Uri.parse(parallelUrl);
+        Bundle params = new Bundle();
+        BundleCompat.putBinder(params, "session", sessionBinder);
+
+        Uri referrerUri = Uri.parse(DEFAULT_REFERRER_URL);
+        params.putParcelable("origin", referrerUri);
+
+        Bundle result = client.extraCommand(ADD_VERIFIED_ORIGN, params);
+        boolean ok = (result != null) && result.getBoolean(ADD_VERIFIED_ORIGN);
+        if (!ok) throw new RuntimeException("Cannot add verified origin");
+
+        result = client.extraCommand(ENABLE_PARALLEL_REQUEST, params);
+        ok = (result != null) && result.getBoolean(ENABLE_PARALLEL_REQUEST);
+        if (!ok) throw new RuntimeException("Cannot enable Parallel Request");
+        Log.w(TAG, "enabled Parallel Request");
+
+        intent.intent.putExtra(PARALLEL_REQUEST_URL_KEY, parallelUri);
+        intent.intent.putExtra(PARALLEL_REQUEST_REFERRER_KEY, referrerUri);
+    }
+
+    private void launchChromeIntent(
+            String url, boolean warmup, CustomTabsClient client, String parallelUrl) {
         CustomTabsCallback callback = new CustomTabsCallback() {
             private long mNavigationStartOffsetMs;
 
@@ -202,6 +253,11 @@
         final CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder(session).build();
         final Uri uri = Uri.parse(url);
 
+        IBinder sessionBinder = BundleCompat.getBinder(
+                customTabsIntent.intent.getExtras(), CustomTabsIntent.EXTRA_SESSION);
+        assert sessionBinder != null;
+        maybePrepareParallelUrlRequest(parallelUrl, client, customTabsIntent, sessionBinder);
+
         if (warmup) {
             client.warmup(0);
             mHandler.postDelayed(new Runnable() {
@@ -228,11 +284,14 @@
     private void startCustomTabsBenchmark(Intent intent) {
         String url = intent.getStringExtra(URL_KEY);
         if (url == null) url = DEFAULT_URL;
+        String parallelUrl = intent.getStringExtra(PARALLEL_URL_KEY);
+
         String speculatedUrl = intent.getStringExtra("speculated_url");
         if (speculatedUrl == null) speculatedUrl = url;
         String packageName = intent.getStringExtra("package_name");
         if (packageName == null) packageName = DEFAULT_PACKAGE;
         boolean warmup = intent.getBooleanExtra("warmup", false);
+
         boolean skipLauncherActivity = intent.getBooleanExtra("skip_launcher_activity", false);
         int delayToMayLaunchUrl = intent.getIntExtra("delay_to_may_launch_url", NONE);
         int delayToLaunchUrl = intent.getIntExtra("delay_to_launch_url", NONE);
@@ -240,8 +299,17 @@
         if (speculationMode == null) speculationMode = "prerender";
         int timeoutSeconds = intent.getIntExtra("timeout", NONE);
 
+        if (parallelUrl != null && !warmup) {
+            Log.w(TAG, "Parallel URL provided, forcing warmup");
+            warmup = true;
+            delayToLaunchUrl = Math.max(delayToLaunchUrl, PARALLEL_REQUEST_MIN_DELAY_AFTER_WARMUP);
+            delayToMayLaunchUrl =
+                    Math.max(delayToMayLaunchUrl, PARALLEL_REQUEST_MIN_DELAY_AFTER_WARMUP);
+        }
+
         launchCustomTabs(packageName, speculatedUrl, url, warmup, skipLauncherActivity,
-                speculationMode, delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds);
+                speculationMode, delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds,
+                parallelUrl);
     }
 
     private final class CustomCallback extends CustomTabsCallback {
@@ -251,6 +319,7 @@
         private final String mSpeculationMode;
         private final int mDelayToMayLaunchUrl;
         private final int mDelayToLaunchUrl;
+        public boolean mWarmupCompleted = false;
         private long mIntentSentMs = NONE;
         private long mPageLoadStartedMs = NONE;
         private long mPageLoadFinishedMs = NONE;
@@ -287,6 +356,11 @@
 
         @Override
         public void extraCallback(String callbackName, Bundle args) {
+            if ("onWarmupCompleted".equals(callbackName)) {
+                mWarmupCompleted = true;
+                return;
+            }
+
             if (!"NavigationMetrics".equals(callbackName)) {
                 Log.w(TAG, "Unknown extra callback skipped: " + callbackName);
                 return;
@@ -410,9 +484,10 @@
     private void onCustomTabsServiceConnected(CustomTabsClient client, final Uri speculatedUri,
             final Uri uri, final CustomCallback cb, boolean warmup, boolean skipLauncherActivity,
             String speculationMode, int delayToMayLaunchUrl, final int delayToLaunchUrl,
-            final int timeoutSeconds, final String packageName) {
+            final int timeoutSeconds, final String packageName, final String parallelUrl) {
         final CustomTabsSession session = client.newSession(cb);
         final CustomTabsIntent intent = (new CustomTabsIntent.Builder(session)).build();
+
         logMemory(packageName, "OnServiceConnected");
 
         IBinder sessionBinder =
@@ -424,6 +499,13 @@
             @Override
             public void run() {
                 logMemory(packageName, "BeforeLaunch");
+
+                if (cb.mWarmupCompleted) {
+                    maybePrepareParallelUrlRequest(parallelUrl, client, intent, sessionBinder);
+                } else {
+                    Log.e(TAG, "not warmed up yet!");
+                }
+
                 intent.launchUrl(MainActivity.this, uri);
                 cb.recordIntentHasBeenSent();
                 if (timeoutSeconds != NONE) cb.logMetricsAndFinishDelayed(timeoutSeconds * 1000);
@@ -448,7 +530,8 @@
 
     private void launchCustomTabs(final String packageName, String speculatedUrl, String url,
             final boolean warmup, final boolean skipLauncherActivity, final String speculationMode,
-            final int delayToMayLaunchUrl, final int delayToLaunchUrl, final int timeoutSeconds) {
+            final int delayToMayLaunchUrl, final int delayToLaunchUrl, final int timeoutSeconds,
+            String parallelUrl) {
         final CustomCallback cb = new CustomCallback(packageName, warmup, skipLauncherActivity,
                 speculationMode, delayToMayLaunchUrl, delayToLaunchUrl);
         final Uri speculatedUri = Uri.parse(speculatedUrl);
@@ -460,7 +543,8 @@
                             ComponentName name, final CustomTabsClient client) {
                         MainActivity.this.onCustomTabsServiceConnected(client, speculatedUri, uri,
                                 cb, warmup, skipLauncherActivity, speculationMode,
-                                delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds, packageName);
+                                delayToMayLaunchUrl, delayToLaunchUrl, timeoutSeconds, packageName,
+                                parallelUrl);
                     }
 
                     @Override
diff --git a/tools/android/customtabs_benchmark/res/layout/main.xml b/tools/android/customtabs_benchmark/res/layout/main.xml
index 6c3a9b0..26f92ef 100644
--- a/tools/android/customtabs_benchmark/res/layout/main.xml
+++ b/tools/android/customtabs_benchmark/res/layout/main.xml
@@ -29,6 +29,7 @@
         android:text="@string/default_url"
         android:ems="10"
         android:id="@+id/url_text" />
+
     <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
@@ -50,6 +51,27 @@
         android:layout_height="wrap_content"
         android:id="@+id/warmup_checkbox" />
 
+    <CheckBox
+        android:text="@string/will_load_parallel_url"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/parallel_url_checkbox" />
+
+    <TextView
+        android:text="@string/parallel_url_to_load"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/parallel_url_label"
+        android:labelFor="@+id/parallel_url_text" />
+
+    <EditText
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:inputType="textUri"
+        android:text="@string/default_parallel_url"
+        android:ems="10"
+        android:id="@+id/parallel_url_text" />
+
     <Button
         android:text="@string/go"
         android:layout_width="match_parent"
diff --git a/tools/android/customtabs_benchmark/res/values/strings.xml b/tools/android/customtabs_benchmark/res/values/strings.xml
index 705141c..77d8f0e0 100644
--- a/tools/android/customtabs_benchmark/res/values/strings.xml
+++ b/tools/android/customtabs_benchmark/res/values/strings.xml
@@ -5,4 +5,7 @@
   <string name="webview">WebView</string>
   <string name="warmup">Call Warmup (3s delay)</string>
   <string name="go">Go</string>
+  <string name="will_load_parallel_url">Load a first URL in parallel:</string>
+  <string name="parallel_url_to_load">URL to Load in parallel:</string>
+  <string name="default_parallel_url">http://www.android.com</string>
 </resources>
diff --git a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
index 0d033c2..a907ce77 100755
--- a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
+++ b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
@@ -40,15 +40,18 @@
 _INVALID_VALUE = -1
 
 
-def RunOnce(device, url, speculated_url, warmup, skip_launcher_activity,
-            speculation_mode, delay_to_may_launch_url, delay_to_launch_url,
-            cold, chrome_args, reset_chrome_state):
+def RunOnce(device, url, speculated_url, parallel_url, warmup,
+            skip_launcher_activity, speculation_mode, delay_to_may_launch_url,
+            delay_to_launch_url, cold, chrome_args, reset_chrome_state):
   """Runs a test on a device once.
 
   Args:
     device: (DeviceUtils) device to run the tests on.
-    url: (str) URL to load.
+    url: (str) URL to load. End of the redirect chain when using a
+        parallel request.
     speculated_url: (str) Speculated URL.
+    parallel_url: ([str]) URL to load in parallel, typically
+        the start of the redirect chain.
     warmup: (bool) Whether to call warmup.
     skip_launcher_activity: (bool) Whether to skip the launcher activity.
     speculation_mode: (str) Speculation Mode.
@@ -57,7 +60,7 @@
     cold: (bool) Whether the page cache should be dropped.
     chrome_args: ([str]) List of arguments to pass to Chrome.
     reset_chrome_state: (bool) Whether to reset the Chrome local state before
-                        the run.
+        the run.
 
   Returns:
     The output line (str), like this (one line only):
@@ -81,6 +84,7 @@
         activity='org.chromium.customtabs.test.MainActivity',
         extras={'url': str(url),
                 'speculated_url': str(speculated_url),
+                'parallel_url': str (parallel_url),
                 'warmup': warmup,
                 'skip_launcher_activity': skip_launcher_activity,
                 'speculation_mode': str(speculation_mode),
@@ -166,7 +170,10 @@
             '--force-fieldtrial-params=trial.group:mode/external-prefetching',
             '--enable-features=SpeculativeResourcePrefetching<trial'])
 
-      result = RunOnce(device, config['url'], config['speculated_url'],
+      result = RunOnce(device,
+                       config['url'],
+                       config['speculated_url'],
+                       config['parallel_url'],
                        config['warmup'], config['skip_launcher_activity'],
                        config['speculation_mode'],
                        config['delay_to_may_launch_url'],
@@ -220,6 +227,8 @@
                     help='URL to call mayLaunchUrl() with.',)
   parser.add_option('--url', help='URL to navigate to.',
                     default='https://www.android.com')
+  parser.add_option('--parallel_url', help='URL to navigate to.in parallel, '
+                    'e.g. the start of the redirect chain.')
   parser.add_option('--warmup', help='Call warmup.', default=False,
                     action='store_true')
   parser.add_option('--skip_launcher_activity',
@@ -265,6 +274,7 @@
       'url': options.url,
       'skip_launcher_activity': options.skip_launcher_activity,
       'speculated_url': options.speculated_url or options.url,
+      'parallel_url': options.parallel_url,
       'warmup': options.warmup,
       'speculation_mode': options.speculation_mode,
       'delay_to_may_launch_url': options.delay_to_may_launch_url,
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index c5eeda3..6cd0319 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -27,7 +27,7 @@
 # Do NOT CHANGE this if you don't know what you're doing -- see
 # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
 # Reverting problematic clang rolls is safe, though.
-CLANG_REVISION = '343880'
+CLANG_REVISION = '344066'
 
 use_head_revision = bool(os.environ.get('LLVM_FORCE_HEAD_REVISION', '0')
                          in ('1', 'YES'))
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a108ffd..2d51c3b 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -20363,6 +20363,7 @@
   <int value="2585" label="CSSValueAppearancePushButtonForOthersRendered"/>
   <int value="2586" label="CSSValueAppearanceSquareButtonRendered"/>
   <int value="2587" label="CSSValueAppearanceSquareButtonForOthersRendered"/>
+  <int value="2588" label="GetComputedStyleForWebkitAppearance"/>
 </enum>
 
 <enum name="FeaturePolicyFeature">
@@ -25326,6 +25327,15 @@
   <int value="2" label="Aggressive"/>
 </enum>
 
+<enum name="IMEExtensionMojoEvent">
+  <int value="0" label="Unknown"/>
+  <int value="1" label="Init Sucess"/>
+  <int value="2" label="Init Failed"/>
+  <int value="3" label="Activate IME Success"/>
+  <int value="4" label="Activate IME Failed"/>
+  <int value="5" label="Rulebased Process Failed"/>
+</enum>
+
 <enum name="IMEGestureTypingEvent">
   <int value="0" label="Typed">A word was typed with a gesture.</int>
   <int value="1" label="Deleted">
@@ -29100,6 +29110,8 @@
   <int value="-1203742042" label="enable-gesture-selection"/>
   <int value="-1201741587" label="DataReductionProxyDecidesTransform:disabled"/>
   <int value="-1201183153" label="enable-centered-app-list"/>
+  <int value="-1199159971"
+      label="ContextualSuggestionsIPHReverseScroll:enabled"/>
   <int value="-1197035323" label="ZeroSuggestRedirectToChrome:disabled"/>
   <int value="-1195194959" label="XGEOVisibleNetworks:disabled"/>
   <int value="-1190174011" label="enable-hdr"/>
@@ -30603,6 +30615,8 @@
   <int value="1786386775" label="TranslateCompactUI:disabled"/>
   <int value="1789517771" label="MacV2Sandbox:enabled"/>
   <int value="1792609232" label="NTPShortcuts:enabled"/>
+  <int value="1798347197"
+      label="ContextualSuggestionsIPHReverseScroll:disabled"/>
   <int value="1803465156" label="enable-zero-suggest-most-visited"/>
   <int value="1803470125" label="SyncUSSSessions:enabled"/>
   <int value="1807374811" label="CCTModuleCache:enabled"/>
@@ -33167,6 +33181,8 @@
   <int value="10" label="Google Maps"/>
   <int value="11" label="Information not available"/>
   <int value="12" label="Chrome Today Extension"/>
+  <int value="13" label="Chrome Search Extension"/>
+  <int value="14" label="Chrome Content Extension"/>
 </enum>
 
 <enum name="MobileSessionShutdownType">
@@ -45713,7 +45729,25 @@
   <int value="9" label="Notification interaction"/>
 </enum>
 
-<enum name="SiteIsolatedCodeCacheBehaviour">
+<enum name="SiteIsolatedCodeCacheJSBehaviour">
+  <int value="0" label="Hit">Available in code cache</int>
+  <int value="1" label="Miss">Not available in cache</int>
+  <int value="2" label="Clear">
+    Clear a cache entry. Typically used when there is a stale entry
+  </int>
+  <int value="3" label="Update">Update an existing entry</int>
+  <int value="4" label="Create">Create a new entry</int>
+  <int value="5" label="Error">
+    Errror in handling the request because either opening backend failed or URL
+    should not be cached
+  </int>
+  <int value="6" label="IncompleteEntry">
+    Entries that are read before a write to that entry has finished when read
+    and write request interleave.
+  </int>
+</enum>
+
+<enum name="SiteIsolatedCodeCacheWASMBehaviour">
   <int value="0" label="Hit">Available in code cache</int>
   <int value="1" label="Miss">Not available in cache</int>
   <int value="2" label="Clear">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index c4362b5..886dea73 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -37507,6 +37507,46 @@
   </summary>
 </histogram>
 
+<histogram name="InputMethod.Mojo.Extension.ActivateIMELatency" units="ms"
+    expires_after="2019-03-31">
+  <owner>googleo@chromium.org</owner>
+  <owner>shuchen@chromium.org</owner>
+  <summary>
+    The time taken to activate a new IME via IME Mojo service in the IME
+    extension. It's from when the IME extension sends out an request to activate
+    a new IME until the new IME is resolved in the IME service and its Mojo
+    interface is bound to the IME extension.
+  </summary>
+</histogram>
+
+<histogram name="InputMethod.Mojo.Extension.Event" enum="IMEExtensionMojoEvent">
+  <owner>googleo@chromium.org</owner>
+  <owner>shuchen@chromium.org</owner>
+  <summary>The events of Mojo service in the IME Extension.</summary>
+</histogram>
+
+<histogram name="InputMethod.Mojo.Extension.Rulebased.ProcessLatency"
+    units="ms" expires_after="2019-03-31">
+  <owner>googleo@chromium.org</owner>
+  <owner>shuchen@chromium.org</owner>
+  <summary>
+    The time taken to process a rulebased request via the IME Mojo service
+    inside the IME extension.
+  </summary>
+</histogram>
+
+<histogram name="InputMethod.Mojo.Extension.ServiceInitLatency" units="ms"
+    expires_after="2019-03-31">
+  <owner>googleo@chromium.org</owner>
+  <owner>shuchen@chromium.org</owner>
+  <summary>
+    The time taken to initialize the IME Mojo service in the IME extension. It's
+    from the IME extension starts loading a private Mojo bundle for making a
+    request to connect a IME service until the connection between the extension
+    and the IME Mojo service is built.
+  </summary>
+</histogram>
+
 <histogram name="InputMethod.PkCommit.Index">
   <owner>shuchen@chromium.org</owner>
   <summary>
@@ -99779,16 +99819,40 @@
   </summary>
 </histogram>
 
-<histogram name="SiteIsolatedCodeCache.Behaviour"
-    enum="SiteIsolatedCodeCacheBehaviour" expires_after="2018-12-31">
+<histogram name="SiteIsolatedCodeCache.Behaviour">
+  <obsolete>
+    Split this histogram into SiteIsolatedCodeCache.JS.Behaviour and
+    SiteIsolatedCodeCache.WASM.Behaviour to collect statistics for JS and WASM
+    code caches in separate histograms.
+  </obsolete>
   <owner>mythria@chromium.org</owner>
   <summary>
-    The behaviour of site isolated code cache recorded for each cache
+    The behaviour of site isolated javascript code cache recorded for each cache
     transaction. It records if the request was serviced and if serviced how it
     was serviced for ex: hit, miss, update.
   </summary>
 </histogram>
 
+<histogram name="SiteIsolatedCodeCache.JS.Behaviour"
+    enum="SiteIsolatedCodeCacheJSBehaviour" expires_after="2018-12-31">
+  <owner>mythria@chromium.org</owner>
+  <summary>
+    The behaviour of site isolated javascript code cache recorded for each cache
+    transaction. It records if the request was serviced and if serviced how it
+    was serviced for ex: hit, miss, update.
+  </summary>
+</histogram>
+
+<histogram name="SiteIsolatedCodeCache.WASM.Behaviour"
+    enum="SiteIsolatedCodeCacheWASMBehaviour" expires_after="2018-12-31">
+  <owner>bbudge@chromium.org</owner>
+  <summary>
+    The behaviour of site isolated web assembly code cache recorded for each
+    cache transaction during WASM compilation. It records if the request was
+    serviced and if serviced how it was serviced for ex: hit, miss, update.
+  </summary>
+</histogram>
+
 <histogram name="SiteIsolation.AllResponses">
   <owner>creis@chromium.org</owner>
   <summary>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv
index 6d0d3676..53d236b 100644
--- a/tools/perf/benchmark.csv
+++ b/tools/perf/benchmark.csv
@@ -21,8 +21,8 @@
 dummy_benchmark.noisy_benchmark_1,nednguyen@google.com,Speed>Telemetry,,
 dummy_benchmark.stable_benchmark_1,nednguyen@google.com,Speed>Telemetry,,
 gpu_perftests,"reveman@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU,,
-jetstream,hablich@chromium.org,,,
-kraken,hablich@chromium.org,,,
+jetstream,hablich@chromium.org,Blink>JavaScript,,
+kraken,hablich@chromium.org,Blink>JavaScript,,
 load_library_perf_tests,"xhwang@chromium.org, crouleau@chromium.org",Internals>Media>Encrypted,,
 loading.desktop,"kouhei@chromium.org, ksakamoto@chromium.org",,https://bit.ly/loading-benchmarks,"cache_temperature_cold,cache_temperature_warm,international,intl_ar_fa_he,intl_es_fr_pt_BR,intl_hi_ru,intl_ja_zh,intl_ko_th_vi,typical"
 loading.mobile,"kouhei@chromium.org, ksakamoto@chromium.org",,https://bit.ly/loading-benchmarks,"cache_temperature_cold,cache_temperature_hot,cache_temperature_warm,easy_ttfmp,easy_tti,global,pwa,tough_ttfmp,tough_tti"
@@ -34,7 +34,7 @@
 memory.long_running_idle_gmail_tbmv2,ulan@chromium.org,,,
 memory.top_10_mobile,perezju@chromium.org,,,
 net_perftests,xunjieli@chromium.org,,,
-octane,hablich@chromium.org,,,
+octane,hablich@chromium.org,Blink>JavaScript,,
 oortonline_tbmv2,ulan@chromium.org,,,
 passthrough_command_buffer_perftests,"piman@chromium.org, chrome-gpu-perf-owners@chromium.org",Internals>GPU>ANGLE,,
 performance_browser_tests,miu@chromium.org,Internals>Media>ScreenCapture,,
@@ -50,10 +50,10 @@
 sizes (win),grt@chromium.org,Internals>PlatformIntegration,,
 smoothness.gpu_rasterization.tough_pinch_zoom_cases,ericrk@chromium.org,,,"gpu_rasterization,tough_pinch_zoom"
 smoothness.tough_pinch_zoom_cases,bokan@chromium.org,Blink>Scroll,,"gpu_rasterization,tough_pinch_zoom"
-speedometer,hablich@chromium.org,,,
-speedometer-future,hablich@chromium.org,,,
-speedometer2,hablich@chromium.org,,,
-speedometer2-future,hablich@chromium.org,,,
+speedometer,hablich@chromium.org,Blink,,
+speedometer-future,hablich@chromium.org,Blink,,
+speedometer2,hablich@chromium.org,Blink,,
+speedometer2-future,hablich@chromium.org,Blink,,
 startup.mobile,"pasko@chromium.org, chrome-android-perf-status@chromium.org",Speed>Metrics>SystemHealthRegressions,,
 supersize_archive,agrieve@chromium.org,,,
 system_health.common_desktop,"charliea@chromium.org, sullivan@chromium.org, tdresser@chromium.org, chrome-speed-metrics-dev@chromium.org",Speed>Metrics>SystemHealthRegressions,https://bit.ly/system-health-benchmarks,"2016,2018,accessibility,emerging_market,health_check,infinite_scroll,international,javascript_heavy,keyboard_input,scroll,tabs_switching,webgl"
diff --git a/tools/perf/benchmarks/jetstream.py b/tools/perf/benchmarks/jetstream.py
index 63ce33b..46aa5c8 100644
--- a/tools/perf/benchmarks/jetstream.py
+++ b/tools/perf/benchmarks/jetstream.py
@@ -75,7 +75,8 @@
     results.AddSummaryValue(list_of_scalar_values.ListOfScalarValues(
         None, 'Score', 'score', all_scores))
 
-@benchmark.Info(emails=['hablich@chromium.org'])
+@benchmark.Info(emails=['hablich@chromium.org'],
+                component='Blink>JavaScript')
 class Jetstream(perf_benchmark.PerfBenchmark):
   test = _JetstreamMeasurement
 
diff --git a/tools/perf/benchmarks/kraken.py b/tools/perf/benchmarks/kraken.py
index d75a6fea..e42317a 100644
--- a/tools/perf/benchmarks/kraken.py
+++ b/tools/perf/benchmarks/kraken.py
@@ -102,7 +102,8 @@
                     '(http://krakenbenchmark.mozilla.org/)'))
 
 
-@benchmark.Info(emails=['hablich@chromium.org'])
+@benchmark.Info(emails=['hablich@chromium.org'],
+                component='Blink>JavaScript')
 class Kraken(perf_benchmark.PerfBenchmark):
   """Mozilla's Kraken JavaScript benchmark.
 
diff --git a/tools/perf/benchmarks/octane.py b/tools/perf/benchmarks/octane.py
index 848ff30..f0318d2 100644
--- a/tools/perf/benchmarks/octane.py
+++ b/tools/perf/benchmarks/octane.py
@@ -117,7 +117,8 @@
                            'benchmark collection.'))
 
 
-@benchmark.Info(emails=['hablich@chromium.org'])
+@benchmark.Info(emails=['hablich@chromium.org'],
+                component='Blink>JavaScript')
 class Octane(perf_benchmark.PerfBenchmark):
   """Google's Octane JavaScript benchmark.
 
diff --git a/tools/perf/benchmarks/speedometer.py b/tools/perf/benchmarks/speedometer.py
index d5fb056c..da2a604 100644
--- a/tools/perf/benchmarks/speedometer.py
+++ b/tools/perf/benchmarks/speedometer.py
@@ -95,7 +95,8 @@
     keychain_metric.KeychainMetric().AddResults(tab, results)
 
 
-@benchmark.Info(emails=['hablich@chromium.org'])
+@benchmark.Info(emails=['hablich@chromium.org'],
+                component='Blink')
 class Speedometer(perf_benchmark.PerfBenchmark):
   test = SpeedometerMeasurement
 
@@ -115,7 +116,8 @@
     return ps
 
 
-@benchmark.Info(emails=['hablich@chromium.org'])
+@benchmark.Info(emails=['hablich@chromium.org'],
+                component='Blink')
 class V8SpeedometerFuture(Speedometer):
   """Speedometer benchmark with the V8 flag --future.
 
diff --git a/tools/perf/benchmarks/speedometer2.py b/tools/perf/benchmarks/speedometer2.py
index e0ff15e..5e32bda8 100644
--- a/tools/perf/benchmarks/speedometer2.py
+++ b/tools/perf/benchmarks/speedometer2.py
@@ -120,7 +120,8 @@
               key=suite_name), important=False))
 
 
-@benchmark.Info(emails=['hablich@chromium.org'])
+@benchmark.Info(emails=['hablich@chromium.org'],
+                component='Blink')
 class Speedometer2(perf_benchmark.PerfBenchmark):
   """Speedometer2 Benchmark.
 
@@ -175,7 +176,8 @@
         raise parser.error('--suite: Invalid regex.')
 
 
-@benchmark.Info(emails=['hablich@chromium.org'])
+@benchmark.Info(emails=['hablich@chromium.org'],
+                component='Blink')
 class V8Speedometer2Future(Speedometer2):
   """Speedometer2 benchmark with the V8 flag --future.
 
diff --git a/tools/perf/benchmarks/startup_mobile.py b/tools/perf/benchmarks/startup_mobile.py
index c6e3257a..46af7b8 100644
--- a/tools/perf/benchmarks/startup_mobile.py
+++ b/tools/perf/benchmarks/startup_mobile.py
@@ -175,6 +175,7 @@
 
     options = timeline_based_measurement.Options(cat_filter)
     options.config.enable_chrome_trace = True
+    options.config.enable_atrace_trace = True
     options.SetTimelineBasedMetrics([
         'tracingMetric',
         'androidStartupMetric',
diff --git a/ui/aura/mus/os_exchange_data_provider_mus.cc b/ui/aura/mus/os_exchange_data_provider_mus.cc
index 9e41787e..f8e327c 100644
--- a/ui/aura/mus/os_exchange_data_provider_mus.cc
+++ b/ui/aura/mus/os_exchange_data_provider_mus.cc
@@ -113,8 +113,7 @@
 void OSExchangeDataProviderMus::SetFilenames(
     const std::vector<ui::FileInfo>& file_names) {
   std::vector<std::string> paths;
-  for (std::vector<ui::FileInfo>::const_iterator it = file_names.begin();
-       it != file_names.end(); ++it) {
+  for (auto it = file_names.begin(); it != file_names.end(); ++it) {
     std::string url_spec = net::FilePathToFileURL(it->path).spec();
     if (!url_spec.empty())
       paths.push_back(url_spec);
diff --git a/ui/aura/test/test_windows.cc b/ui/aura/test/test_windows.cc
index 75d24462..84659fd 100644
--- a/ui/aura/test/test_windows.cc
+++ b/ui/aura/test/test_windows.cc
@@ -95,8 +95,8 @@
 
 std::string ChildWindowIDsAsString(aura::Window* parent) {
   std::string result;
-  for (Window::Windows::const_iterator i = parent->children().begin();
-       i != parent->children().end(); ++i) {
+  for (auto i = parent->children().begin(); i != parent->children().end();
+       ++i) {
     if (!result.empty())
       result += " ";
     result += base::IntToString((*i)->id());
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index ed6b696..a204ca193 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -890,7 +890,7 @@
   if (child->OwnsLayer())
     layer()->Remove(child->layer());
   child->parent_ = NULL;
-  Windows::iterator i = std::find(children_.begin(), children_.end(), child);
+  auto i = std::find(children_.begin(), children_.end(), child);
   DCHECK(i != children_.end());
   children_.erase(i);
   child->OnParentChanged();
@@ -1078,9 +1078,7 @@
   bool state_modified = false;
   state_modified |= env_->gesture_recognizer()->CancelActiveTouches(this);
   state_modified |= env_->gesture_recognizer()->CleanupStateForConsumer(this);
-  for (Window::Windows::iterator iter = children_.begin();
-       iter != children_.end();
-       ++iter) {
+  for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
     state_modified |= (*iter)->CleanupGestureState();
   }
   return state_modified;
diff --git a/ui/base/accelerators/accelerator_manager.cc b/ui/base/accelerators/accelerator_manager.cc
index 5527526..919326f 100644
--- a/ui/base/accelerators/accelerator_manager.cc
+++ b/ui/base/accelerators/accelerator_manager.cc
@@ -48,7 +48,7 @@
 
 void AcceleratorManager::Unregister(const Accelerator& accelerator,
                                     AcceleratorTarget* target) {
-  AcceleratorMap::iterator map_iter = accelerators_.find(accelerator);
+  auto map_iter = accelerators_.find(accelerator);
   if (map_iter == accelerators_.end()) {
     NOTREACHED() << "Unregistering non-existing accelerator";
     return;
@@ -58,7 +58,7 @@
 }
 
 void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) {
-  for (AcceleratorMap::iterator map_iter = accelerators_.begin();
+  for (auto map_iter = accelerators_.begin();
        map_iter != accelerators_.end();) {
     AcceleratorTargetList* targets = &map_iter->second.second;
     if (!base::ContainsValue(*targets, target)) {
@@ -72,20 +72,19 @@
 }
 
 bool AcceleratorManager::IsRegistered(const Accelerator& accelerator) const {
-  AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator);
+  auto map_iter = accelerators_.find(accelerator);
   return map_iter != accelerators_.end() && !map_iter->second.second.empty();
 }
 
 bool AcceleratorManager::Process(const Accelerator& accelerator) {
-  AcceleratorMap::iterator map_iter = accelerators_.find(accelerator);
+  auto map_iter = accelerators_.find(accelerator);
   if (map_iter == accelerators_.end())
     return false;
 
   // We have to copy the target list here, because an AcceleratorPressed
   // event handler may modify the list.
   AcceleratorTargetList targets(map_iter->second.second);
-  for (AcceleratorTargetList::iterator iter = targets.begin();
-       iter != targets.end(); ++iter) {
+  for (auto iter = targets.begin(); iter != targets.end(); ++iter) {
     if ((*iter)->CanHandleAccelerators() &&
         (*iter)->AcceleratorPressed(accelerator)) {
       return true;
@@ -97,7 +96,7 @@
 
 bool AcceleratorManager::HasPriorityHandler(
     const Accelerator& accelerator) const {
-  AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator);
+  auto map_iter = accelerators_.find(accelerator);
   if (map_iter == accelerators_.end() || map_iter->second.second.empty())
     return false;
 
@@ -113,8 +112,7 @@
 void AcceleratorManager::UnregisterImpl(AcceleratorMap::iterator map_iter,
                                         AcceleratorTarget* target) {
   AcceleratorTargetList* targets = &map_iter->second.second;
-  AcceleratorTargetList::iterator target_iter =
-      std::find(targets->begin(), targets->end(), target);
+  auto target_iter = std::find(targets->begin(), targets->end(), target);
   if (target_iter == targets->end()) {
     NOTREACHED() << "Unregistering accelerator for wrong target";
     return;
diff --git a/ui/base/class_property.cc b/ui/base/class_property.cc
index 8b13aa1..01941ed 100644
--- a/ui/base/class_property.cc
+++ b/ui/base/class_property.cc
@@ -54,7 +54,7 @@
 
 int64_t PropertyHandler::GetPropertyInternal(const void* key,
                                              int64_t default_value) const {
-  std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
+  auto iter = prop_map_.find(key);
   if (iter == prop_map_.end())
     return default_value;
   return iter->second.value;
diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc
index 6697be9..3866526 100644
--- a/ui/base/clipboard/clipboard.cc
+++ b/ui/base/clipboard/clipboard.cc
@@ -80,7 +80,7 @@
 
   ClipboardMap* clipboard_map = clipboard_map_.Pointer();
   base::PlatformThreadId id = base::PlatformThread::CurrentId();
-  ClipboardMap::iterator it = clipboard_map->find(id);
+  auto it = clipboard_map->find(id);
   if (it != clipboard_map->end())
     clipboard_map->erase(it);
 }
diff --git a/ui/base/clipboard/clipboard_aurax11.cc b/ui/base/clipboard/clipboard_aurax11.cc
index d5aa2fec9e..4e767fc 100644
--- a/ui/base/clipboard/clipboard_aurax11.cc
+++ b/ui/base/clipboard/clipboard_aurax11.cc
@@ -379,9 +379,8 @@
     // with the X server.
     const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
 
-    for (std::vector< ::Atom>::const_iterator it = types.begin();
-         it != types.end(); ++it) {
-      SelectionFormatMap::const_iterator format_map_it = format_map.find(*it);
+    for (auto it = types.begin(); it != types.end(); ++it) {
+      auto format_map_it = format_map.find(*it);
       if (format_map_it != format_map.end())
         return SelectionData(format_map_it->first, format_map_it->second);
     }
@@ -406,8 +405,7 @@
     // We can local fastpath and return the list of local targets.
     const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
 
-    for (SelectionFormatMap::const_iterator it = format_map.begin();
-         it != format_map.end(); ++it) {
+    for (auto it = format_map.begin(); it != format_map.end(); ++it) {
       out.push_back(it->first);
     }
   } else {
@@ -814,14 +812,13 @@
   DCHECK(IsSupportedClipboardType(type));
 
   aurax11_details_->CreateNewClipboardData();
-  for (ObjectMap::const_iterator iter = objects.begin(); iter != objects.end();
-       ++iter) {
+  for (auto iter = objects.begin(); iter != objects.end(); ++iter) {
     DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
   }
   aurax11_details_->TakeOwnershipOfSelection(type);
 
   if (type == CLIPBOARD_TYPE_COPY_PASTE) {
-    ObjectMap::const_iterator text_iter = objects.find(CBF_TEXT);
+    auto text_iter = objects.find(CBF_TEXT);
     if (text_iter != objects.end()) {
       aurax11_details_->CreateNewClipboardData();
       const ObjectMapParams& params_vector = text_iter->second;
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc b/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
index 1a6e9a1..6666737 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
@@ -173,9 +173,7 @@
 void OSExchangeDataProviderAuraX11::SetFilenames(
     const std::vector<FileInfo>& filenames) {
   std::vector<std::string> paths;
-  for (std::vector<FileInfo>::const_iterator it = filenames.begin();
-       it != filenames.end();
-       ++it) {
+  for (auto it = filenames.begin(); it != filenames.end(); ++it) {
     std::string url_spec = net::FilePathToFileURL(it->path).spec();
     if (!url_spec.empty())
       paths.push_back(url_spec);
diff --git a/ui/base/models/list_selection_model.cc b/ui/base/models/list_selection_model.cc
index 1456c0f..d8e23ba1 100644
--- a/ui/base/models/list_selection_model.cc
+++ b/ui/base/models/list_selection_model.cc
@@ -76,8 +76,7 @@
 
 void ListSelectionModel::IncrementFrom(int index) {
   // Shift the selection to account for a newly inserted item at |index|.
-  for (SelectedIndices::iterator i = selected_indices_.begin();
-       i != selected_indices_.end(); ++i) {
+  for (auto i = selected_indices_.begin(); i != selected_indices_.end(); ++i) {
     IncrementFromImpl(index, &(*i));
   }
   IncrementFromImpl(index, &anchor_);
@@ -85,8 +84,7 @@
 }
 
 void ListSelectionModel::DecrementFrom(int index) {
-  for (SelectedIndices::iterator i = selected_indices_.begin();
-       i != selected_indices_.end(); ) {
+  for (auto i = selected_indices_.begin(); i != selected_indices_.end();) {
     if (DecrementFromImpl(index, &(*i)))
       i = selected_indices_.erase(i);
     else
@@ -115,8 +113,7 @@
 }
 
 void ListSelectionModel::RemoveIndexFromSelection(int index) {
-  SelectedIndices::iterator i = std::find(selected_indices_.begin(),
-                                          selected_indices_.end(), index);
+  auto i = std::find(selected_indices_.begin(), selected_indices_.end(), index);
   if (i != selected_indices_.end())
     selected_indices_.erase(i);
 }
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc
index 6543508..5561c41 100644
--- a/ui/base/models/simple_menu_model.cc
+++ b/ui/base/models/simple_menu_model.cc
@@ -295,7 +295,7 @@
 }
 
 int SimpleMenuModel::GetIndexOfCommandId(int command_id) const {
-  for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) {
+  for (auto i = items_.begin(); i != items_.end(); ++i) {
     if (i->command_id == command_id)
       return static_cast<int>(std::distance(items_.begin(), i));
   }
@@ -306,7 +306,7 @@
 // SimpleMenuModel, MenuModel implementation:
 
 bool SimpleMenuModel::HasIcons() const {
-  for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) {
+  for (auto i = items_.begin(); i != items_.end(); ++i) {
     if (!i->icon.IsEmpty())
       return true;
   }
diff --git a/ui/base/resource/resource_bundle_unittest.cc b/ui/base/resource/resource_bundle_unittest.cc
index 363a0e9..996df62 100644
--- a/ui/base/resource/resource_bundle_unittest.cc
+++ b/ui/base/resource/resource_bundle_unittest.cc
@@ -92,8 +92,7 @@
       bitmap_data->begin(),
       bitmap_data->begin() + arraysize(kPngMagic),
       kPngMagic));
-  std::vector<unsigned char>::iterator ihdr_start =
-      bitmap_data->begin() + arraysize(kPngMagic);
+  auto ihdr_start = bitmap_data->begin() + arraysize(kPngMagic);
   char ihdr_length_data[sizeof(uint32_t)];
   for (size_t i = 0; i < sizeof(uint32_t); ++i)
     ihdr_length_data[i] = *(ihdr_start + i);
diff --git a/ui/base/template_expressions.cc b/ui/base/template_expressions.cc
index 9618dc7..1aec20c 100644
--- a/ui/base/template_expressions.cc
+++ b/ui/base/template_expressions.cc
@@ -93,7 +93,7 @@
         source.substr(current_pos, key_end - current_pos).as_string();
     CHECK(!key.empty());
 
-    TemplateReplacements::const_iterator value = replacements.find(key);
+    auto value = replacements.find(key);
     CHECK(value != replacements.end()) << "$i18n replacement key \"" << key
                                        << "\" not found";
 
diff --git a/ui/base/view_prop.cc b/ui/base/view_prop.cc
index 2ff403e..45185f5 100644
--- a/ui/base/view_prop.cc
+++ b/ui/base/view_prop.cc
@@ -21,7 +21,7 @@
     if (!data_set_)
       data_set_ = new DataSet;
     scoped_refptr<Data> new_data(new Data(view, key));
-    DataSet::const_iterator i = data_set_->find(new_data.get());
+    auto i = data_set_->find(new_data.get());
     if (i != data_set_->end()) {
       *data = *i;
       return;
@@ -58,7 +58,7 @@
         data_(NULL) {}
 
   ~Data() {
-    DataSet::iterator i = data_set_->find(this);
+    auto i = data_set_->find(this);
     // Also check for equality using == as |Get| creates dummy values in order
     // to look up a value.
     if (i != data_set_->end() && *i == this)
diff --git a/ui/base/x/selection_owner.cc b/ui/base/x/selection_owner.cc
index 17b750b..1804eaed 100644
--- a/ui/base/x/selection_owner.cc
+++ b/ui/base/x/selection_owner.cc
@@ -100,8 +100,7 @@
 }
 
 void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) {
-  for (SelectionFormatMap::const_iterator it = format_map_.begin();
-       it != format_map_.end(); ++it) {
+  for (auto it = format_map_.begin(); it != format_map_.end(); ++it) {
     targets->push_back(it->first);
   }
 }
@@ -187,8 +186,7 @@
 }
 
 void SelectionOwner::OnPropertyEvent(const XEvent& event) {
-  std::vector<IncrementalTransfer>::iterator it =
-      FindIncrementalTransferForEvent(event);
+  auto it = FindIncrementalTransferForEvent(event);
   if (it == incremental_transfers_.end())
     return;
 
@@ -233,7 +231,7 @@
   }
 
   // Try to find the data type in map.
-  SelectionFormatMap::const_iterator it = format_map_.find(target);
+  auto it = format_map_.find(target);
   if (it != format_map_.end()) {
     if (it->second->size() > max_request_size_) {
       // We must send the data back in several chunks due to a limitation in
@@ -326,10 +324,8 @@
 
 std::vector<SelectionOwner::IncrementalTransfer>::iterator
     SelectionOwner::FindIncrementalTransferForEvent(const XEvent& event) {
-  for (std::vector<IncrementalTransfer>::iterator it =
-           incremental_transfers_.begin();
-       it != incremental_transfers_.end();
-       ++it) {
+  for (auto it = incremental_transfers_.begin();
+       it != incremental_transfers_.end(); ++it) {
     if (it->window == event.xproperty.window &&
         it->property == event.xproperty.atom) {
       return it;
diff --git a/ui/base/x/selection_requestor.cc b/ui/base/x/selection_requestor.cc
index ccd65a4d..8fb3bda 100644
--- a/ui/base/x/selection_requestor.cc
+++ b/ui/base/x/selection_requestor.cc
@@ -82,8 +82,7 @@
     ConvertSelectionForCurrentRequest();
   BlockTillSelectionNotifyForRequest(&request);
 
-  std::vector<Request*>::iterator request_it = std::find(
-      requests_.begin(), requests_.end(), &request);
+  auto request_it = std::find(requests_.begin(), requests_.end(), &request);
   CHECK(request_it != requests_.end());
   if (static_cast<int>(current_request_index_) >
       request_it - requests_.begin()) {
@@ -116,8 +115,7 @@
 SelectionData SelectionRequestor::RequestAndWaitForTypes(
     XAtom selection,
     const std::vector<XAtom>& types) {
-  for (std::vector<XAtom>::const_iterator it = types.begin();
-       it != types.end(); ++it) {
+  for (auto it = types.begin(); it != types.end(); ++it) {
     scoped_refptr<base::RefCountedMemory> data;
     XAtom type = x11::None;
     if (PerformBlockingConvertSelection(selection,
diff --git a/ui/base/x/selection_utils.cc b/ui/base/x/selection_utils.cc
index 8a41342..c0947ea 100644
--- a/ui/base/x/selection_utils.cc
+++ b/ui/base/x/selection_utils.cc
@@ -51,8 +51,7 @@
 void GetAtomIntersection(const std::vector< ::Atom>& desired,
                          const std::vector< ::Atom>& offered,
                          std::vector< ::Atom>* output) {
-  for (std::vector< ::Atom>::const_iterator it = desired.begin();
-       it != desired.end(); ++it) {
+  for (auto it = desired.begin(); it != desired.end(); ++it) {
     if (base::ContainsValue(offered, *it))
       output->push_back(*it);
   }
@@ -121,9 +120,8 @@
 
 ui::SelectionData SelectionFormatMap::GetFirstOf(
     const std::vector< ::Atom>& requested_types) const {
-  for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
-       it != requested_types.end(); ++it) {
-    const_iterator data_it = data_.find(*it);
+  for (auto it = requested_types.begin(); it != requested_types.end(); ++it) {
+    auto data_it = data_.find(*it);
     if (data_it != data_.end()) {
       return SelectionData(data_it->first, data_it->second);
     }
@@ -134,7 +132,7 @@
 
 std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
   std::vector< ::Atom> atoms;
-  for (const_iterator it = data_.begin(); it != data_.end(); ++it)
+  for (auto it = data_.begin(); it != data_.end(); ++it)
     atoms.push_back(it->first);
 
   return atoms;
diff --git a/ui/base/x/x11_menu_list.cc b/ui/base/x/x11_menu_list.cc
index 876865b..83a5522 100644
--- a/ui/base/x/x11_menu_list.cc
+++ b/ui/base/x/x11_menu_list.cc
@@ -34,8 +34,7 @@
 }
 
 void XMenuList::MaybeUnregisterMenu(XID menu) {
-  std::vector<XID>::iterator iter = std::find(menus_.begin(), menus_.end(),
-                                              menu);
+  auto iter = std::find(menus_.begin(), menus_.end(), menu);
   if (iter == menus_.end())
     return;
   menus_.erase(iter);
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index 734904f..f85469f6 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -284,8 +284,7 @@
   if (compositor)
     child->ResetCompositorForAnimatorsInTree(compositor);
 
-  std::vector<Layer*>::iterator i =
-      std::find(children_.begin(), children_.end(), child);
+  auto i = std::find(children_.begin(), children_.end(), child);
   DCHECK(i != children_.end());
   children_.erase(i);
   child->parent_ = nullptr;
diff --git a/ui/compositor/layer_animation_observer.cc b/ui/compositor/layer_animation_observer.cc
index e5db5ecd..2c77493 100644
--- a/ui/compositor/layer_animation_observer.cc
+++ b/ui/compositor/layer_animation_observer.cc
@@ -159,8 +159,7 @@
 ImplicitAnimationObserver::AnimationStatus
 ImplicitAnimationObserver::AnimationStatusForProperty(
     LayerAnimationElement::AnimatableProperty property) const {
-  PropertyAnimationStatusMap::const_iterator iter =
-      property_animation_status_.find(property);
+  auto iter = property_animation_status_.find(property);
   return iter == property_animation_status_.end() ? ANIMATION_STATUS_UNKNOWN :
       iter->second;
 }
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc
index d64ac0e6..3c3efd6 100644
--- a/ui/compositor/layer_animator.cc
+++ b/ui/compositor/layer_animator.cc
@@ -414,7 +414,7 @@
   // The call to GetRunningAnimation made above already purged deleted
   // animations, so we are guaranteed that all the animations we iterate
   // over now are alive.
-  for (RunningAnimations::iterator iter = running_animations_.begin();
+  for (auto iter = running_animations_.begin();
        iter != running_animations_.end(); ++iter) {
     // Ensure that each sequence is only Started once, regardless of the
     // number of sequences in the group that have threaded first elements.
@@ -541,7 +541,7 @@
   bool is_running = false;
 
   // First remove from running animations
-  for (RunningAnimations::iterator iter = running_animations_.begin();
+  for (auto iter = running_animations_.begin();
        iter != running_animations_.end(); ++iter) {
     if ((*iter).sequence() == sequence) {
       running_animations_.erase(iter);
@@ -638,7 +638,7 @@
 LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
     LayerAnimationElement::AnimatableProperty property) {
   PurgeDeletedAnimations();
-  for (RunningAnimations::iterator iter = running_animations_.begin();
+  for (auto iter = running_animations_.begin();
        iter != running_animations_.end(); ++iter) {
     if ((*iter).sequence()->properties() & property)
       return &(*iter);
diff --git a/ui/compositor/layer_animator_collection.cc b/ui/compositor/layer_animator_collection.cc
index 54951f0..fd9873e 100644
--- a/ui/compositor/layer_animator_collection.cc
+++ b/ui/compositor/layer_animator_collection.cc
@@ -46,9 +46,7 @@
 void LayerAnimatorCollection::OnAnimationStep(base::TimeTicks now) {
   last_tick_time_ = now;
   std::set<scoped_refptr<LayerAnimator> > list = animators_;
-  for (std::set<scoped_refptr<LayerAnimator> >::iterator iter = list.begin();
-       iter != list.end();
-       ++iter) {
+  for (auto iter = list.begin(); iter != list.end(); ++iter) {
     // Make sure the animator is still valid.
     if (animators_.count(*iter) > 0)
       (*iter)->Step(now);
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index cd4b56a..01eaa955 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -316,7 +316,7 @@
 }
 
 void InProcessContextFactory::RemoveCompositor(Compositor* compositor) {
-  PerCompositorDataMap::iterator it = per_compositor_data_.find(compositor);
+  auto it = per_compositor_data_.find(compositor);
   if (it == per_compositor_data_.end())
     return;
   PerCompositorData* data = it->second.get();
diff --git a/ui/compositor/test/test_layers.cc b/ui/compositor/test/test_layers.cc
index 2e71eac..a9309a3 100644
--- a/ui/compositor/test/test_layers.cc
+++ b/ui/compositor/test/test_layers.cc
@@ -11,8 +11,8 @@
 
 std::string ChildLayerNamesAsString(const ui::Layer& parent) {
   std::string names;
-  for (std::vector<Layer*>::const_iterator it = parent.children().begin();
-       it != parent.children().end(); ++it) {
+  for (auto it = parent.children().begin(); it != parent.children().end();
+       ++it) {
     if (!names.empty())
       names += " ";
     names += (*it)->name();
diff --git a/ui/display/display_change_notifier.cc b/ui/display/display_change_notifier.cc
index 3a5cfd0..9c1e6ec 100644
--- a/ui/display/display_change_notifier.cc
+++ b/ui/display/display_change_notifier.cc
@@ -44,7 +44,7 @@
     const std::vector<Display>& old_displays,
     const std::vector<Display>& new_displays) {
   // Display present in old_displays but not in new_displays has been removed.
-  std::vector<Display>::const_iterator old_it = old_displays.begin();
+  auto old_it = old_displays.begin();
   for (; old_it != old_displays.end(); ++old_it) {
     if (std::find_if(new_displays.begin(), new_displays.end(),
                      DisplayComparator(*old_it)) == new_displays.end()) {
@@ -55,10 +55,10 @@
 
   // Display present in new_displays but not in old_displays has been added.
   // Display present in both might have been modified.
-  for (std::vector<Display>::const_iterator new_it = new_displays.begin();
-       new_it != new_displays.end(); ++new_it) {
-    std::vector<Display>::const_iterator old_it = std::find_if(
-        old_displays.begin(), old_displays.end(), DisplayComparator(*new_it));
+  for (auto new_it = new_displays.begin(); new_it != new_displays.end();
+       ++new_it) {
+    auto old_it = std::find_if(old_displays.begin(), old_displays.end(),
+                               DisplayComparator(*new_it));
 
     if (old_it == old_displays.end()) {
       for (DisplayObserver& observer : observer_list_)
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc
index 0677086..e55e494 100644
--- a/ui/display/manager/display_manager.cc
+++ b/ui/display/manager/display_manager.cc
@@ -714,8 +714,7 @@
 bool DisplayManager::GetSelectedModeForDisplayId(
     int64_t display_id,
     ManagedDisplayMode* mode) const {
-  std::map<int64_t, ManagedDisplayMode>::const_iterator iter =
-      display_modes_.find(display_id);
+  auto iter = display_modes_.find(display_id);
   if (iter == display_modes_.end())
     return false;
   *mode = iter->second;
@@ -741,8 +740,7 @@
 }
 
 gfx::Insets DisplayManager::GetOverscanInsets(int64_t display_id) const {
-  std::map<int64_t, ManagedDisplayInfo>::const_iterator it =
-      display_info_.find(display_id);
+  auto it = display_info_.find(display_id);
   return (it != display_info_.end()) ? it->second.overscan_insets_in_dip()
                                      : gfx::Insets();
 }
@@ -943,7 +941,7 @@
   std::map<size_t, uint32_t> display_changes;
   std::vector<size_t> added_display_indices;
 
-  Displays::iterator curr_iter = active_display_list_.begin();
+  auto curr_iter = active_display_list_.begin();
   DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin();
 
   while (curr_iter != active_display_list_.end() ||
@@ -1068,8 +1066,8 @@
   bool notify_primary_change =
       delegate_ ? old_primary.id() != screen_->GetPrimaryDisplay().id() : false;
 
-  for (std::map<size_t, uint32_t>::iterator iter = display_changes.begin();
-       iter != display_changes.end(); ++iter) {
+  for (auto iter = display_changes.begin(); iter != display_changes.end();
+       ++iter) {
     uint32_t metrics = iter->second;
     const Display& updated_display = active_display_list_[iter->first];
 
@@ -1240,8 +1238,7 @@
     int64_t display_id) const {
   DCHECK_NE(kInvalidDisplayId, display_id);
 
-  std::map<int64_t, ManagedDisplayInfo>::const_iterator iter =
-      display_info_.find(display_id);
+  auto iter = display_info_.find(display_id);
   CHECK(iter != display_info_.end()) << display_id;
   return iter->second;
 }
@@ -1260,8 +1257,7 @@
   if (id == kInvalidDisplayId)
     return l10n_util::GetStringUTF8(IDS_DISPLAY_NAME_UNKNOWN);
 
-  std::map<int64_t, ManagedDisplayInfo>::const_iterator iter =
-      display_info_.find(id);
+  auto iter = display_info_.find(id);
   if (iter != display_info_.end() && !iter->second.name().empty())
     return iter->second.name();
 
diff --git a/ui/display/test/display_manager_test_api.cc b/ui/display/test/display_manager_test_api.cc
index aa16317..bf0f4a24 100644
--- a/ui/display/test/display_manager_test_api.cc
+++ b/ui/display/test/display_manager_test_api.cc
@@ -51,11 +51,10 @@
   const ManagedDisplayInfo::ManagedDisplayModeList& modes =
       info.display_modes();
   DCHECK_NE(0u, modes.size());
-  ManagedDisplayInfo::ManagedDisplayModeList::const_iterator iter =
-      std::find_if(modes.begin(), modes.end(),
-                   [resolution](const ManagedDisplayMode& mode) {
-                     return mode.size() == resolution;
-                   });
+  auto iter = std::find_if(modes.begin(), modes.end(),
+                           [resolution](const ManagedDisplayMode& mode) {
+                             return mode.size() == resolution;
+                           });
   if (iter == modes.end()) {
     DLOG(WARNING) << "Unsupported resolution was requested:"
                   << resolution.ToString();
@@ -94,8 +93,8 @@
     // Start from (1,1) so that windows won't overlap with native mouse cursor.
     // See |AshTestBase::SetUp()|.
     int next_y = 1;
-    for (DisplayInfoList::iterator iter = display_info_list.begin();
-         iter != display_info_list.end(); ++iter) {
+    for (auto iter = display_info_list.begin(); iter != display_info_list.end();
+         ++iter) {
       gfx::Rect bounds(iter->bounds_in_native().size());
       bounds.set_x(1);
       bounds.set_y(next_y);
diff --git a/ui/events/devices/x11/device_data_manager_x11.cc b/ui/events/devices/x11/device_data_manager_x11.cc
index ec5a0ac..19648ce1 100644
--- a/ui/events/devices/x11/device_data_manager_x11.cc
+++ b/ui/events/devices/x11/device_data_manager_x11.cc
@@ -832,8 +832,7 @@
   blocked_devices_.set(deviceid, true);
   // TODO(rsadam@): Support blocking touchscreen devices.
   std::vector<InputDevice> keyboards = GetKeyboardDevices();
-  std::vector<InputDevice>::iterator it =
-      FindDeviceWithId(keyboards.begin(), keyboards.end(), deviceid);
+  auto it = FindDeviceWithId(keyboards.begin(), keyboards.end(), deviceid);
   if (it != std::end(keyboards)) {
     blocked_keyboard_devices_.insert(
         std::pair<int, InputDevice>(deviceid, *it));
@@ -844,8 +843,7 @@
 
 void DeviceDataManagerX11::EnableDevice(int deviceid) {
   blocked_devices_.set(deviceid, false);
-  std::map<int, InputDevice>::iterator it =
-      blocked_keyboard_devices_.find(deviceid);
+  auto it = blocked_keyboard_devices_.find(deviceid);
   if (it != blocked_keyboard_devices_.end()) {
     std::vector<InputDevice> devices = GetKeyboardDevices();
     // Add device to current list of active devices.
@@ -879,13 +877,11 @@
 void DeviceDataManagerX11::OnKeyboardDevicesUpdated(
     const std::vector<InputDevice>& devices) {
   std::vector<InputDevice> keyboards(devices);
-  for (std::map<int, InputDevice>::iterator blocked_iter =
-           blocked_keyboard_devices_.begin();
+  for (auto blocked_iter = blocked_keyboard_devices_.begin();
        blocked_iter != blocked_keyboard_devices_.end();) {
     // Check if the blocked device still exists in list of devices.
     int device_id = blocked_iter->first;
-    std::vector<InputDevice>::iterator it =
-        FindDeviceWithId(keyboards.begin(), keyboards.end(), device_id);
+    auto it = FindDeviceWithId(keyboards.begin(), keyboards.end(), device_id);
     // If the device no longer exists, unblock it, else filter it out from our
     // active list.
     if (it == keyboards.end()) {
diff --git a/ui/events/devices/x11/touch_factory_x11.cc b/ui/events/devices/x11/touch_factory_x11.cc
index d7c0327..40c9e65 100644
--- a/ui/events/devices/x11/touch_factory_x11.cc
+++ b/ui/events/devices/x11/touch_factory_x11.cc
@@ -312,8 +312,7 @@
     const std::vector<int>& devices) {
   touch_device_lookup_.reset();
   touch_device_list_.clear();
-  for (std::vector<int>::const_iterator iter = devices.begin();
-       iter != devices.end(); ++iter) {
+  for (auto iter = devices.begin(); iter != devices.end(); ++iter) {
     DCHECK(IsValidDevice(*iter));
     touch_device_lookup_[*iter] = true;
     touch_device_list_[*iter] = {true, EventPointerType::POINTER_TYPE_TOUCH};
@@ -324,8 +323,7 @@
 void TouchFactory::SetPointerDeviceForTest(
     const std::vector<int>& devices) {
   pointer_device_lookup_.reset();
-  for (std::vector<int>::const_iterator iter = devices.begin();
-       iter != devices.end(); ++iter) {
+  for (auto iter = devices.begin(); iter != devices.end(); ++iter) {
     pointer_device_lookup_[*iter] = true;
   }
 }
diff --git a/ui/events/event_rewriter_unittest.cc b/ui/events/event_rewriter_unittest.cc
index ae9abce..90c5d26 100644
--- a/ui/events/event_rewriter_unittest.cc
+++ b/ui/events/event_rewriter_unittest.cc
@@ -125,8 +125,7 @@
   EventRewriteStatus RewriteEvent(
       const Event& event,
       std::unique_ptr<Event>* rewritten_event) override {
-    RewriteRules::iterator find =
-        rules_.find(RewriteCase(state_, event.type()));
+    auto find = rules_.find(RewriteCase(state_, event.type()));
     if (find == rules_.end())
       return EVENT_REWRITE_CONTINUE;
     if ((find->second.status == EVENT_REWRITE_REWRITTEN) ||
diff --git a/ui/events/event_source.cc b/ui/events/event_source.cc
index 21e160b..d2c955c 100644
--- a/ui/events/event_source.cc
+++ b/ui/events/event_source.cc
@@ -34,8 +34,7 @@
 }
 
 void EventSource::RemoveEventRewriter(EventRewriter* rewriter) {
-  EventRewriterList::iterator find =
-      std::find(rewriter_list_.begin(), rewriter_list_.end(), rewriter);
+  auto find = std::find(rewriter_list_.begin(), rewriter_list_.end(), rewriter);
   if (find != rewriter_list_.end())
     rewriter_list_.erase(find);
 }
diff --git a/ui/events/event_target.cc b/ui/events/event_target.cc
index 09c115a..e72b72c 100644
--- a/ui/events/event_target.cc
+++ b/ui/events/event_target.cc
@@ -58,10 +58,8 @@
 }
 
 void EventTarget::RemovePostTargetHandler(EventHandler* handler) {
-  EventHandlerList::iterator find =
-      std::find(post_target_list_.begin(),
-                post_target_list_.end(),
-                handler);
+  auto find =
+      std::find(post_target_list_.begin(), post_target_list_.end(), handler);
   if (find != post_target_list_.end())
     post_target_list_.erase(find);
 }
@@ -99,8 +97,9 @@
 void EventTarget::GetPostTargetHandlers(EventHandlerList* list) {
   EventTarget* target = this;
   while (target) {
-    for (EventHandlerList::iterator it = target->post_target_list_.begin(),
-        end = target->post_target_list_.end(); it != end; ++it) {
+    for (auto it = target->post_target_list_.begin(),
+              end = target->post_target_list_.end();
+         it != end; ++it) {
       list->push_back(*it);
     }
     target = target->GetParentTarget();
diff --git a/ui/events/event_utils.cc b/ui/events/event_utils.cc
index 4e8b8376..164fd22 100644
--- a/ui/events/event_utils.cc
+++ b/ui/events/event_utils.cc
@@ -89,8 +89,7 @@
   if (!screen)
     return display::Display::TouchSupport::UNKNOWN;
   const std::vector<display::Display>& displays = screen->GetAllDisplays();
-  for (std::vector<display::Display>::const_iterator it = displays.begin();
-       it != displays.end(); ++it) {
+  for (auto it = displays.begin(); it != displays.end(); ++it) {
     if (it->IsInternal())
       return it->touch_support();
   }
diff --git a/ui/events/gestures/gesture_recognizer_impl.cc b/ui/events/gestures/gesture_recognizer_impl.cc
index 45ec592..6e81131 100644
--- a/ui/events/gestures/gesture_recognizer_impl.cc
+++ b/ui/events/gestures/gesture_recognizer_impl.cc
@@ -373,8 +373,7 @@
 
 void GestureRecognizerImpl::RemoveGestureEventHelper(
     GestureEventHelper* helper) {
-  std::vector<GestureEventHelper*>::iterator it = std::find(helpers_.begin(),
-      helpers_.end(), helper);
+  auto it = std::find(helpers_.begin(), helpers_.end(), helper);
   if (it != helpers_.end())
     helpers_.erase(it);
 }
diff --git a/ui/events/keycodes/keyboard_code_conversion_mac.mm b/ui/events/keycodes/keyboard_code_conversion_mac.mm
index 2b4dd2f0..873c4ce 100644
--- a/ui/events/keycodes/keyboard_code_conversion_mac.mm
+++ b/ui/events/keycodes/keyboard_code_conversion_mac.mm
@@ -892,7 +892,7 @@
       &buffer_length, char_buffer);
   OSSTATUS_DCHECK(ret == noErr, ret);
 
-  // TODO(chongz): Handle multiple character case. Should be rare.
+  // TODO(input-dev): Handle multiple character case. Should be rare.
   return char_buffer[0];
 }
 
diff --git a/ui/events/keycodes/keysym_to_unicode.cc b/ui/events/keycodes/keysym_to_unicode.cc
index 5a358804..9413e97d 100644
--- a/ui/events/keycodes/keysym_to_unicode.cc
+++ b/ui/events/keycodes/keysym_to_unicode.cc
@@ -834,7 +834,7 @@
     }
 
     // Other KeySyms which are not Unicode-style.
-    KeySymToUnicodeMap::const_iterator i = keysym_to_unicode_map_.find(keysym);
+    auto i = keysym_to_unicode_map_.find(keysym);
     return i != keysym_to_unicode_map_.end() ? i->second : 0;
   }
 
diff --git a/ui/events/keycodes/platform_key_map_win.cc b/ui/events/keycodes/platform_key_map_win.cc
index c1e3b83..c803dc47 100644
--- a/ui/events/keycodes/platform_key_map_win.cc
+++ b/ui/events/keycodes/platform_key_map_win.cc
@@ -192,7 +192,7 @@
     {VKEY_EREOF, DomKey::ERASE_EOF},
     {VKEY_PLAY, DomKey::PLAY},
     {VKEY_ZOOM, DomKey::ZOOM_TOGGLE},
-    // TODO(chongz): Handle VKEY_NONAME, VKEY_PA1.
+    // TODO(input-dev): Handle VKEY_NONAME, VKEY_PA1.
     // https://crbug.com/616910
     {VKEY_OEM_CLEAR, DomKey::CLEAR},
 };
@@ -268,7 +268,8 @@
           base::ThreadLocalStorage::Slot> {
   static base::ThreadLocalStorage::Slot* New(void* instance) {
     // Use placement new to initialize our instance in our preallocated space.
-    // TODO(chongz): Use std::default_delete instead of providing own function.
+    // TODO(input-dev): Use std::default_delete instead of providing own
+    // function.
     return new (instance) base::ThreadLocalStorage::Slot(CleanupKeyMapTls);
   }
 };
@@ -382,7 +383,7 @@
   if (!::GetKeyboardState(keyboard_state_to_restore))
     return;
 
-  // TODO(chongz): Optimize layout switching (see crbug.com/587147).
+  // TODO(input-dev): Optimize layout switching (see crbug.com/587147).
   keyboard_layout_ = layout;
   printable_keycode_to_key_.clear();
   has_alt_graph_ = false;
@@ -418,7 +419,7 @@
                                                    flags)] =
               DomKey::DeadKeyFromCombiningCharacter(translated_chars[0]);
         } else {
-          // TODO(chongz): Check if this will actually happen.
+          // TODO(input-dev): Check if this will actually happen.
         }
       } else if (rv == 1) {
         if (translated_chars[0] >= 0x20) {
@@ -434,7 +435,7 @@
           // Ignores legacy non-printable control characters.
         }
       } else {
-        // TODO(chongz): Handle rv <= -2 and rv >= 2.
+        // TODO(input-dev): Handle rv <= -2 and rv >= 2.
       }
     }
   }
diff --git a/ui/events/keycodes/platform_key_map_win.h b/ui/events/keycodes/platform_key_map_win.h
index bf0e19a..2a8dc38 100644
--- a/ui/events/keycodes/platform_key_map_win.h
+++ b/ui/events/keycodes/platform_key_map_win.h
@@ -44,12 +44,12 @@
 
   PlatformKeyMap();
 
-  // TODO(chongz): Expose this function when we need to access separate layout.
-  // Returns the DomKey 'meaning' of |KeyboardCode| in the context of specified
-  // |EventFlags| and stored keyboard layout.
+  // TODO(input-dev): Expose this function when we need to access separate
+  // layout. Returns the DomKey 'meaning' of |KeyboardCode| in the context of
+  // specified |EventFlags| and stored keyboard layout.
   DomKey DomKeyFromKeyboardCodeImpl(KeyboardCode, int* flags) const;
 
-  // TODO(chongz): Expose this function in response to WM_INPUTLANGCHANGE.
+  // TODO(input-dev): Expose this function in response to WM_INPUTLANGCHANGE.
   void UpdateLayout(HKL layout);
 
   HKL keyboard_layout_ = 0;
diff --git a/ui/events/keycodes/platform_key_map_win_unittest.cc b/ui/events/keycodes/platform_key_map_win_unittest.cc
index f992eef..da2459c 100644
--- a/ui/events/keycodes/platform_key_map_win_unittest.cc
+++ b/ui/events/keycodes/platform_key_map_win_unittest.cc
@@ -265,8 +265,8 @@
 
     int scan_code =
         ui::KeycodeConverter::DomCodeToNativeKeycode(test_case.dom_code);
-    // TODO(chongz): Some |scan_code| should map to different |key_code| based
-    // on modifiers.
+    // TODO(input-dev): Some |scan_code| should map to different |key_code|
+    // based on modifiers.
     KeyboardCode key_code = static_cast<KeyboardCode>(
         ::MapVirtualKeyEx(scan_code, MAPVK_VSC_TO_VK, layout));
 
diff --git a/ui/gfx/animation/animation_container.cc b/ui/gfx/animation/animation_container.cc
index ef15c8f6..884c3c8 100644
--- a/ui/gfx/animation/animation_container.cc
+++ b/ui/gfx/animation/animation_container.cc
@@ -114,7 +114,7 @@
   // elements in the set share the same interval).
   TimeDelta min;
   size_t count = 1;
-  Elements::const_iterator i = elements_.begin();
+  auto i = elements_.begin();
   min = (*i)->GetTimerInterval();
   for (++i; i != elements_.end(); ++i) {
     auto interval = (*i)->GetTimerInterval();
diff --git a/ui/gfx/color_analysis.cc b/ui/gfx/color_analysis.cc
index 5aa02fc..a23a9ad 100644
--- a/ui/gfx/color_analysis.cc
+++ b/ui/gfx/color_analysis.cc
@@ -541,7 +541,7 @@
     clusters.resize(kNumberOfClusters, KMeanCluster());
 
     // Pick a starting point for each cluster
-    std::vector<KMeanCluster>::iterator cluster = clusters.begin();
+    auto cluster = clusters.begin();
     while (cluster != clusters.end()) {
       // Try up to 10 times to find a unique color. If no unique color can be
       // found, destroy this cluster.
@@ -562,9 +562,8 @@
         // Loop through the previous clusters and check to see if we have seen
         // this color before.
         color_unique = true;
-        for (std::vector<KMeanCluster>::iterator
-            cluster_check = clusters.begin();
-            cluster_check != cluster; ++cluster_check) {
+        for (auto cluster_check = clusters.begin(); cluster_check != cluster;
+             ++cluster_check) {
           if (cluster_check->IsAtCentroid(r, g, b)) {
             color_unique = false;
             break;
@@ -612,11 +611,11 @@
           continue;
 
         uint32_t distance_sqr_to_closest_cluster = UINT_MAX;
-        std::vector<KMeanCluster>::iterator closest_cluster = clusters.begin();
+        auto closest_cluster = clusters.begin();
 
         // Figure out which cluster this color is closest to in RGB space.
-        for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
-            cluster != clusters.end(); ++cluster) {
+        for (auto cluster = clusters.begin(); cluster != clusters.end();
+             ++cluster) {
           uint32_t distance_sqr = cluster->GetDistanceSqr(r, g, b);
 
           if (distance_sqr < distance_sqr_to_closest_cluster) {
@@ -630,8 +629,8 @@
 
       // Calculate the new cluster centers and see if we've converged or not.
       convergence = true;
-      for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
-          cluster != clusters.end(); ++cluster) {
+      for (auto cluster = clusters.begin(); cluster != clusters.end();
+           ++cluster) {
         convergence &= cluster->CompareCentroidWithAggregate();
 
         cluster->RecomputeCentroid();
@@ -645,8 +644,8 @@
 
     // Loop through the clusters to figure out which cluster has an appropriate
     // color. Skip any that are too bright/dark and go in order of weight.
-    for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
-        cluster != clusters.end(); ++cluster) {
+    for (auto cluster = clusters.begin(); cluster != clusters.end();
+         ++cluster) {
       uint8_t r, g, b;
       cluster->GetCentroid(&r, &g, &b);
 
diff --git a/ui/gfx/font_list_impl.cc b/ui/gfx/font_list_impl.cc
index 6decee9..da82a0fb 100644
--- a/ui/gfx/font_list_impl.cc
+++ b/ui/gfx/font_list_impl.cc
@@ -219,8 +219,7 @@
   int ascent = 0;
   int descent = 0;
   const std::vector<Font>& fonts = GetFonts();
-  for (std::vector<Font>::const_iterator i = fonts.begin();
-       i != fonts.end(); ++i) {
+  for (auto i = fonts.begin(); i != fonts.end(); ++i) {
     ascent = std::max(ascent, i->GetBaseline());
     descent = std::max(descent, i->GetHeight() - i->GetBaseline());
   }
diff --git a/ui/gfx/font_render_params_linux.cc b/ui/gfx/font_render_params_linux.cc
index f12db00e..1277d92 100644
--- a/ui/gfx/font_render_params_linux.cc
+++ b/ui/gfx/font_render_params_linux.cc
@@ -138,8 +138,7 @@
 
   FcPatternAddBool(query_pattern.get(), FC_SCALABLE, FcTrue);
 
-  for (std::vector<std::string>::const_iterator it = query.families.begin();
-       it != query.families.end(); ++it) {
+  for (auto it = query.families.begin(); it != query.families.end(); ++it) {
     FcPatternAddString(query_pattern.get(),
         FC_FAMILY, reinterpret_cast<const FcChar8*>(it->c_str()));
   }
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc
index 855387a4..a81091e 100644
--- a/ui/gfx/image/image.cc
+++ b/ui/gfx/image/image.cc
@@ -123,8 +123,7 @@
   gfx::Size Size() const override {
     // Read the PNG data to get the image size, caching it.
     if (!size_cache_) {
-      for (std::vector<ImagePNGRep>::const_iterator it = image_reps().begin();
-           it != image_reps().end(); ++it) {
+      for (auto it = image_reps().begin(); it != image_reps().end(); ++it) {
         if (it->scale == 1.0f) {
           size_cache_.reset(new gfx::Size(it->Size()));
           return *size_cache_;
diff --git a/ui/gfx/image/image_family.cc b/ui/gfx/image/image_family.cc
index 0adc66923..adc1482c 100644
--- a/ui/gfx/image/image_family.cc
+++ b/ui/gfx/image/image_family.cc
@@ -79,8 +79,7 @@
 
 float ImageFamily::GetClosestAspect(float desired_aspect) const {
   // Find the two aspect ratios on either side of |desired_aspect|.
-  std::map<MapKey, gfx::Image>::const_iterator greater_or_equal =
-      map_.lower_bound(MapKey(desired_aspect, 0));
+  auto greater_or_equal = map_.lower_bound(MapKey(desired_aspect, 0));
   // Early exit optimization if there is an exact match.
   if (greater_or_equal != map_.end() &&
       greater_or_equal->first.aspect() == desired_aspect) {
@@ -91,8 +90,7 @@
   // aspect ratio >= |desired_aspect|, and |less_than| will point to the last
   // image with aspect ratio < |desired_aspect|.
   if (greater_or_equal != map_.begin()) {
-    std::map<MapKey, gfx::Image>::const_iterator less_than =
-        greater_or_equal;
+    auto less_than = greater_or_equal;
     --less_than;
     float thinner_aspect = less_than->first.aspect();
     DCHECK_GT(thinner_aspect, 0.0f);
@@ -148,8 +146,7 @@
 const gfx::Image* ImageFamily::GetWithExactAspect(float aspect,
                                                   int width) const {
   // Find the two images of given aspect ratio on either side of |width|.
-  std::map<MapKey, gfx::Image>::const_iterator greater_or_equal =
-      map_.lower_bound(MapKey(aspect, width));
+  auto greater_or_equal = map_.lower_bound(MapKey(aspect, width));
   if (greater_or_equal != map_.end() &&
       greater_or_equal->first.aspect() == aspect) {
     // We have found the smallest image of the same size or greater.
@@ -157,7 +154,7 @@
   }
 
   DCHECK(greater_or_equal != map_.begin());
-  std::map<MapKey, gfx::Image>::const_iterator less_than = greater_or_equal;
+  auto less_than = greater_or_equal;
   --less_than;
   // This must be true because there must be at least one image with |aspect|.
   DCHECK_EQ(less_than->first.aspect(), aspect);
diff --git a/ui/gfx/image/image_generic.cc b/ui/gfx/image/image_generic.cc
index 4c8510b..acca9d0 100644
--- a/ui/gfx/image/image_generic.cc
+++ b/ui/gfx/image/image_generic.cc
@@ -39,8 +39,8 @@
     // 1) The ImageSkiaRep with the highest scale if all available
     // scales are smaller than |scale|.
     // 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
-    for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
-         iter != image_skia_reps_.end(); ++iter) {
+    for (auto iter = image_skia_reps_.begin(); iter != image_skia_reps_.end();
+         ++iter) {
       if ((*iter).scale() == scale)
         return (*iter);
       if (!rep || rep->scale() < (*iter).scale())
diff --git a/ui/gfx/image/image_skia.cc b/ui/gfx/image/image_skia.cc
index 235505559..245a7408 100644
--- a/ui/gfx/image/image_skia.cc
+++ b/ui/gfx/image/image_skia.cc
@@ -154,7 +154,7 @@
                                    float scale)
     : source_(std::move(source)), read_only_(false) {
   DCHECK(source_);
-  ImageSkia::ImageSkiaReps::iterator it = FindRepresentation(scale, true);
+  auto it = FindRepresentation(scale, true);
   if (it == image_reps_.end() || it->is_null())
     source_.reset();
   else
@@ -208,12 +208,11 @@
     bool fetch_new_image) const {
   ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
 
-  ImageSkia::ImageSkiaReps::iterator closest_iter =
-      non_const->image_reps().end();
-  ImageSkia::ImageSkiaReps::iterator exact_iter = non_const->image_reps().end();
+  auto closest_iter = non_const->image_reps().end();
+  auto exact_iter = non_const->image_reps().end();
   float smallest_diff = std::numeric_limits<float>::max();
-  for (ImageSkia::ImageSkiaReps::iterator it = non_const->image_reps().begin();
-       it < image_reps_.end(); ++it) {
+  for (auto it = non_const->image_reps().begin(); it < image_reps_.end();
+       ++it) {
     if (it->scale() == scale) {
       // found exact match
       fetch_new_image = false;
@@ -239,8 +238,7 @@
     if (!HasRepresentationAtAllScales() && g_supported_scales)
       resource_scale = MapToSupportedScale(scale);
     if (scale != resource_scale) {
-      std::vector<ImageSkiaRep>::iterator iter =
-          FindRepresentation(resource_scale, fetch_new_image);
+      auto iter = FindRepresentation(resource_scale, fetch_new_image);
       CHECK(iter != image_reps_.end());
       image = iter->unscaled() ? (*iter) : ScaleImageSkiaRep(*iter, scale);
     } else {
@@ -349,8 +347,7 @@
   CHECK(CanRead());
 
   std::vector<gfx::ImageSkiaRep>& reps = storage_->image_reps();
-  for (std::vector<gfx::ImageSkiaRep>::iterator iter = reps.begin();
-       iter != reps.end(); ++iter) {
+  for (auto iter = reps.begin(); iter != reps.end(); ++iter) {
     copy->AddRepresentation(*iter);
   }
   // The copy has its own storage. Detach the copy from the current
@@ -392,8 +389,7 @@
   CHECK(CanModify());
 
   ImageSkiaReps& image_reps = storage_->image_reps();
-  ImageSkiaReps::iterator it =
-      storage_->FindRepresentation(scale, false);
+  auto it = storage_->FindRepresentation(scale, false);
   if (it != image_reps.end() && it->scale() == scale)
     image_reps.erase(it);
 }
@@ -411,7 +407,7 @@
   if (storage_->HasRepresentationAtAllScales())
     return true;
 
-  ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, false);
+  auto it = storage_->FindRepresentation(scale, false);
   return (it != storage_->image_reps().end() && it->scale() == scale);
 }
 
@@ -421,7 +417,7 @@
 
   CHECK(CanRead());
 
-  ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, true);
+  auto it = storage_->FindRepresentation(scale, true);
   if (it == storage_->image_reps().end())
     return NullImageRep();
 
@@ -470,8 +466,8 @@
   // Create list of image reps to return, skipping null image reps which were
   // added for caching purposes only.
   ImageSkiaReps image_reps;
-  for (ImageSkiaReps::iterator it = internal_image_reps.begin();
-       it != internal_image_reps.end(); ++it) {
+  for (auto it = internal_image_reps.begin(); it != internal_image_reps.end();
+       ++it) {
     if (!it->is_null())
       image_reps.push_back(*it);
   }
@@ -522,7 +518,7 @@
   CHECK(CanRead());
 #endif
 
-  ImageSkiaReps::iterator it = storage_->FindRepresentation(1.0f, true);
+  auto it = storage_->FindRepresentation(1.0f, true);
   if (it != storage_->image_reps().end())
     return it->GetBitmap();
   return NullImageRep().GetBitmap();
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index d08db4c..c8a9af2 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -1595,10 +1595,9 @@
             SkIntToScalar(origin.x()) + offset_x,
             SkIntToScalar(origin.y() + run.font_params.baseline_offset));
       }
-      for (BreakList<SkColor>::const_iterator it =
-               colors().GetBreak(segment.char_range.start());
+      for (auto it = colors().GetBreak(segment.char_range.start());
            it != colors().breaks().end() &&
-               it->first < segment.char_range.end();
+           it->first < segment.char_range.end();
            ++it) {
         const Range intersection =
             colors().GetRange(it).Intersect(segment.char_range);
diff --git a/ui/gfx/sequential_id_generator.cc b/ui/gfx/sequential_id_generator.cc
index 3d8b246..ad5ab8c 100644
--- a/ui/gfx/sequential_id_generator.cc
+++ b/ui/gfx/sequential_id_generator.cc
@@ -11,7 +11,7 @@
 // Removes |key| from |first|, and |first[key]| from |second|.
 template <typename T>
 void Remove(uint32_t key, T* first, T* second) {
-  typename T::iterator iter = first->find(key);
+  auto iter = first->find(key);
   if (iter == first->end())
     return;
 
@@ -34,7 +34,7 @@
 }
 
 uint32_t SequentialIDGenerator::GetGeneratedID(uint32_t number) {
-  IDMap::iterator find = number_to_id_.find(number);
+  auto find = number_to_id_.find(number);
   if (find != number_to_id_.end())
     return find->second;
 
diff --git a/ui/gl/gl_share_group.cc b/ui/gl/gl_share_group.cc
index 94708c0..e9386c4b 100644
--- a/ui/gl/gl_share_group.cc
+++ b/ui/gl/gl_share_group.cc
@@ -42,9 +42,7 @@
 }
 
 GLContext* GLShareGroup::GetContext() {
-  for (ContextSet::iterator it = contexts_.begin();
-       it != contexts_.end();
-       ++it) {
+  for (auto it = contexts_.begin(); it != contexts_.end(); ++it) {
     if ((*it)->GetHandle())
       return *it;
   }
diff --git a/ui/gl/gpu_timing_fake.cc b/ui/gl/gpu_timing_fake.cc
index 4a3fc2e..f446617 100644
--- a/ui/gl/gpu_timing_fake.cc
+++ b/ui/gl/gpu_timing_fake.cc
@@ -223,7 +223,7 @@
                                             GLuint* params) {
   switch (pname) {
     case GL_QUERY_RESULT_AVAILABLE: {
-      std::map<GLuint, QueryResult>::iterator it = query_results_.find(id);
+      auto it = query_results_.find(id);
       if (it != query_results_.end() && it->second.value_ <= current_gl_time_)
         *params = 1;
       else
@@ -262,7 +262,7 @@
                                               GLuint64* params) {
   switch (pname) {
     case GL_QUERY_RESULT: {
-      std::map<GLuint, QueryResult>::iterator it = query_results_.find(id);
+      auto it = query_results_.find(id);
       ASSERT_TRUE(it != query_results_.end());
       switch (it->second.type_) {
         case QueryResult::kQueryResultType_TimeStamp:
diff --git a/ui/latency/latency_info.cc b/ui/latency/latency_info.cc
index 089a3a95..aa09366e 100644
--- a/ui/latency/latency_info.cc
+++ b/ui/latency/latency_info.cc
@@ -283,7 +283,7 @@
                            "trace_id", trace_id_);
   }
 
-  LatencyMap::iterator it = latency_components_.find(component);
+  auto it = latency_components_.find(component);
   DCHECK(it == latency_components_.end());
   latency_components_[component] = time;
 
@@ -327,7 +327,7 @@
 
 bool LatencyInfo::FindLatency(LatencyComponentType type,
                               base::TimeTicks* output) const {
-  LatencyMap::const_iterator it = latency_components_.find(type);
+  auto it = latency_components_.find(type);
   if (it == latency_components_.end())
     return false;
   if (output)
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc
index c6f7e14..1c113d6 100644
--- a/ui/message_center/message_center_impl.cc
+++ b/ui/message_center/message_center_impl.cc
@@ -64,8 +64,7 @@
 void MessageCenterImpl::RemoveNotificationBlocker(
     NotificationBlocker* blocker) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  std::vector<NotificationBlocker*>::iterator iter =
-      std::find(blockers_.begin(), blockers_.end(), blocker);
+  auto iter = std::find(blockers_.begin(), blockers_.end(), blocker);
   if (iter == blockers_.end())
     return;
   blocker->RemoveObserver(this);
diff --git a/ui/message_center/message_center_impl_unittest.cc b/ui/message_center/message_center_impl_unittest.cc
index 430c2ce..6d85eb7 100644
--- a/ui/message_center/message_center_impl_unittest.cc
+++ b/ui/message_center/message_center_impl_unittest.cc
@@ -291,8 +291,7 @@
 bool PopupNotificationsContain(
     const NotificationList::PopupNotifications& popups,
     const std::string& id) {
-  for (NotificationList::PopupNotifications::const_iterator iter =
-           popups.begin(); iter != popups.end(); ++iter) {
+  for (auto iter = popups.begin(); iter != popups.end(); ++iter) {
     if ((*iter)->id() == id)
       return true;
   }
@@ -303,8 +302,7 @@
 bool NotificationsContain(
     const NotificationList::Notifications& notifications,
     const std::string& id) {
-  for (NotificationList::Notifications::const_iterator iter =
-           notifications.begin(); iter != notifications.end(); ++iter) {
+  for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
     if ((*iter)->id() == id)
       return true;
   }
diff --git a/ui/message_center/message_center_stats_collector.cc b/ui/message_center/message_center_stats_collector.cc
index 076da87..4f3faa6 100644
--- a/ui/message_center/message_center_stats_collector.cc
+++ b/ui/message_center/message_center_stats_collector.cc
@@ -61,7 +61,7 @@
     const std::string& notification_id) {
   stats_[notification_id] = NotificationStats(notification_id);
 
-  StatsCollection::iterator iter = stats_.find(notification_id);
+  auto iter = stats_.find(notification_id);
   DCHECK(iter != stats_.end());
 
   stats_[notification_id].CollectAction(NOTIFICATION_ACTION_ADD);
@@ -70,7 +70,7 @@
 void MessageCenterStatsCollector::OnNotificationRemoved(
     const std::string& notification_id,
     bool by_user) {
-  StatsCollection::iterator iter = stats_.find(notification_id);
+  auto iter = stats_.find(notification_id);
   if (iter == stats_.end())
     return;
   NotificationStats& notification_stat = iter->second;
@@ -83,7 +83,7 @@
 
 void MessageCenterStatsCollector::OnNotificationUpdated(
     const std::string& notification_id) {
-  StatsCollection::iterator iter = stats_.find(notification_id);
+  auto iter = stats_.find(notification_id);
   if (iter == stats_.end())
     return;
   NotificationStats& notification_stat = iter->second;
@@ -95,7 +95,7 @@
     const std::string& notification_id,
     const base::Optional<int>& button_index,
     const base::Optional<base::string16>& reply) {
-  StatsCollection::iterator iter = stats_.find(notification_id);
+  auto iter = stats_.find(notification_id);
   if (iter == stats_.end())
     return;
   NotificationStats& notification_stat = iter->second;
@@ -112,7 +112,7 @@
 void MessageCenterStatsCollector::OnNotificationDisplayed(
     const std::string& notification_id,
     const DisplaySource source) {
-  StatsCollection::iterator iter = stats_.find(notification_id);
+  auto iter = stats_.find(notification_id);
   if (iter == stats_.end())
     return;
   NotificationStats& notification_stat = iter->second;
diff --git a/ui/message_center/notification_list_unittest.cc b/ui/message_center/notification_list_unittest.cc
index 227681f..71432f1 100644
--- a/ui/message_center/notification_list_unittest.cc
+++ b/ui/message_center/notification_list_unittest.cc
@@ -118,8 +118,7 @@
 
 bool IsInNotifications(const NotificationList::Notifications& notifications,
                        const std::string& id) {
-  for (NotificationList::Notifications::const_iterator iter =
-           notifications.begin(); iter != notifications.end(); ++iter) {
+  for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
     if ((*iter)->id() == id)
       return true;
   }
@@ -305,14 +304,12 @@
   // one should come earlier in the popup list. It means, the last element
   // of |popups| should be the firstly added one, and so on.
   EXPECT_EQ(kMaxVisiblePopupNotifications, popups.size());
-  NotificationList::PopupNotifications::const_reverse_iterator iter =
-      popups.rbegin();
+  auto iter = popups.rbegin();
   for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i, ++iter) {
     EXPECT_EQ(ids[i], (*iter)->id()) << i;
   }
 
-  for (NotificationList::PopupNotifications::const_iterator iter =
-           popups.begin(); iter != popups.end(); ++iter) {
+  for (auto iter = popups.begin(); iter != popups.end(); ++iter) {
     notification_list_->MarkSinglePopupAsShown((*iter)->id(), false);
   }
   popups.clear();
@@ -346,8 +343,7 @@
 
   NotificationList::Notifications notifications =
       notification_list_->GetVisibleNotifications(blockers_);
-  for (NotificationList::Notifications::const_iterator iter =
-           notifications.begin(); iter != notifications.end(); ++iter) {
+  for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
     notification_list_->RemoveNotification((*iter)->id());
   }
 
@@ -582,7 +578,7 @@
     // Popups: latest comes first.
     NotificationList::PopupNotifications popups = GetPopups();
     EXPECT_EQ(3u, popups.size());
-    NotificationList::PopupNotifications::const_iterator iter = popups.begin();
+    auto iter = popups.begin();
     EXPECT_EQ(default_id, (*iter)->id());
     iter++;
     EXPECT_EQ(high_id, (*iter)->id());
@@ -594,8 +590,7 @@
     const NotificationList::Notifications notifications =
         notification_list_->GetVisibleNotifications(blockers_);
     EXPECT_EQ(3u, notifications.size());
-    NotificationList::Notifications::const_iterator iter =
-        notifications.begin();
+    auto iter = notifications.begin();
     EXPECT_EQ(max_id, (*iter)->id());
     iter++;
     EXPECT_EQ(high_id, (*iter)->id());
@@ -625,7 +620,7 @@
   // The notifications in the NotificationCenter are unaffected by popups shown.
   NotificationList::Notifications notifications =
       notification_list_->GetVisibleNotifications(blockers_);
-  NotificationList::Notifications::const_iterator iter = notifications.begin();
+  auto iter = notifications.begin();
   EXPECT_EQ(id3, (*iter)->id());
   iter++;
   EXPECT_EQ(id2, (*iter)->id());
diff --git a/ui/message_center/popup_timers_controller.cc b/ui/message_center/popup_timers_controller.cc
index 359f104..0c5eead 100644
--- a/ui/message_center/popup_timers_controller.cc
+++ b/ui/message_center/popup_timers_controller.cc
@@ -98,8 +98,7 @@
     return;
   }
 
-  NotificationList::PopupNotifications::const_iterator iter =
-      popup_notifications.begin();
+  auto iter = popup_notifications.begin();
   for (; iter != popup_notifications.end(); ++iter) {
     if ((*iter)->id() == id)
       break;
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc
index 8a5890a..d25b6a8b 100644
--- a/ui/message_center/views/notification_view_unittest.cc
+++ b/ui/message_center/views/notification_view_unittest.cc
@@ -128,8 +128,8 @@
     std::copy(notification_view()->action_buttons_.begin(),
               notification_view()->action_buttons_.end(),
               std::back_inserter(vertical_order));
-    std::vector<views::View*>::iterator current = vertical_order.begin();
-    std::vector<views::View*>::iterator last = current++;
+    auto current = vertical_order.begin();
+    auto last = current++;
     while (current != vertical_order.end()) {
       gfx::Point last_point = (*last)->origin();
       views::View::ConvertPointToTarget(
diff --git a/ui/views/controls/button/radio_button.cc b/ui/views/controls/button/radio_button.cc
index 9adf494..6113742 100644
--- a/ui/views/controls/button/radio_button.cc
+++ b/ui/views/controls/button/radio_button.cc
@@ -99,7 +99,7 @@
     if (container) {
       Views other;
       container->GetViewsInGroup(GetGroup(), &other);
-      for (Views::iterator i(other.begin()); i != other.end(); ++i) {
+      for (auto i(other.begin()); i != other.end(); ++i) {
         if (*i != this) {
           if (strcmp((*i)->GetClassName(), kViewClassName)) {
             NOTREACHED() << "radio-button-nt has same group as other non "
diff --git a/ui/views/controls/image_view_base.cc b/ui/views/controls/image_view_base.cc
index f942680..5bb66f8 100644
--- a/ui/views/controls/image_view_base.cc
+++ b/ui/views/controls/image_view_base.cc
@@ -76,7 +76,7 @@
 
 void ImageViewBase::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ax::mojom::Role::kImage;
-  node_data->SetName(tooltip_text_);
+  node_data->SetName(accessible_name_);
 }
 
 void ImageViewBase::SetHorizontalAlignment(Alignment alignment) {
@@ -111,8 +111,11 @@
   return accessible_name_;
 }
 
+// TODO(crbug.com/890465): Update the duplicate code here and in views::Button.
 void ImageViewBase::SetTooltipText(const base::string16& tooltip) {
   tooltip_text_ = tooltip;
+  if (accessible_name_.empty())
+    accessible_name_ = tooltip_text_;
 }
 
 base::string16 ImageViewBase::GetTooltipText() const {
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 63a169e..5a2af4b 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -1845,8 +1845,7 @@
   // Open all the submenus preceeding the last menu item (last menu item is
   // handled next).
   if (new_path.size() > 1) {
-    for (std::vector<MenuItemView*>::iterator i = new_path.begin();
-         i != new_path.end() - 1; ++i) {
+    for (auto i = new_path.begin(); i != new_path.end() - 1; ++i) {
       OpenMenu(*i);
     }
   }
diff --git a/ui/views/controls/menu/menu_runner_impl.cc b/ui/views/controls/menu/menu_runner_impl.cc
index 1c7b5c4..3f1fb8a 100644
--- a/ui/views/controls/menu/menu_runner_impl.cc
+++ b/ui/views/controls/menu/menu_runner_impl.cc
@@ -192,8 +192,7 @@
 
 MenuRunnerImpl::~MenuRunnerImpl() {
   delete menu_;
-  for (std::set<MenuItemView*>::iterator i = sibling_menus_.begin();
-       i != sibling_menus_.end(); ++i)
+  for (auto i = sibling_menus_.begin(); i != sibling_menus_.end(); ++i)
     delete *i;
 }
 
diff --git a/ui/views/controls/native/native_view_host.cc b/ui/views/controls/native/native_view_host.cc
index a0c853b..5240d2bf 100644
--- a/ui/views/controls/native/native_view_host.cc
+++ b/ui/views/controls/native/native_view_host.cc
@@ -229,7 +229,7 @@
 
   Widget::Widgets widgets;
   Widget::GetAllChildWidgets(native_view(), &widgets);
-  for (Widget::Widgets::iterator i = widgets.begin(); i != widgets.end(); ++i) {
+  for (auto i = widgets.begin(); i != widgets.end(); ++i) {
     focus_manager->ViewRemoved((*i)->GetRootView());
     if (!focus_manager->GetFocusedView())
       return;
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc
index a809ece..1bfea071 100644
--- a/ui/views/controls/textfield/textfield_model.cc
+++ b/ui/views/controls/textfield/textfield_model.cc
@@ -487,7 +487,7 @@
   if (edit_history_.empty())
     return false;
   // There is no redo iff the current edit is the last element in the history.
-  EditHistory::iterator iter = current_edit_;
+  auto iter = current_edit_;
   return iter == edit_history_.end() || // at the top.
       ++iter != edit_history_.end();
 }
@@ -761,7 +761,7 @@
     ClearEditHistory();
     return;
   }
-  EditHistory::iterator delete_start = current_edit_;
+  auto delete_start = current_edit_;
   ++delete_start;
   edit_history_.erase(delete_start, edit_history_.end());
 }
diff --git a/ui/views/corewm/tooltip_controller_unittest.cc b/ui/views/corewm/tooltip_controller_unittest.cc
index 1212a6f..8351993 100644
--- a/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/ui/views/corewm/tooltip_controller_unittest.cc
@@ -463,10 +463,8 @@
 
 // Returns the index of |window| in its parent's children.
 int IndexInParent(const aura::Window* window) {
-  aura::Window::Windows::const_iterator i =
-      std::find(window->parent()->children().begin(),
-                window->parent()->children().end(),
-                window);
+  auto i = std::find(window->parent()->children().begin(),
+                     window->parent()->children().end(), window);
   return i == window->parent()->children().end() ? -1 :
       static_cast<int>(i - window->parent()->children().begin());
 }
diff --git a/ui/views/examples/menu_example.cc b/ui/views/examples/menu_example.cc
index 2e9081c..3c2713a 100644
--- a/ui/views/examples/menu_example.cc
+++ b/ui/views/examples/menu_example.cc
@@ -155,7 +155,7 @@
         checked_fruit = "Kiwi";
 
       // Update the check status.
-      std::set<int>::iterator iter = checked_fruits_.find(command_id);
+      auto iter = checked_fruits_.find(command_id);
       if (iter == checked_fruits_.end()) {
         DVLOG(1) << "Checked " << checked_fruit;
         checked_fruits_.insert(command_id);
diff --git a/ui/views/layout/box_layout.cc b/ui/views/layout/box_layout.cc
index f9c1b6d..cdc9750 100644
--- a/ui/views/layout/box_layout.cc
+++ b/ui/views/layout/box_layout.cc
@@ -363,7 +363,7 @@
 }
 
 int BoxLayout::GetFlexForView(const View* view) const {
-  FlexMap::const_iterator it = flex_map_.find(view);
+  auto it = flex_map_.find(view);
   if (it == flex_map_.end())
     return default_flex_;
 
@@ -371,7 +371,7 @@
 }
 
 int BoxLayout::GetMinimumSizeForView(const View* view) const {
-  FlexMap::const_iterator it = flex_map_.find(view);
+  auto it = flex_map_.find(view);
   if (it == flex_map_.end() || !it->second.use_min_size)
     return 0;
 
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 1a1636af..d0aba92 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -311,7 +311,7 @@
 }
 
 int View::GetIndexOf(const View* view) const {
-  Views::const_iterator i(std::find(children_.begin(), children_.end(), view));
+  auto i(std::find(children_.begin(), children_.end(), view));
   return i != children_.end() ? static_cast<int>(i - children_.begin()) : -1;
 }
 
@@ -1216,8 +1216,7 @@
     return;
   }
 
-  std::vector<ui::Accelerator>::iterator i(
-      std::find(accelerators_->begin(), accelerators_->end(), accelerator));
+  auto i(std::find(accelerators_->begin(), accelerators_->end(), accelerator));
   if (i == accelerators_->end()) {
     NOTREACHED() << "Removing non-existing accelerator";
     return;
@@ -2211,7 +2210,7 @@
   // Notify interested Views that visible bounds within the root view may have
   // changed.
   if (descendants_to_notify_.get()) {
-    for (Views::iterator i(descendants_to_notify_->begin());
+    for (auto i(descendants_to_notify_->begin());
          i != descendants_to_notify_->end(); ++i) {
       (*i)->OnVisibleBoundsChanged();
     }
@@ -2261,8 +2260,8 @@
 
 void View::RemoveDescendantToNotify(View* view) {
   DCHECK(view && descendants_to_notify_.get());
-  Views::iterator i(std::find(
-      descendants_to_notify_->begin(), descendants_to_notify_->end(), view));
+  auto i(std::find(descendants_to_notify_->begin(),
+                   descendants_to_notify_->end(), view));
   DCHECK(i != descendants_to_notify_->end());
   descendants_to_notify_->erase(i);
   if (descendants_to_notify_->empty())
diff --git a/ui/views/widget/desktop_aura/desktop_capture_client.cc b/ui/views/widget/desktop_aura/desktop_capture_client.cc
index 86578b9..38447dc9 100644
--- a/ui/views/widget/desktop_aura/desktop_capture_client.cc
+++ b/ui/views/widget/desktop_aura/desktop_capture_client.cc
@@ -79,8 +79,7 @@
     // Notify the other roots that we got capture. This is important so that
     // they reset state.
     CaptureClients capture_clients(*capture_clients_);
-    for (CaptureClients::iterator i = capture_clients.begin();
-         i != capture_clients.end(); ++i) {
+    for (auto i = capture_clients.begin(); i != capture_clients.end(); ++i) {
       if (*i != this) {
         aura::client::CaptureDelegate* delegate =
             (*i)->root_->GetHost()->dispatcher();
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
index 6ae0806..f0da4f8 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -450,8 +450,7 @@
 
 int DesktopDragDropClientAuraX11::X11DragContext::GetDragOperation() const {
   int drag_operation = ui::DragDropTypes::DRAG_NONE;
-  for (std::vector<::Atom>::const_iterator it = actions_.begin();
-       it != actions_.end(); ++it) {
+  for (auto it = actions_.begin(); it != actions_.end(); ++it) {
     MaskOperation(*it, &drag_operation);
   }
 
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
index a6fe148..f60cc49 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
@@ -354,8 +354,7 @@
 }
 
 void TestDragDropClient::SendXClientEvent(::Window xid, XEvent* event) {
-  std::map< ::Window, ClientMessageEventCollector*>::iterator it =
-      collectors_.find(xid);
+  auto it = collectors_.find(xid);
   if (it != collectors_.end())
     it->second->RecordEvent(event->xclient);
 }
diff --git a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
index 5d4ae7a..d073133 100644
--- a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
@@ -51,7 +51,7 @@
   delegate->CommitCursor(new_cursor);
 
   if (delegate->IsCursorVisible()) {
-    for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+    for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
       (*i)->SetCursor(new_cursor);
   }
 }
@@ -66,11 +66,11 @@
   } else {
     gfx::NativeCursor invisible_cursor(ui::CursorType::kNone);
     cursor_loader_->SetPlatformCursor(&invisible_cursor);
-    for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+    for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
       (*i)->SetCursor(invisible_cursor);
   }
 
-  for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+  for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
     (*i)->OnCursorVisibilityChanged(visible);
 }
 
@@ -90,7 +90,7 @@
 
   SetVisibility(delegate->IsCursorVisible(), delegate);
 
-  for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+  for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
     (*i)->dispatcher()->OnMouseEventsEnableStateChanged(enabled);
 }
 
diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index 98fa87c..0951d2fb 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -232,8 +232,7 @@
     const gfx::Point& point) const {
   if (displays_.size() <= 1)
     return GetPrimaryDisplay();
-  for (std::vector<display::Display>::const_iterator it = displays_.begin();
-       it != displays_.end(); ++it) {
+  for (auto it = displays_.begin(); it != displays_.end(); ++it) {
     if (it->bounds().Contains(point))
       return *it;
   }
@@ -244,8 +243,7 @@
     const gfx::Rect& match_rect) const {
   int max_area = 0;
   const display::Display* matching = NULL;
-  for (std::vector<display::Display>::const_iterator it = displays_.begin();
-       it != displays_.end(); ++it) {
+  for (auto it = displays_.begin(); it != displays_.end(); ++it) {
     gfx::Rect intersect = gfx::IntersectRects(it->bounds(), match_rect);
     int area = intersect.width() * intersect.height();
     if (area > max_area) {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 496f1e39..53e0077 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -476,8 +476,7 @@
   // If we have children, close them. Use a copy for iteration because they'll
   // remove themselves.
   std::set<DesktopWindowTreeHostX11*> window_children_copy = window_children_;
-  for (std::set<DesktopWindowTreeHostX11*>::iterator it =
-           window_children_copy.begin(); it != window_children_copy.end();
+  for (auto it = window_children_copy.begin(); it != window_children_copy.end();
        ++it) {
     (*it)->CloseNow();
   }
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index dc9c3c6..28c63b02 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -1157,8 +1157,7 @@
   }
 
   const aura::Window::Windows& child_windows = native_view->children();
-  for (aura::Window::Windows::const_iterator i = child_windows.begin();
-       i != child_windows.end(); ++i) {
+  for (auto i = child_windows.begin(); i != child_windows.end(); ++i) {
     GetAllChildWidgets((*i), children);
   }
 }
@@ -1194,8 +1193,7 @@
 
   // First notify all the widgets that they are being disassociated
   // from their previous parent.
-  for (Widget::Widgets::iterator it = widgets.begin();
-      it != widgets.end(); ++it) {
+  for (auto it = widgets.begin(); it != widgets.end(); ++it) {
     (*it)->NotifyNativeViewHierarchyWillChange();
   }
 
@@ -1219,8 +1217,7 @@
   }
 
   // And now, notify them that they have a brand new parent.
-  for (Widget::Widgets::iterator it = widgets.begin();
-      it != widgets.end(); ++it) {
+  for (auto it = widgets.begin(); it != widgets.end(); ++it) {
     (*it)->NotifyNativeViewHierarchyChanged();
   }
 }
diff --git a/ui/views/widget/window_reorderer.cc b/ui/views/widget/window_reorderer.cc
index 2f83b18f..2f459a86 100644
--- a/ui/views/widget/window_reorderer.cc
+++ b/ui/views/widget/window_reorderer.cc
@@ -166,14 +166,13 @@
   // |view_with_layer_order| backwards and stack windows at the bottom so that
   // windows not associated to a view are stacked above windows with an
   // associated view.
-  for (std::vector<View*>::reverse_iterator it = view_with_layer_order.rbegin();
+  for (auto it = view_with_layer_order.rbegin();
        it != view_with_layer_order.rend(); ++it) {
     View* view = *it;
     ui::Layer* layer = view->layer();
     aura::Window* window = NULL;
 
-    std::map<View*, aura::Window*>::iterator hosted_window_it =
-        hosted_windows.find(view);
+    auto hosted_window_it = hosted_windows.find(view);
     if (hosted_window_it != hosted_windows.end()) {
       window = hosted_window_it->second;
       layer = window->layer();
diff --git a/ui/views/widget/window_reorderer_unittest.cc b/ui/views/widget/window_reorderer_unittest.cc
index 579e622..faecf6b 100644
--- a/ui/views/widget/window_reorderer_unittest.cc
+++ b/ui/views/widget/window_reorderer_unittest.cc
@@ -39,9 +39,8 @@
 // first) of |parent|. The format of the string is "name1 name2 name3 ...".
 std::string ChildWindowNamesAsString(const aura::Window& parent) {
   std::string names;
-  typedef std::vector<aura::Window*> Windows;
-  for (Windows::const_iterator it = parent.children().begin();
-       it != parent.children().end(); ++it) {
+  for (auto it = parent.children().begin(); it != parent.children().end();
+       ++it) {
     if (!names.empty())
       names += " ";
     names += (*it)->GetName();
diff --git a/ui/views/window/custom_frame_view.cc b/ui/views/window/custom_frame_view.cc
index 0ae8ebd..01a5c58 100644
--- a/ui/views/window/custom_frame_view.cc
+++ b/ui/views/window/custom_frame_view.cc
@@ -522,8 +522,7 @@
       button_order->trailing_buttons();
 
   ImageButton* button = NULL;
-  for (std::vector<views::FrameButton>::const_iterator it =
-           leading_buttons.begin(); it != leading_buttons.end(); ++it) {
+  for (auto it = leading_buttons.begin(); it != leading_buttons.end(); ++it) {
     button = GetImageButton(*it);
     if (!button)
       continue;
@@ -538,8 +537,8 @@
 
   // Trailing buttions are laid out in a RTL fashion
   next_button_x = width() - FrameBorderThickness();
-  for (std::vector<views::FrameButton>::const_reverse_iterator it =
-           trailing_buttons.rbegin(); it != trailing_buttons.rend(); ++it) {
+  for (auto it = trailing_buttons.rbegin(); it != trailing_buttons.rend();
+       ++it) {
     button = GetImageButton(*it);
     if (!button)
       continue;
diff --git a/ui/wm/core/base_focus_rules.cc b/ui/wm/core/base_focus_rules.cc
index 73e95142..eb446ee 100644
--- a/ui/wm/core/base_focus_rules.cc
+++ b/ui/wm/core/base_focus_rules.cc
@@ -178,9 +178,7 @@
   const aura::Window::Windows& siblings = ignore->parent()->children();
   DCHECK(!siblings.empty());
 
-  for (aura::Window::Windows::const_reverse_iterator rit = siblings.rbegin();
-       rit != siblings.rend();
-       ++rit) {
+  for (auto rit = siblings.rbegin(); rit != siblings.rend(); ++rit) {
     aura::Window* cur = *rit;
     if (cur == ignore)
       continue;
diff --git a/ui/wm/core/transient_window_manager.cc b/ui/wm/core/transient_window_manager.cc
index dd65f45..80a57bab 100644
--- a/ui/wm/core/transient_window_manager.cc
+++ b/ui/wm/core/transient_window_manager.cc
@@ -84,7 +84,7 @@
 }
 
 void TransientWindowManager::RemoveTransientChild(Window* child) {
-  Windows::iterator i =
+  auto i =
       std::find(transient_children_.begin(), transient_children_.end(), child);
   DCHECK(i != transient_children_.end());
   transient_children_.erase(i);
@@ -131,8 +131,7 @@
   // |window_|. The existing stacking order is preserved by iterating backwards
   // and always stacking on top.
   Window::Windows children(parent->children());
-  for (Window::Windows::reverse_iterator it = children.rbegin();
-       it != children.rend(); ++it) {
+  for (auto it = children.rbegin(); it != children.rend(); ++it) {
     if ((*it) != window_ && HasTransientAncestor(*it, window_)) {
       TransientWindowManager* descendant_manager = GetOrCreate(*it);
       base::AutoReset<Window*> resetter(
@@ -205,10 +204,8 @@
   // Do nothing if we initiated the stacking change.
   const TransientWindowManager* transient_manager = GetIfExists(window);
   if (transient_manager && transient_manager->stacking_target_) {
-    Windows::const_iterator window_i = std::find(
-        window->parent()->children().begin(),
-        window->parent()->children().end(),
-        window);
+    auto window_i = std::find(window->parent()->children().begin(),
+                              window->parent()->children().end(), window);
     DCHECK(window_i != window->parent()->children().end());
     if (window_i != window->parent()->children().begin() &&
         (*(window_i - 1) == transient_manager->stacking_target_))
diff --git a/ui/wm/core/transient_window_stacking_client.cc b/ui/wm/core/transient_window_stacking_client.cc
index 1811098..ff373762 100644
--- a/ui/wm/core/transient_window_stacking_client.cc
+++ b/ui/wm/core/transient_window_stacking_client.cc
@@ -45,8 +45,8 @@
     return;
   }
   // Walk the two chains backwards and look for the first difference.
-  Window::Windows::reverse_iterator it1 = ancestors1.rbegin();
-  Window::Windows::reverse_iterator it2 = ancestors2.rbegin();
+  auto it1 = ancestors1.rbegin();
+  auto it2 = ancestors2.rbegin();
   for (; it1  != ancestors1.rend() && it2  != ancestors2.rend(); ++it1, ++it2) {
     if (*it1 != *it2) {
       *window1 = *it1;
diff --git a/ui/wm/core/window_animations.cc b/ui/wm/core/window_animations.cc
index 7177a1c..d61a35a 100644
--- a/ui/wm/core/window_animations.cc
+++ b/ui/wm/core/window_animations.cc
@@ -85,10 +85,8 @@
     if (window_->parent()) {
       const aura::Window::Windows& transient_children =
           GetTransientChildren(window_);
-      aura::Window::Windows::const_iterator iter =
-          std::find(window_->parent()->children().begin(),
-                    window_->parent()->children().end(),
-                    window_);
+      auto iter = std::find(window_->parent()->children().begin(),
+                            window_->parent()->children().end(), window_);
       DCHECK(iter != window_->parent()->children().end());
       aura::Window* topmost_transient_child = NULL;
       for (++iter; iter != window_->parent()->children().end(); ++iter) {
diff --git a/ui/wm/core/window_animations_unittest.cc b/ui/wm/core/window_animations_unittest.cc
index 3b8a8247..f8e993a 100644
--- a/ui/wm/core/window_animations_unittest.cc
+++ b/ui/wm/core/window_animations_unittest.cc
@@ -31,8 +31,7 @@
 template<typename T>int GetZPosition(const T* child) {
   const T* parent = child->parent();
   const std::vector<T*> children = parent->children();
-  typename std::vector<T*>::const_iterator iter =
-      std::find(children.begin(), children.end(), child);
+  auto iter = std::find(children.begin(), children.end(), child);
   DCHECK(iter != children.end());
   return iter - children.begin();
 }