diff --git a/DEPS b/DEPS
index 52aff2b..18b9add 100644
--- a/DEPS
+++ b/DEPS
@@ -40,11 +40,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': 'db0e4f952a71a7a5009ec8276a234227e0ec18f6',
+  'skia_revision': 'af7bbc8b0495612cdbc98847fadb0a08924c41bb',
   # 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': 'a2104e4aebf5d9a498b54eb1f350fa596e9f1efd',
+  'v8_revision': '11e3de08c734763e1f9f6907cf41d97c6465c5e3',
   # 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.
@@ -52,7 +52,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': 'abe89c7d32d719ffd86ce2400505188b52b55e4c',
+  'angle_revision': '308d745d8e3c7710778c993a9b37fe74d0a2bc12',
   # 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.
@@ -96,7 +96,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': 'df581f5fc8deac24b0027c260b6bace47906161b',
+  'catapult_revision': '71c4c9aba898fe6d112646d549cb94de1b41a54f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/build/android/pylib/constants/__init__.py b/build/android/pylib/constants/__init__.py
index 80ad2c1a..916ee27 100644
--- a/build/android/pylib/constants/__init__.py
+++ b/build/android/pylib/constants/__init__.py
@@ -37,28 +37,28 @@
     'chromecast_shell': chrome.PackageInfo(
         'com.google.android.apps.mediashell',
         'com.google.android.apps.mediashell.MediaShellActivity',
-        '/data/local/tmp/castshell-command-line',
+        'castshell-command-line',
         None),
     'android_webview_shell': chrome.PackageInfo(
         'org.chromium.android_webview.shell',
         'org.chromium.android_webview.shell.AwShellActivity',
-        '/data/local/tmp/android-webview-command-line',
+        'android-webview-command-line',
         None),
     'gtest': chrome.PackageInfo(
         'org.chromium.native_test',
         'org.chromium.native_test.NativeUnitTestActivity',
-        '/data/local/tmp/chrome-native-tests-command-line',
+        'chrome-native-tests-command-line',
         None),
     'components_browsertests': chrome.PackageInfo(
         'org.chromium.components_browsertests_apk',
         ('org.chromium.components_browsertests_apk' +
          '.ComponentsBrowserTestsActivity'),
-        '/data/local/tmp/chrome-native-tests-command-line',
+        'chrome-native-tests-command-line',
         None),
     'content_browsertests': chrome.PackageInfo(
         'org.chromium.content_browsertests_apk',
         'org.chromium.content_browsertests_apk.ContentBrowserTestsActivity',
-        '/data/local/tmp/chrome-native-tests-command-line',
+        'chrome-native-tests-command-line',
         None),
     'chromedriver_webview_shell': chrome.PackageInfo(
         'org.chromium.chromedriver_webview_shell',
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
index 0c5f37a3..aad8ce4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java
@@ -73,7 +73,7 @@
         mUiConfig = uiConfig;
         mRoot = new InnerNode();
 
-        mSections = new SectionList(mUiDelegate, offlinePageBridge, mUiConfig);
+        mSections = new SectionList(mUiDelegate, offlinePageBridge);
         mSigninPromo = new SignInPromo(mUiDelegate);
         mAllDismissed = new AllDismissedItem();
         mFooter = new Footer();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
index 1199690..24bc8c0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.suggestions.SuggestionsRanker;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
 
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -36,12 +35,9 @@
     private final SuggestionsUiDelegate mUiDelegate;
     private final OfflinePageBridge mOfflinePageBridge;
     private final SuggestionsRanker mSuggestionsRanker;
-    private final UiConfig mUiConfig;
 
-    public SectionList(SuggestionsUiDelegate uiDelegate, OfflinePageBridge offlinePageBridge,
-            UiConfig uiConfig) {
+    public SectionList(SuggestionsUiDelegate uiDelegate, OfflinePageBridge offlinePageBridge) {
         mSuggestionsRanker = new SuggestionsRanker();
-        mUiConfig = uiConfig;
         mUiDelegate = uiDelegate;
         mUiDelegate.getSuggestionsSource().setObserver(this);
         mUiDelegate.getMetricsReporter().setRanker(mSuggestionsRanker);
@@ -247,9 +243,6 @@
         // If there is more than a section we want to show the headers for disambiguation purposes.
         if (mSections.size() != 1) return;
 
-        // On larger screens there is no need to hide the header and showing it is more consistent.
-        if (!mUiConfig.getCurrentDisplayStyle().isSmall()) return;
-
         SuggestionsSection articlesSection = mSections.get(KnownCategories.ARTICLES);
         if (articlesSection == null) return;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
index d2498867..05815973 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -37,8 +37,6 @@
 public class SuggestionsSection extends InnerNode {
     private static final String TAG = "NtpCards";
 
-    private static final Set<Integer> SECTION_DISMISSAL_GROUP = new HashSet<>(Arrays.asList(1, 2));
-
     private final Delegate mDelegate;
     private final SuggestionsCategoryInfo mCategoryInfo;
     private final OfflinePageBridge mOfflinePageBridge;
@@ -489,14 +487,11 @@
     private Set<Integer> getSectionDismissalRange() {
         if (hasSuggestions()) return Collections.emptySet();
 
-        if (!mMoreButton.isVisible()) {
-            assert getStartingOffsetForChild(mStatus) == 1;
-            return Collections.singleton(1);
-        }
+        int statusCardIndex = getStartingOffsetForChild(mStatus);
+        if (!mMoreButton.isVisible()) return Collections.singleton(statusCardIndex);
 
-        assert SECTION_DISMISSAL_GROUP.contains(getStartingOffsetForChild(mStatus));
-        assert SECTION_DISMISSAL_GROUP.contains(getStartingOffsetForChild(mMoreButton));
-        return SECTION_DISMISSAL_GROUP;
+        assert statusCardIndex + 1 == getStartingOffsetForChild(mMoreButton);
+        return new HashSet<>(Arrays.asList(statusCardIndex, statusCardIndex + 1));
     }
 
     public SuggestionsCategoryInfo getCategoryInfo() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java
index 36a80ad..225e06b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java
@@ -18,6 +18,7 @@
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ImageButton;
@@ -214,25 +215,45 @@
         text.setText(message);
         text.announceForAccessibility(message);
 
-        final int screenWidth = resources.getDisplayMetrics().widthPixels;
-        final int screenHeight = resources.getDisplayMetrics().heightPixels;
-
+        // The tooltip should be shown above and to the left (right for RTL) of the info button.
+        // In order to do so the tooltip's location on the screen is determined. This location is
+        // specified with regard to the top left corner and ignores RTL layouts. For this reason the
+        // location of the tooltip is also specified as offsets to the top left corner of the
+        // screen. Since the tooltip should be shown above the info button, the height of the
+        // tooltip needs to be measured. Furthermore, the height of the statusbar is ignored when
+        // obtaining the icon's screen location, but must be considered when specifying a y offset.
+        // In addition, the measured width is needed in LTR layout, so that the right end of the
+        // tooltip aligns with the right end of the info icon.
         final int[] screenPos = new int[2];
         view.getLocationOnScreen(screenPos);
 
-        final int width = view.getWidth();
-        final int tooltipMargin = resources.getDimensionPixelSize(R.dimen.psl_info_tooltip_margin);
+        text.measure(MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+                MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
 
-        // The toast should be shown above and to the left (right for RTL) of the info button.
-        // In order to avoid measuring the size of the toast offsets are specified with regard
-        // to the bottom right / left corner of the screen.
+        final int width = view.getWidth();
+
         final int xOffset = ApiCompatibilityUtils.isLayoutRtl(view)
                 ? screenPos[0]
-                : screenWidth - screenPos[0] - width;
-        final int yOffset = screenHeight - screenPos[1] + tooltipMargin;
+                : screenPos[0] + width - text.getMeasuredWidth();
+
+        final int statusBarHeightResourceId =
+                resources.getIdentifier("status_bar_height", "dimen", "android");
+
+        final int statusBarHeight = statusBarHeightResourceId > 0
+                ? resources.getDimensionPixelSize(statusBarHeightResourceId)
+                : 0;
+
+        final int tooltipMargin = resources.getDimensionPixelSize(R.dimen.psl_info_tooltip_margin);
+
+        final int yOffset =
+                screenPos[1] - tooltipMargin - statusBarHeight - text.getMeasuredHeight();
+
+        // The xOffset is with regard to the left edge of the screen. Gravity.LEFT is deprecated,
+        // which is why the following line is necessary.
+        final int xGravity = ApiCompatibilityUtils.isLayoutRtl(view) ? Gravity.END : Gravity.START;
 
         Toast toast = new Toast(context);
-        toast.setGravity(Gravity.BOTTOM | Gravity.END, xOffset, yOffset);
+        toast.setGravity(Gravity.TOP | xGravity, xOffset, yOffset);
         toast.setDuration(Toast.LENGTH_SHORT);
         toast.setView(text);
         toast.show();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/displaystyle/UiConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/displaystyle/UiConfig.java
index ce5bfd9..5aa23d6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/displaystyle/UiConfig.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/displaystyle/UiConfig.java
@@ -19,10 +19,9 @@
  * Exposes general configuration info about the display style for a given reference View.
  */
 public class UiConfig {
-
-    public static final int REGULAR_DISPLAY_STYLE_MIN_WIDTH_DP = 360;
+    public static final int NARROW_DISPLAY_STYLE_MAX_WIDTH_DP = 320;
     public static final int WIDE_DISPLAY_STYLE_MIN_WIDTH_DP = 600;
-    public static final int REGULAR_DISPLAY_STYLE_MIN_HEIGHT_DP = 360;
+    public static final int FLAT_DISPLAY_STYLE_MAX_HEIGHT_DP = 320;
 
     private static final String TAG = "DisplayStyle";
     private static final boolean DEBUG = false;
@@ -94,7 +93,7 @@
 
         @HorizontalDisplayStyle
         int newHorizontalDisplayStyle;
-        if (widthDp < REGULAR_DISPLAY_STYLE_MIN_WIDTH_DP) {
+        if (widthDp <= NARROW_DISPLAY_STYLE_MAX_WIDTH_DP) {
             newHorizontalDisplayStyle = HorizontalDisplayStyle.NARROW;
         } else if (widthDp >= WIDE_DISPLAY_STYLE_MIN_WIDTH_DP) {
             newHorizontalDisplayStyle = HorizontalDisplayStyle.WIDE;
@@ -104,8 +103,8 @@
 
         @VerticalDisplayStyle
         int newVerticalDisplayStyle =
-                heightDp < REGULAR_DISPLAY_STYLE_MIN_HEIGHT_DP ? VerticalDisplayStyle.FLAT
-                                                               : VerticalDisplayStyle.REGULAR;
+                heightDp <= FLAT_DISPLAY_STYLE_MAX_HEIGHT_DP ? VerticalDisplayStyle.FLAT
+                                                             : VerticalDisplayStyle.REGULAR;
 
         final DisplayStyle displayStyle =
                 new DisplayStyle(newHorizontalDisplayStyle, newVerticalDisplayStyle);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java
index 750ed15f..f9e2a34b 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SectionListTest.java
@@ -14,7 +14,6 @@
 import static org.mockito.Mockito.when;
 
 import static org.chromium.chrome.browser.ntp.cards.ContentSuggestionsUnitTestUtils.bindViewHolders;
-import static org.chromium.chrome.browser.ntp.cards.ContentSuggestionsUnitTestUtils.makeUiConfig;
 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.createDummySuggestions;
 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.registerCategory;
 
@@ -37,9 +36,6 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.suggestions.SuggestionsMetricsReporter;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
-import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle;
-import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
-import org.chromium.chrome.browser.widget.displaystyle.VerticalDisplayStyle;
 import org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.CategoryInfoBuilder;
 import org.chromium.chrome.test.util.browser.suggestions.FakeSuggestionsSource;
 import org.chromium.testing.local.LocalRobolectricTestRunner;
@@ -99,7 +95,7 @@
         registerCategory(mSuggestionSource, CATEGORY1 + CATEGORY2, 0);
         List<SnippetArticle> suggestions2 = registerCategory(mSuggestionSource, CATEGORY2, 4);
 
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, makeUiConfig());
+        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge);
 
         bindViewHolders(sectionList);
 
@@ -133,7 +129,7 @@
         registerCategory(mSuggestionSource, CATEGORY1 + CATEGORY2, 0);
         List<SnippetArticle> suggestions2 = registerCategory(mSuggestionSource, CATEGORY2, 4);
 
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, makeUiConfig());
+        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge);
 
         bindViewHolders(sectionList, 0, 5); // Bind until after the third item from |suggestions1|.
 
@@ -228,7 +224,7 @@
         registerCategory(mSuggestionSource,
                 new CategoryInfoBuilder(CATEGORY2).withViewAllAction().build(), 3);
 
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, makeUiConfig());
+        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge);
         bindViewHolders(sectionList);
 
         assertThat(sectionList.getSectionForTesting(CATEGORY1)
@@ -247,7 +243,7 @@
         registerCategory(mSuggestionSource, CATEGORY1, 1);
         registerCategory(mSuggestionSource,
                 new CategoryInfoBuilder(CATEGORY2).withViewAllAction().build(), 3);
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, makeUiConfig());
+        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge);
         bindViewHolders(sectionList);
 
         ArgumentCaptor<DestructionObserver> argument =
@@ -269,34 +265,22 @@
 
     @Test
     @Feature({"Ntp"})
-    public void testArticlesHeaderShownOnRegularDisplays() {
+    public void testArticlesHeaderHiddenWhenAlone() {
         registerCategory(mSuggestionSource, KnownCategories.ARTICLES, 1);
 
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, makeUiConfig());
-        SuggestionsSection articles = sectionList.getSectionForTesting(KnownCategories.ARTICLES);
-        assertTrue(articles.getHeaderItemForTesting().isVisible());
-    }
-
-    @Test
-    @Feature({"Ntp"})
-    public void testArticlesHeaderHiddenOnNarrowDisplays() {
-        registerCategory(mSuggestionSource, KnownCategories.ARTICLES, 1);
-
-        UiConfig config = makeUiConfig(HorizontalDisplayStyle.NARROW, VerticalDisplayStyle.REGULAR);
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, config);
+        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge);
         SuggestionsSection articles = sectionList.getSectionForTesting(KnownCategories.ARTICLES);
         assertFalse(articles.getHeaderItemForTesting().isVisible());
     }
 
     @Test
     @Feature({"Ntp"})
-    public void testArticlesHeaderHiddenOnFlatDisplays() {
-        registerCategory(mSuggestionSource, KnownCategories.ARTICLES, 1);
+    public void testRandomSectionHeaderShownWhenAlone() {
+        registerCategory(mSuggestionSource, CATEGORY1, 1);
 
-        UiConfig config = makeUiConfig(HorizontalDisplayStyle.REGULAR, VerticalDisplayStyle.FLAT);
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, config);
-        SuggestionsSection articles = sectionList.getSectionForTesting(KnownCategories.ARTICLES);
-        assertFalse(articles.getHeaderItemForTesting().isVisible());
+        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge);
+        SuggestionsSection section = sectionList.getSectionForTesting(CATEGORY1);
+        assertTrue(section.getHeaderItemForTesting().isVisible());
     }
 
     @Test
@@ -305,8 +289,7 @@
         registerCategory(mSuggestionSource, KnownCategories.ARTICLES, 1);
         registerCategory(mSuggestionSource, CATEGORY1, 1);
 
-        UiConfig config = makeUiConfig(HorizontalDisplayStyle.REGULAR, VerticalDisplayStyle.FLAT);
-        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge, config);
+        SectionList sectionList = new SectionList(mUiDelegate, mOfflinePageBridge);
         SuggestionsSection articles = sectionList.getSectionForTesting(KnownCategories.ARTICLES);
         assertTrue(articles.getHeaderItemForTesting().isVisible());
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
index c2fe9dc..31302ff 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
@@ -118,6 +118,38 @@
 
     @Test
     @Feature({"Ntp"})
+    public void testGetDismissalGroupWithoutHeader() {
+        SuggestionsSection section = createSectionWithFetchAction(true);
+        section.setHeaderVisibility(false);
+
+        assertEquals(ItemViewType.STATUS, section.getItemViewType(0));
+        assertEquals(setOf(0, 1), section.getItemDismissalGroup(0));
+
+        assertEquals(ItemViewType.ACTION, section.getItemViewType(1));
+        assertEquals(setOf(0, 1), section.getItemDismissalGroup(1));
+    }
+
+    @Test
+    @Feature({"Ntp"})
+    public void testGetDismissalGroupWithoutAction() {
+        SuggestionsSection section = createSectionWithFetchAction(false);
+
+        assertEquals(ItemViewType.STATUS, section.getItemViewType(1));
+        assertEquals(Collections.singleton(1), section.getItemDismissalGroup(1));
+    }
+
+    @Test
+    @Feature({"Ntp"})
+    public void testGetDismissalGroupActionAndHeader() {
+        SuggestionsSection section = createSectionWithFetchAction(false);
+        section.setHeaderVisibility(false);
+
+        assertEquals(ItemViewType.STATUS, section.getItemViewType(0));
+        assertEquals(Collections.singleton(0), section.getItemDismissalGroup(0));
+    }
+
+    @Test
+    @Feature({"Ntp"})
     public void testAddSuggestionsNotification() {
         final int suggestionCount = 5;
         List<SnippetArticle> snippets = createDummySuggestions(suggestionCount,
diff --git a/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc b/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc
index 8a88dca..468fa4d7 100644
--- a/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc
+++ b/chrome/browser/chromeos/policy/restore_on_startup_browsertest_chromeos.cc
@@ -70,13 +70,16 @@
 }
 
 // Verify that the policies are honored on a new user's login.
-IN_PROC_BROWSER_TEST_F(RestoreOnStartupTestChromeOS, PRE_LogInAndVerify) {
+// Disabled https://crbug.com/694269
+IN_PROC_BROWSER_TEST_F(RestoreOnStartupTestChromeOS,
+                       DISABLED_PRE_LogInAndVerify) {
   SkipToLoginScreen();
   LogInAndVerifyStartUpURLs();
 }
 
 // Verify that the policies are honored on an existing user's login.
-IN_PROC_BROWSER_TEST_F(RestoreOnStartupTestChromeOS, LogInAndVerify) {
+// Disabled https://crbug.com/694269
+IN_PROC_BROWSER_TEST_F(RestoreOnStartupTestChromeOS, DISABLED_LogInAndVerify) {
   content::WindowedNotificationObserver(
       chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
       content::NotificationService::AllSources()).Wait();
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index 2c68938..b21a79357 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -50,6 +50,7 @@
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 #include "net/test/url_request/url_request_failed_job.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -78,7 +79,10 @@
       net::URLRequestStatus expected_request_status)
       : expected_request_status_(expected_request_status),
         is_complete_(false),
-        fetcher_(net::URLFetcher::Create(url, net::URLFetcher::GET, this)) {
+        fetcher_(net::URLFetcher::Create(url,
+                                         net::URLFetcher::GET,
+                                         this,
+                                         TRAFFIC_ANNOTATION_FOR_TESTS)) {
     fetcher_->SetRequestContext(context_getter.get());
     fetcher_->Start();
   }
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc
index 01e19295..ea33467a 100644
--- a/chrome/browser/profiles/profile_downloader.cc
+++ b/chrome/browser/profiles/profile_downloader.cc
@@ -35,6 +35,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "net/base/load_flags.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_request_status.h"
 #include "skia/ext/image_operations.h"
@@ -237,9 +238,33 @@
     return;
   }
 
+  // Create traffic annotation tag.
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("signed_in_profile_avatar", R"(
+        semantics {
+          sender: "Profile G+ Image Downloader"
+          description:
+            "Signed in users use their G+ profile image as their Chrome "
+            "profile image, unless they explicitly select otherwise. This "
+            "fetcher uses the sign-in token and the image URL provided by GAIA "
+            "to fetch the image."
+          trigger: "User signs into a Profile."
+          data: "Filename of the png to download and Google OAuth bearer token."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: false
+          setting: "This feature cannot be disabled by settings."
+          policy_exception_justification:
+            "Not implemented, considered not useful as no content is being "
+            "uploaded or saved; this request merely downloads the user's G+ "
+            "profile image."
+        })");
+
   VLOG(1) << "Fetching profile image from " << image_url_with_size;
-  profile_image_fetcher_ = net::URLFetcher::Create(
-      GURL(image_url_with_size), net::URLFetcher::GET, this);
+  profile_image_fetcher_ =
+      net::URLFetcher::Create(GURL(image_url_with_size), net::URLFetcher::GET,
+                              this, traffic_annotation);
   data_use_measurement::DataUseUserData::AttachToFetcher(
       profile_image_fetcher_.get(),
       data_use_measurement::DataUseUserData::PROFILE_DOWNLOADER);
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index c21d544..f30a670 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -338,7 +338,8 @@
 
 
 /**
- * Fetches new data, creates, and renders tiles.
+ * Fetches new data (RIDs) from the embeddedSearch.newTabPage API and passes
+ * them to the iframe.
  */
 function reloadTiles() {
   var pages = ntpApiHandle.mostVisited;
@@ -649,7 +650,7 @@
   var iframe = document.createElement('iframe');
   iframe.id = IDS.TILES_IFRAME;
   iframe.tabIndex = 1;
-  iframe.src = '//most-visited/single.html?' + args.join('&');
+  iframe.src = 'chrome-search://most-visited/single.html?' + args.join('&');
   $(IDS.TILES).appendChild(iframe);
 
   iframe.onload = function() {
diff --git a/chrome/browser/search/suggestions/image_decoder_impl.h b/chrome/browser/search/suggestions/image_decoder_impl.h
index 658b7c4..0757e27 100644
--- a/chrome/browser/search/suggestions/image_decoder_impl.h
+++ b/chrome/browser/search/suggestions/image_decoder_impl.h
@@ -13,7 +13,9 @@
 
 namespace suggestions {
 
-// image_fetcher::ImageDecoder Implementation.
+// image_fetcher::ImageDecoder implementation.
+// TODO(treib,markusheintz): Move this to a better place - it really has
+// nothing to do with suggestions. crbug.com/624761
 class ImageDecoderImpl : public image_fetcher::ImageDecoder {
  public:
   ImageDecoderImpl();
diff --git a/chrome/browser/ui/search/instant_test_utils.cc b/chrome/browser/ui/search/instant_test_utils.cc
index 6ab4a5f..0708ea50 100644
--- a/chrome/browser/ui/search/instant_test_utils.cc
+++ b/chrome/browser/ui/search/instant_test_utils.cc
@@ -104,32 +104,32 @@
   nav_observer.Wait();
 }
 
-bool InstantTestBase::GetBoolFromJS(content::WebContents* contents,
+bool InstantTestBase::GetBoolFromJS(const content::ToRenderFrameHost& adapter,
                                     const std::string& script,
                                     bool* result) {
-  return content::ExecuteScriptAndExtractBool(
-      contents, WrapScript(script), result);
+  return content::ExecuteScriptAndExtractBool(adapter, WrapScript(script),
+                                              result);
 }
 
-bool InstantTestBase::GetIntFromJS(content::WebContents* contents,
+bool InstantTestBase::GetIntFromJS(const content::ToRenderFrameHost& adapter,
                                    const std::string& script,
                                    int* result) {
-  return content::ExecuteScriptAndExtractInt(
-      contents, WrapScript(script), result);
+  return content::ExecuteScriptAndExtractInt(adapter, WrapScript(script),
+                                             result);
 }
 
-bool InstantTestBase::GetDoubleFromJS(content::WebContents* contents,
+bool InstantTestBase::GetDoubleFromJS(const content::ToRenderFrameHost& adapter,
                                       const std::string& script,
                                       double* result) {
-  return content::ExecuteScriptAndExtractDouble(contents, WrapScript(script),
+  return content::ExecuteScriptAndExtractDouble(adapter, WrapScript(script),
                                                 result);
 }
 
-bool InstantTestBase::GetStringFromJS(content::WebContents* contents,
+bool InstantTestBase::GetStringFromJS(const content::ToRenderFrameHost& adapter,
                                       const std::string& script,
                                       std::string* result) {
-  return content::ExecuteScriptAndExtractString(
-      contents, WrapScript(script), result);
+  return content::ExecuteScriptAndExtractString(adapter, WrapScript(script),
+                                                result);
 }
 
 std::string InstantTestBase::GetOmniboxText() {
diff --git a/chrome/browser/ui/search/instant_test_utils.h b/chrome/browser/ui/search/instant_test_utils.h
index e688e22..0d5f678 100644
--- a/chrome/browser/ui/search/instant_test_utils.h
+++ b/chrome/browser/ui/search/instant_test_utils.h
@@ -13,15 +13,12 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/search/instant_controller.h"
+#include "content/public/test/browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/gurl.h"
 
 class OmniboxView;
 
-namespace content {
-class WebContents;
-};
-
 // This utility class is meant to be used in a "mix-in" fashion, giving the
 // derived test class additional Instant-related functionality.
 class InstantTestBase {
@@ -55,16 +52,16 @@
   void PressEnterAndWaitForNavigation();
   void PressEnterAndWaitForFrameLoad();
 
-  bool GetBoolFromJS(content::WebContents* contents,
+  bool GetBoolFromJS(const content::ToRenderFrameHost& adapter,
                      const std::string& script,
                      bool* result) WARN_UNUSED_RESULT;
-  bool GetIntFromJS(content::WebContents* contents,
+  bool GetIntFromJS(const content::ToRenderFrameHost& adapter,
                     const std::string& script,
                     int* result) WARN_UNUSED_RESULT;
-  bool GetDoubleFromJS(content::WebContents* contents,
+  bool GetDoubleFromJS(const content::ToRenderFrameHost& adapter,
                        const std::string& script,
                        double* result) WARN_UNUSED_RESULT;
-  bool GetStringFromJS(content::WebContents* contents,
+  bool GetStringFromJS(const content::ToRenderFrameHost& adapter,
                        const std::string& script,
                        std::string* result) WARN_UNUSED_RESULT;
 
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc
index 97cd8e9c..c80828b 100644
--- a/chrome/browser/ui/search/local_ntp_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -19,6 +19,7 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -135,6 +136,81 @@
   EXPECT_FALSE(result);
 }
 
+namespace {
+
+// Returns the RenderFrameHost corresponding to the most visited iframe in the
+// given |tab|. |tab| must correspond to an NTP.
+content::RenderFrameHost* GetMostVisitedIframe(content::WebContents* tab) {
+  CHECK_EQ(2u, tab->GetAllFrames().size());
+  for (content::RenderFrameHost* frame : tab->GetAllFrames()) {
+    if (frame != tab->GetMainFrame()) {
+      return frame;
+    }
+  }
+  NOTREACHED();
+  return nullptr;
+}
+
+}  // namespace
+
+IN_PROC_BROWSER_TEST_F(LocalNTPTest, LoadsIframe) {
+  ASSERT_NO_FATAL_FAILURE(SetupInstant(browser()));
+  FocusOmnibox();
+
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), ntp_url(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
+          ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+  content::WebContents* active_tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(search::IsInstantNTP(active_tab));
+
+  content::DOMMessageQueue msg_queue;
+
+  bool result = false;
+  ASSERT_TRUE(GetBoolFromJS(active_tab, "!!setupAdvancedTest(true)", &result));
+  ASSERT_TRUE(result);
+
+  // Wait for the MV iframe to load.
+  std::string message;
+  // First get rid of the "true" message from the GetBoolFromJS call above.
+  ASSERT_TRUE(msg_queue.PopMessage(&message));
+  ASSERT_EQ("true", message);
+  // Now wait for the "loaded" message.
+  ASSERT_TRUE(msg_queue.WaitForMessage(&message));
+  ASSERT_EQ("\"loaded\"", message);
+
+  // Get the iframe and check that the tiles loaded correctly.
+  content::RenderFrameHost* iframe = GetMostVisitedIframe(active_tab);
+
+  // Get the total number of (non-empty) tiles from the iframe.
+  int total_thumbs = 0;
+  ASSERT_TRUE(GetIntFromJS(
+      iframe, "document.querySelectorAll('.mv-thumb').length", &total_thumbs));
+  // Also get how many of the tiles succeeded and failed in loading their
+  // thumbnail images.
+  int succeeded_imgs = 0;
+  ASSERT_TRUE(GetIntFromJS(iframe,
+                           "document.querySelectorAll('.mv-thumb img').length",
+                           &succeeded_imgs));
+  int failed_imgs = 0;
+  ASSERT_TRUE(GetIntFromJS(
+      iframe, "document.querySelectorAll('.mv-thumb.failed-img').length",
+      &failed_imgs));
+
+  // First, sanity check that the numbers line up (none of the css classes was
+  // renamed, etc).
+  EXPECT_EQ(total_thumbs, succeeded_imgs + failed_imgs);
+
+  // Since we're in a non-signed-in, fresh profile with no history, there should
+  // be the default TopSites tiles (see history::PrepopulatedPage).
+  // Check that there is at least one tile, and that all of them loaded their
+  // images successfully.
+  EXPECT_GT(total_thumbs, 0);
+  EXPECT_EQ(total_thumbs, succeeded_imgs);
+  EXPECT_EQ(0, failed_imgs);
+}
+
 IN_PROC_BROWSER_TEST_F(LocalNTPTest,
                        NTPRespectsBrowserLanguageSetting) {
   // Make sure the default language is not French.
diff --git a/chrome/test/data/extensions/api_test/webrequest/csp/violation.html b/chrome/test/data/extensions/api_test/webrequest/csp/violation.html
new file mode 100644
index 0000000..de4cfe37
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest/csp/violation.html
@@ -0,0 +1,4 @@
+This page is served with a report-uri in its CSP header, and content that violates the policy.
+<script>
+console.log('This should be blocked by the Content-Security-Policy, and reported to the value in report-uri.');
+</script>
diff --git a/chrome/test/data/extensions/api_test/webrequest/csp/violation.html.mock-http-headers b/chrome/test/data/extensions/api_test/webrequest/csp/violation.html.mock-http-headers
new file mode 100644
index 0000000..dedf3b3
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/webrequest/csp/violation.html.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+Content-Security-Policy: script-src 'none'; report-uri /csp-violation-dont-ignore-me
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_types.js b/chrome/test/data/extensions/api_test/webrequest/test_types.js
index 561cd0c..5bf86cb 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_types.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_types.js
@@ -35,6 +35,12 @@
   return getServerURL('empty.html?as-beacon');
 }
 
+function getCSPReportURL() {
+  // dont-ignore-me is included so that framework.js does not filter out the
+  // request of type "other".
+  return getServerURL('csp-violation-dont-ignore-me');
+}
+
 // A slow URL used for the beacon test, to make sure that the test fails
 // deterministically if there is a bug that causes the frameId/tabId to not be
 // set if the frame is removed during the request.
@@ -610,4 +616,94 @@
     };
     frame.remove();
   },
+
+  function typeOther_cspreport() {
+    expect([
+      { label: 'onBeforeRequest',
+        event: 'onBeforeRequest',
+        details: {
+          type: 'csp_report',
+          method: 'POST',
+          url: getCSPReportURL(),
+          frameUrl: 'unknown frame URL',
+          frameId: 1,
+          parentFrameId: 0,
+          tabId: 1,
+        }
+      },
+      { label: 'onBeforeSendHeaders',
+        event: 'onBeforeSendHeaders',
+        details: {
+          type: 'csp_report',
+          method: 'POST',
+          url: getCSPReportURL(),
+          frameId: 1,
+          parentFrameId: 0,
+          tabId: 1,
+        },
+      },
+      { label: 'onSendHeaders',
+        event: 'onSendHeaders',
+        details: {
+          type: 'csp_report',
+          method: 'POST',
+          url: getCSPReportURL(),
+          frameId: 1,
+          parentFrameId: 0,
+          tabId: 1,
+        },
+      },
+      { label: 'onHeadersReceived',
+        event: 'onHeadersReceived',
+        details: {
+          type: 'csp_report',
+          method: 'POST',
+          url: getCSPReportURL(),
+          frameId: 1,
+          parentFrameId: 0,
+          tabId: 1,
+          statusLine: 'HTTP/1.1 404 Not Found',
+          statusCode: 404,
+        },
+      },
+      { label: 'onResponseStarted',
+        event: 'onResponseStarted',
+        details: {
+          type: 'csp_report',
+          method: 'POST',
+          url: getCSPReportURL(),
+          frameId: 1,
+          parentFrameId: 0,
+          tabId: 1,
+          ip: '127.0.0.1',
+          fromCache: false,
+          statusLine: 'HTTP/1.1 404 Not Found',
+          statusCode: 404,
+        },
+      },
+      { label: 'onCompleted',
+        event: 'onCompleted',
+        details: {
+          type: 'csp_report',
+          method: 'POST',
+          url: getCSPReportURL(),
+          frameId: 1,
+          parentFrameId: 0,
+          tabId: 1,
+          ip: '127.0.0.1',
+          fromCache: false,
+          statusLine: 'HTTP/1.1 404 Not Found',
+          statusCode: 404,
+        },
+      }],
+      [['onBeforeRequest', 'onBeforeSendHeaders', 'onSendHeaders',
+        'onHeadersReceived', 'onResponseStarted', 'onCompleted']], {
+        urls: ['<all_urls>'], types: ['csp_report']
+      });
+
+    var frame = document.createElement('iframe');
+    frame.src =
+      getServerURL('extensions/api_test/webrequest/csp/violation.html');
+    document.body.appendChild(frame);
+  },
 ]);
diff --git a/chrome/test/data/local_ntp_browsertest.js b/chrome/test/data/local_ntp_browsertest.js
index bb33e34..f16fc95f 100644
--- a/chrome/test/data/local_ntp_browsertest.js
+++ b/chrome/test/data/local_ntp_browsertest.js
@@ -139,7 +139,18 @@
 // Advanced tests are controlled from the native side. The helpers here are
 // called from native code to set up the page and to check results.
 
-function setupAdvancedTest() {
+function handlePostMessage(event) {
+  if (event.data.cmd == 'loaded') {
+    domAutomationController.setAutomationId(0);
+    domAutomationController.send('loaded');
+  }
+}
+
+function setupAdvancedTest(opt_waitForIframeLoaded) {
+  if (opt_waitForIframeLoaded) {
+    window.addEventListener('message', handlePostMessage);
+  }
+
   setUp();
   initLocalNTP(/*isGooglePage=*/true);
 
diff --git a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js
index 5431d452..360debc 100644
--- a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js
+++ b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js
@@ -170,7 +170,10 @@
   },
 };
 
-TEST_F('SettingsAutofillSectionBrowserTest', 'CreditCardTests', function() {
+// Disabled because of flakiness http://crbug.com/694289
+TEST_F('SettingsAutofillSectionBrowserTest',
+       'DISABLED_CreditCardTests',
+       function() {
   var self = this;
 
   setup(function() {
diff --git a/components/browser_watcher/BUILD.gn b/components/browser_watcher/BUILD.gn
index 6963cef3..2e831c9 100644
--- a/components/browser_watcher/BUILD.gn
+++ b/components/browser_watcher/BUILD.gn
@@ -69,6 +69,7 @@
       ":stability_data",
       ":stability_report_proto",
       "//base",
+      "//components/variations",
       "//third_party/crashpad/crashpad/client",
       "//third_party/crashpad/crashpad/util",
     ]
diff --git a/components/browser_watcher/DEPS b/components/browser_watcher/DEPS
index 1d59b5c..7650b54 100644
--- a/components/browser_watcher/DEPS
+++ b/components/browser_watcher/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "+components/metrics",
+  "+components/variations",
   "+third_party/crashpad/crashpad",
 ]
diff --git a/components/browser_watcher/postmortem_report_collector.cc b/components/browser_watcher/postmortem_report_collector.cc
index 8f1ccd4..7f5bf145 100644
--- a/components/browser_watcher/postmortem_report_collector.cc
+++ b/components/browser_watcher/postmortem_report_collector.cc
@@ -13,9 +13,11 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/path_service.h"
 #include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/browser_watcher/postmortem_minidump_writer.h"
 #include "components/browser_watcher/stability_data_names.h"
+#include "components/variations/active_field_trials.h"
 #include "third_party/crashpad/crashpad/client/settings.h"
 #include "third_party/crashpad/crashpad/util/misc/uuid.h"
 
@@ -32,14 +34,18 @@
 
 namespace {
 
+const char kFieldTrialKeyPrefix[] = "FieldTrial.";
+
 // Collects stability user data from the recorded format to the collected
 // format.
 void CollectUserData(
     const ActivityUserData::Snapshot& recorded_map,
-    google::protobuf::Map<std::string, TypedValue>* collected_map) {
+    google::protobuf::Map<std::string, TypedValue>* collected_map,
+    StabilityReport* report) {
   DCHECK(collected_map);
 
   for (const auto& name_and_value : recorded_map) {
+    const std::string& key = name_and_value.first;
     const ActivityUserData::TypedValue& recorded_value = name_and_value.second;
     TypedValue collected_value;
 
@@ -47,9 +53,11 @@
       case ActivityUserData::END_OF_VALUES:
         NOTREACHED();
         break;
-      case ActivityUserData::RAW_VALUE:
-        collected_value.set_bytes_value(recorded_value.Get().as_string());
+      case ActivityUserData::RAW_VALUE: {
+        base::StringPiece raw = recorded_value.Get();
+        collected_value.set_bytes_value(raw.data(), raw.size());
         break;
+      }
       case ActivityUserData::RAW_VALUE_REFERENCE: {
         base::StringPiece recorded_ref = recorded_value.GetReference();
         TypedValue::Reference* collected_ref =
@@ -59,10 +67,25 @@
         collected_ref->set_size(recorded_ref.size());
         break;
       }
-      case ActivityUserData::STRING_VALUE:
-        collected_value.set_string_value(
-            recorded_value.GetString().as_string());
+      case ActivityUserData::STRING_VALUE: {
+        base::StringPiece value = recorded_value.GetString();
+
+        if (report && base::StartsWith(key, kFieldTrialKeyPrefix,
+                                       base::CompareCase::SENSITIVE)) {
+          // This entry represents an active Field Trial.
+          std::string trial_name =
+              key.substr(std::strlen(kFieldTrialKeyPrefix));
+          variations::ActiveGroupId group_id =
+              variations::MakeActiveGroupId(trial_name, value.as_string());
+          FieldTrial* field_trial = report->add_field_trials();
+          field_trial->set_name_id(group_id.name);
+          field_trial->set_group_id(group_id.group);
+          continue;
+        }
+
+        collected_value.set_string_value(value.data(), value.size());
         break;
+      }
       case ActivityUserData::STRING_VALUE_REFERENCE: {
         base::StringPiece recorded_ref = recorded_value.GetStringReference();
         TypedValue::Reference* collected_ref =
@@ -72,10 +95,11 @@
         collected_ref->set_size(recorded_ref.size());
         break;
       }
-      case ActivityUserData::CHAR_VALUE:
-        collected_value.set_char_value(
-            std::string(1, recorded_value.GetChar()));
+      case ActivityUserData::CHAR_VALUE: {
+        char char_value = recorded_value.GetChar();
+        collected_value.set_char_value(&char_value, 1);
         break;
+      }
       case ActivityUserData::BOOL_VALUE:
         collected_value.set_bool_value(recorded_value.GetBool());
         break;
@@ -87,7 +111,7 @@
         break;
     }
 
-    (*collected_map)[name_and_value.first].Swap(&collected_value);
+    (*collected_map)[key].Swap(&collected_value);
   }
 }
 
@@ -288,7 +312,7 @@
   // Collect global user data.
   google::protobuf::Map<std::string, TypedValue>& global_data =
       *(*report)->mutable_global_data();
-  CollectUserData(global_data_snapshot, &global_data);
+  CollectUserData(global_data_snapshot, &global_data, report->get());
 
   // Add the reporting Chrome's details to the report.
   global_data[kStabilityReporterChannel].set_string_value(channel_name());
@@ -371,7 +395,7 @@
     // Collect user data
     if (i < snapshot.user_data_stack.size()) {
       CollectUserData(snapshot.user_data_stack[i],
-                      collected->mutable_user_data());
+                      collected->mutable_user_data(), nullptr);
     }
   }
 }
diff --git a/components/browser_watcher/postmortem_report_collector.h b/components/browser_watcher/postmortem_report_collector.h
index 4dd768d35..0650d37ec 100644
--- a/components/browser_watcher/postmortem_report_collector.h
+++ b/components/browser_watcher/postmortem_report_collector.h
@@ -80,6 +80,9 @@
       GlobalUserDataCollection);
   FRIEND_TEST_ALL_PREFIXES(
       PostmortemReportCollectorCollectionFromGlobalTrackerTest,
+      FieldTrialCollection);
+  FRIEND_TEST_ALL_PREFIXES(
+      PostmortemReportCollectorCollectionFromGlobalTrackerTest,
       ModuleCollection);
 
   // Virtual for unittesting.
diff --git a/components/browser_watcher/postmortem_report_collector_unittest.cc b/components/browser_watcher/postmortem_report_collector_unittest.cc
index 8d8d5cc..ae241e3 100644
--- a/components/browser_watcher/postmortem_report_collector_unittest.cc
+++ b/components/browser_watcher/postmortem_report_collector_unittest.cc
@@ -650,6 +650,38 @@
 }
 
 TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest,
+       FieldTrialCollection) {
+  // Record some data.
+  GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
+                                        "", 3);
+  ActivityUserData& global_data = GlobalActivityTracker::Get()->global_data();
+  global_data.SetString("string", "bar");
+  global_data.SetString("FieldTrial.string", "bar");
+  global_data.SetString("FieldTrial.foo", "bar");
+
+  // Collect the stability report.
+  PostmortemReportCollector collector(kProductName, kVersionNumber,
+                                      kChannelName);
+  std::unique_ptr<StabilityReport> report;
+  ASSERT_EQ(PostmortemReportCollector::SUCCESS,
+            collector.Collect(debug_file_path(), &report));
+  ASSERT_NE(nullptr, report);
+
+  // Validate the report's experiment and global data.
+  ASSERT_EQ(2, report->field_trials_size());
+  EXPECT_NE(0U, report->field_trials(0).name_id());
+  EXPECT_NE(0U, report->field_trials(0).group_id());
+  EXPECT_NE(0U, report->field_trials(1).name_id());
+  EXPECT_EQ(report->field_trials(0).group_id(),
+            report->field_trials(1).group_id());
+
+  // Expect 5 key/value pairs (including product details).
+  const auto& collected_data = report->global_data();
+  EXPECT_EQ(5U, collected_data.size());
+  EXPECT_TRUE(base::ContainsKey(collected_data, "string"));
+}
+
+TEST_F(PostmortemReportCollectorCollectionFromGlobalTrackerTest,
        ModuleCollection) {
   // Record some module information.
   GlobalActivityTracker::CreateWithFile(debug_file_path(), kMemorySize, 0ULL,
diff --git a/components/browser_watcher/stability_report.proto b/components/browser_watcher/stability_report.proto
index 7f20f7d5..b5039a2 100644
--- a/components/browser_watcher/stability_report.proto
+++ b/components/browser_watcher/stability_report.proto
@@ -150,10 +150,24 @@
   // TODO(manzagop): add experiment state.
 }
 
+// Description of a field trial or experiment that the user is currently
+// enrolled in. This message is an analogue of the UMA proto in
+// components/metrics/proto/system_profile.proto. For details about generating
+// the identifiers from the field trial and group names, see
+// variations::MakeActiveGroupId().
+// Next id: 3
+message FieldTrial {
+  // A 32-bit identifier for the name of the field trial.
+  optional fixed32 name_id = 1;
+
+  // A 32-bit identifier for the user's group within the field trial.
+  optional fixed32 group_id = 2;
+}
+
 // A stability report contains information pertaining to the execution of a
 // single logical instance of a "chrome browser". It is comprised of information
 // about the system state and about the chrome browser's processes.
-// Next id: 5
+// Next id: 6
 message StabilityReport {
   optional SystemState system_state = 1;
   // TODO(manzagop): revisit whether a single repeated field should contain all
@@ -166,4 +180,7 @@
   //     relocate these to their process (and perhaps thread).
   repeated string log_messages = 3;
   map<string, TypedValue> global_data = 4;
+
+  // The field trials the user is currently enrolled in.
+  repeated FieldTrial field_trials = 5;
 }
diff --git a/components/image_fetcher/image_fetcher.h b/components/image_fetcher/image_fetcher.h
index 6983638..9529bc1 100644
--- a/components/image_fetcher/image_fetcher.h
+++ b/components/image_fetcher/image_fetcher.h
@@ -41,6 +41,9 @@
       const GURL& image_url,
       base::Callback<void(const std::string&, const gfx::Image&)> callback) = 0;
 
+  // TODO(treib,markusheintz): Now that iOS uses the same ImageFetcherImpl (see
+  // crbug.com/689020), add a getter for the ImageDecoder here.
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ImageFetcher);
 };
diff --git a/components/image_fetcher/image_fetcher_impl.h b/components/image_fetcher/image_fetcher_impl.h
index d8294ef..8c92d917 100644
--- a/components/image_fetcher/image_fetcher_impl.h
+++ b/components/image_fetcher/image_fetcher_impl.h
@@ -28,8 +28,7 @@
 
 namespace image_fetcher {
 
-// TODO(markusheintz): Once the iOS implementation of the ImageFetcher is
-// removed merge the two classes ImageFetcher and ImageFetcherImpl.
+// The standard (non-test) implementation of ImageFetcher.
 class ImageFetcherImpl : public image_fetcher::ImageFetcher {
  public:
   ImageFetcherImpl(
diff --git a/components/subresource_filter/content/browser/BUILD.gn b/components/subresource_filter/content/browser/BUILD.gn
index 6388aab..24a4c3cf 100644
--- a/components/subresource_filter/content/browser/BUILD.gn
+++ b/components/subresource_filter/content/browser/BUILD.gn
@@ -4,6 +4,8 @@
 
 static_library("browser") {
   sources = [
+    "async_document_subresource_filter.cc",
+    "async_document_subresource_filter.h",
     "content_ruleset_service_delegate.cc",
     "content_ruleset_service_delegate.h",
     "content_subresource_filter_driver_factory.cc",
@@ -31,6 +33,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "async_document_subresource_filter_unittest.cc",
     "content_ruleset_service_delegate_unittest.cc",
     "content_subresource_filter_driver_factory_unittest.cc",
     "verified_ruleset_dealer_unittest.cc",
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.cc b/components/subresource_filter/content/browser/async_document_subresource_filter.cc
new file mode 100644
index 0000000..099eec1
--- /dev/null
+++ b/components/subresource_filter/content/browser/async_document_subresource_filter.cc
@@ -0,0 +1,138 @@
+// 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 "components/subresource_filter/content/browser/async_document_subresource_filter.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/subresource_filter/core/common/memory_mapped_ruleset.h"
+
+namespace subresource_filter {
+
+// AsyncDocumentSubresourceFilter::InitializationParams ------------------------
+
+using InitializationParams =
+    AsyncDocumentSubresourceFilter::InitializationParams;
+
+InitializationParams::InitializationParams() = default;
+
+InitializationParams::InitializationParams(GURL document_url,
+                                           ActivationLevel activation_level,
+                                           bool measure_performance)
+    : document_url(std::move(document_url)),
+      parent_activation_state(activation_level) {
+  DCHECK_NE(ActivationLevel::DISABLED, activation_level);
+  parent_activation_state.measure_performance = measure_performance;
+}
+
+InitializationParams::InitializationParams(
+    GURL document_url,
+    url::Origin parent_document_origin,
+    ActivationState parent_activation_state)
+    : document_url(std::move(document_url)),
+      parent_document_origin(std::move(parent_document_origin)),
+      parent_activation_state(parent_activation_state) {
+  DCHECK_NE(ActivationLevel::DISABLED,
+            parent_activation_state.activation_level);
+}
+
+InitializationParams::~InitializationParams() = default;
+InitializationParams::InitializationParams(InitializationParams&&) = default;
+InitializationParams& InitializationParams::operator=(InitializationParams&&) =
+    default;
+
+// AsyncDocumentSubresourceFilter ----------------------------------------------
+
+AsyncDocumentSubresourceFilter::AsyncDocumentSubresourceFilter(
+    VerifiedRuleset::Handle* ruleset_handle,
+    InitializationParams params,
+    base::Callback<void(ActivationState)> activation_state_callback,
+    base::OnceClosure first_disallowed_load_callback)
+    : task_runner_(ruleset_handle->task_runner()),
+      core_(new Core(), base::OnTaskRunnerDeleter(task_runner_)),
+      first_disallowed_load_callback_(
+          std::move(first_disallowed_load_callback)) {
+  DCHECK_NE(ActivationLevel::DISABLED,
+            params.parent_activation_state.activation_level);
+
+  // Note: It is safe to post |ruleset_handle|'s VerifiedRuleset pointer,
+  // because a task to delete it can only be posted to (and, therefore,
+  // processed by) |task_runner| after this method returns, hence after the
+  // below task is posted.
+  base::PostTaskAndReplyWithResult(
+      task_runner_, FROM_HERE,
+      base::Bind(&Core::Initialize, base::Unretained(core_.get()),
+                 base::Passed(&params), ruleset_handle->ruleset_.get()),
+      std::move(activation_state_callback));
+}
+
+AsyncDocumentSubresourceFilter::~AsyncDocumentSubresourceFilter() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void AsyncDocumentSubresourceFilter::GetLoadPolicyForSubdocument(
+    const GURL& subdocument_url,
+    LoadPolicyCallback result_callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  // TODO(pkalinnikov): Think about avoiding copy of |subdocument_url| if it is
+  // too big and won't be allowed anyway (e.g., it's a data: URI).
+  base::PostTaskAndReplyWithResult(
+      task_runner_, FROM_HERE,
+      base::Bind(
+          [](AsyncDocumentSubresourceFilter::Core* core,
+             const GURL& subdocument_url) {
+            DCHECK(core);
+            DocumentSubresourceFilter* filter = core->filter();
+            return filter
+                       ? filter->GetLoadPolicy(subdocument_url,
+                                               proto::ELEMENT_TYPE_SUBDOCUMENT)
+                       : LoadPolicy::ALLOW;
+          },
+          core_.get(), subdocument_url),
+      std::move(result_callback));
+}
+
+void AsyncDocumentSubresourceFilter::ReportDisallowedLoad() {
+  if (!first_disallowed_load_callback_.is_null())
+    std::move(first_disallowed_load_callback_).Run();
+}
+
+// AsyncDocumentSubresourceFilter::Core ----------------------------------------
+
+AsyncDocumentSubresourceFilter::Core::Core() {
+  thread_checker_.DetachFromThread();
+}
+
+AsyncDocumentSubresourceFilter::Core::~Core() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+ActivationState AsyncDocumentSubresourceFilter::Core::Initialize(
+    InitializationParams params,
+    VerifiedRuleset* verified_ruleset) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(verified_ruleset);
+
+  if (!verified_ruleset->Get())
+    return ActivationState(ActivationLevel::DISABLED);
+
+  ActivationState activation_state = ComputeActivationState(
+      params.document_url, params.parent_document_origin,
+      params.parent_activation_state, verified_ruleset->Get());
+
+  DCHECK_NE(ActivationLevel::DISABLED, activation_state.activation_level);
+  filter_.emplace(url::Origin(params.document_url), activation_state,
+                  verified_ruleset->Get());
+
+  return activation_state;
+}
+
+}  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter.h b/components/subresource_filter/content/browser/async_document_subresource_filter.h
new file mode 100644
index 0000000..3d4c9dd
--- /dev/null
+++ b/components/subresource_filter/content/browser/async_document_subresource_filter.h
@@ -0,0 +1,148 @@
+// 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 COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ASYNC_DOCUMENT_SUBRESOURCE_FILTER_H_
+#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ASYNC_DOCUMENT_SUBRESOURCE_FILTER_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/thread_checker.h"
+#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h"
+#include "components/subresource_filter/core/common/activation_level.h"
+#include "components/subresource_filter/core/common/activation_state.h"
+#include "components/subresource_filter/core/common/document_subresource_filter.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace subresource_filter {
+
+// An asynchronous wrapper around DocumentSubresourceFilter (DSF).
+//
+// It is accessed on the UI thread and owns a DSF living on a dedicated
+// sequenced |task_runner|. Provides asynchronous access to the DSF and destroys
+// it asynchronously.
+//
+// Initially holds an empty filter in the synchronously created Core object, and
+// initializes the filter on the |task_runner| asynchronously. This lets ADSF be
+// created synchrously and be immediately used by clients on the UI thread,
+// while the DSF is retrieved on the |task_runner| in a deferred manner.
+class AsyncDocumentSubresourceFilter {
+ public:
+  using LoadPolicyCallback = base::Callback<void(LoadPolicy)>;
+
+  class Core;
+
+  // Encapsulates the parameters needed for computing the frame-level
+  // ActivationState appropriate for the frame this ADSF is created for. These
+  // parameters are posted to ADSF::Core during its initialization.
+  struct InitializationParams {
+    InitializationParams();
+
+    // Takes parameters needed for calculating the main-frame ActivationState,
+    // that is: the main-frame |document| URL, the page-level
+    // |activation_level|, and whether or not to |measure_performance|.
+    InitializationParams(GURL document_url,
+                         ActivationLevel activation_level,
+                         bool measure_performance);
+
+    // Takes parameters needed for calculating the sub-frame ActivationState,
+    // that is: the sub-frame |document| URL, the origin of its |parent|, as
+    // well as the parent's |activation_state|.
+    InitializationParams(GURL document_url,
+                         url::Origin parent_document_origin,
+                         ActivationState parent_activation_state);
+
+    ~InitializationParams();
+
+    InitializationParams(InitializationParams&& other);
+    InitializationParams& operator=(InitializationParams&& other);
+
+    // Parameters used to compute ActivationState for the |document| before
+    // creating a DocumentSubresourceFilter.
+    GURL document_url;
+    url::Origin parent_document_origin;
+    ActivationState parent_activation_state;
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(InitializationParams);
+  };
+
+  // Creates a Core and initializes it asynchronously on a |task_runner| using
+  // the supplied initialization |params| and a VerifiedRuleset taken from the
+  // |ruleset_handle|. The core remains owned by |this| object, but lives on
+  // (and is accessed on) the |task_runner|.
+  //
+  // Once the ActivationState for the current frame is calculated, it is
+  // reported back via |activation_state_callback| on the task runner associated
+  // with the current thread. If MemoryMappedRuleset is not present or
+  // malformed, then a default ActivationState is reported (with ActivationLevel
+  // equal to DISABLED).
+  //
+  // The |first_disallowed_load_callback|, if it is non-null, is invoked on the
+  // first ReportDisallowedLoad() call.
+  AsyncDocumentSubresourceFilter(
+      VerifiedRuleset::Handle* ruleset_handle,
+      InitializationParams params,
+      base::Callback<void(ActivationState)> activation_state_callback,
+      base::OnceClosure first_disallowed_load_callback);
+
+  ~AsyncDocumentSubresourceFilter();
+
+  // Computes LoadPolicy on a |task_runner| and returns it back to the calling
+  // thread via |result_callback|. If MemoryMappedRuleset is not present or
+  // malformed, then a LoadPolicy::Allow is returned.
+  void GetLoadPolicyForSubdocument(const GURL& subdocument_url,
+                                   LoadPolicyCallback result_callback);
+
+  // Invokes |first_disallowed_load_callback|, if necessary, and posts a task to
+  // call DocumentSubresourceFilter::reportDisallowedCallback() on the
+  // |task_runner|.
+  void ReportDisallowedLoad();
+
+ private:
+  // Note: Raw pointer, |core_| already holds a reference to |task_runner_|.
+  base::SequencedTaskRunner* task_runner_;
+  std::unique_ptr<Core, base::OnTaskRunnerDeleter> core_;
+  base::OnceClosure first_disallowed_load_callback_;
+
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(AsyncDocumentSubresourceFilter);
+};
+
+// Holds a DocumentSubresourceFilter that is created in a deferred manner in
+// Initialize(), provided there is a valid ruleset to work with.
+class AsyncDocumentSubresourceFilter::Core {
+ public:
+  Core();
+  ~Core();
+
+  // Can return nullptr even after initialization in case MemoryMappedRuleset
+  // was not present, or was malformed during it.
+  DocumentSubresourceFilter* filter() {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    return filter_ ? &filter_.value() : nullptr;
+  }
+
+ private:
+  friend class AsyncDocumentSubresourceFilter;
+
+  // Computes ActivationState from |params| and initializes a DSF using it.
+  // Returns the computed activation state.
+  ActivationState Initialize(InitializationParams params,
+                             VerifiedRuleset* verified_ruleset);
+
+  base::Optional<DocumentSubresourceFilter> filter_;
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
+}  // namespace subresource_filter
+
+#endif  // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_ASYNC_DOCUMENT_SUBRESOURCE_FILTER_H_
diff --git a/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
new file mode 100644
index 0000000..a3cef15
--- /dev/null
+++ b/components/subresource_filter/content/browser/async_document_subresource_filter_unittest.cc
@@ -0,0 +1,267 @@
+// 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 "components/subresource_filter/content/browser/async_document_subresource_filter.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/subresource_filter/core/common/proto/rules.pb.h"
+#include "components/subresource_filter/core/common/test_ruleset_creator.h"
+#include "components/subresource_filter/core/common/test_ruleset_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace subresource_filter {
+
+class AsyncDocumentSubresourceFilterTest : public ::testing::Test {
+ public:
+  AsyncDocumentSubresourceFilterTest()
+      : reply_task_runner_(new base::TestSimpleTaskRunner),
+        reply_task_runner_handle_(reply_task_runner_),
+        blocking_task_runner_(new base::TestSimpleTaskRunner) {}
+
+ protected:
+  void SetUp() override {
+    std::vector<proto::UrlRule> rules;
+    rules.push_back(testing::CreateWhitelistRuleForDocument(
+        "whitelisted.subframe.com", proto::ACTIVATION_TYPE_GENERICBLOCK,
+        {"example.com"}));
+    rules.push_back(testing::CreateSuffixRule("disallowed.html"));
+
+    ASSERT_NO_FATAL_FAILURE(test_ruleset_creator_.CreateRulesetWithRules(
+        rules, &test_ruleset_pair_));
+
+    dealer_handle_.reset(
+        new VerifiedRulesetDealer::Handle(blocking_task_runner_));
+  }
+
+  void TearDown() override {
+    dealer_handle_.reset(nullptr);
+    RunUntilIdle();
+  }
+
+  const testing::TestRuleset& ruleset() const {
+    return test_ruleset_pair_.indexed;
+  }
+
+  void RunUntilIdle() {
+    while (blocking_task_runner_->HasPendingTask() ||
+           reply_task_runner_->HasPendingTask()) {
+      blocking_task_runner_->RunUntilIdle();
+      reply_task_runner_->RunUntilIdle();
+    }
+  }
+
+  VerifiedRulesetDealer::Handle* dealer_handle() {
+    return dealer_handle_.get();
+  }
+
+  std::unique_ptr<VerifiedRuleset::Handle> CreateRulesetHandle() {
+    return base::MakeUnique<VerifiedRuleset::Handle>(dealer_handle());
+  }
+
+ private:
+  testing::TestRulesetCreator test_ruleset_creator_;
+  testing::TestRulesetPair test_ruleset_pair_;
+
+  // Note: ADSF assumes a task runner is associated with the current thread.
+  scoped_refptr<base::TestSimpleTaskRunner> reply_task_runner_;
+  base::SequencedTaskRunnerHandle reply_task_runner_handle_;
+  scoped_refptr<base::TestSimpleTaskRunner> blocking_task_runner_;
+
+  std::unique_ptr<VerifiedRulesetDealer::Handle> dealer_handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(AsyncDocumentSubresourceFilterTest);
+};
+
+namespace {
+
+class TestActivationStateCallbackReceiver {
+ public:
+  TestActivationStateCallbackReceiver() = default;
+
+  base::Callback<void(ActivationState)> callback() {
+    return base::Bind(&TestActivationStateCallbackReceiver::Callback,
+                      base::Unretained(this));
+  }
+  void ExpectReceivedOnce(ActivationState expected_state) const {
+    ASSERT_EQ(1, callback_count_);
+    EXPECT_EQ(expected_state, last_activation_state_);
+  }
+
+ private:
+  void Callback(ActivationState activation_state) {
+    ++callback_count_;
+    last_activation_state_ = activation_state;
+  }
+
+  ActivationState last_activation_state_;
+  int callback_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TestActivationStateCallbackReceiver);
+};
+
+class TestCallbackReceiver {
+ public:
+  TestCallbackReceiver() = default;
+
+  base::Closure closure() {
+    return base::Bind(&TestCallbackReceiver::Callback, base::Unretained(this));
+  }
+  int callback_count() const { return callback_count_; }
+
+ private:
+  void Callback() { ++callback_count_; }
+
+  int callback_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(TestCallbackReceiver);
+};
+
+class LoadPolicyCallbackReceiver {
+ public:
+  LoadPolicyCallbackReceiver() = default;
+
+  AsyncDocumentSubresourceFilter::LoadPolicyCallback callback() {
+    return base::Bind(&LoadPolicyCallbackReceiver::Callback,
+                      base::Unretained(this));
+  }
+  void ExpectReceivedOnce(LoadPolicy load_policy) const {
+    ASSERT_EQ(1, callback_count_);
+    EXPECT_EQ(load_policy, last_load_policy_);
+  }
+
+ private:
+  void Callback(LoadPolicy load_policy) {
+    ++callback_count_;
+    last_load_policy_ = load_policy;
+  }
+
+  int callback_count_ = 0;
+  LoadPolicy last_load_policy_;
+
+  DISALLOW_COPY_AND_ASSIGN(LoadPolicyCallbackReceiver);
+};
+
+}  // namespace
+
+TEST_F(AsyncDocumentSubresourceFilterTest, ActivationStateIsReported) {
+  dealer_handle()->SetRulesetFile(testing::TestRuleset::Open(ruleset()));
+  auto ruleset_handle = CreateRulesetHandle();
+
+  AsyncDocumentSubresourceFilter::InitializationParams params(
+      GURL("http://example.com"), ActivationLevel::ENABLED, false);
+
+  TestActivationStateCallbackReceiver activation_state;
+  auto filter = base::MakeUnique<AsyncDocumentSubresourceFilter>(
+      ruleset_handle.get(), std::move(params), activation_state.callback(),
+      base::OnceClosure());
+
+  RunUntilIdle();
+  activation_state.ExpectReceivedOnce(
+      ActivationState(ActivationLevel::ENABLED));
+}
+
+TEST_F(AsyncDocumentSubresourceFilterTest, ActivationStateIsComputedCorrectly) {
+  dealer_handle()->SetRulesetFile(testing::TestRuleset::Open(ruleset()));
+  auto ruleset_handle = CreateRulesetHandle();
+
+  AsyncDocumentSubresourceFilter::InitializationParams params(
+      GURL("http://whitelisted.subframe.com"), ActivationLevel::ENABLED, false);
+  params.parent_document_origin = url::Origin(GURL("http://example.com"));
+
+  TestActivationStateCallbackReceiver activation_state;
+  auto filter = base::MakeUnique<AsyncDocumentSubresourceFilter>(
+      ruleset_handle.get(), std::move(params), activation_state.callback(),
+      base::OnceClosure());
+
+  RunUntilIdle();
+
+  ActivationState expected_activation_state(ActivationLevel::ENABLED);
+  expected_activation_state.generic_blocking_rules_disabled = true;
+  activation_state.ExpectReceivedOnce(expected_activation_state);
+}
+
+TEST_F(AsyncDocumentSubresourceFilterTest, DisabledForCorruptRuleset) {
+  testing::TestRuleset::CorruptByFilling(ruleset(), 0, 100, 0xFF);
+  dealer_handle()->SetRulesetFile(testing::TestRuleset::Open(ruleset()));
+
+  auto ruleset_handle = CreateRulesetHandle();
+
+  AsyncDocumentSubresourceFilter::InitializationParams params(
+      GURL("http://example.com"), ActivationLevel::ENABLED, false);
+
+  TestActivationStateCallbackReceiver activation_state;
+  auto filter = base::MakeUnique<AsyncDocumentSubresourceFilter>(
+      ruleset_handle.get(), std::move(params), activation_state.callback(),
+      base::OnceClosure());
+
+  RunUntilIdle();
+  activation_state.ExpectReceivedOnce(
+      ActivationState(ActivationLevel::DISABLED));
+}
+
+TEST_F(AsyncDocumentSubresourceFilterTest, GetLoadPolicyForSubdocument) {
+  dealer_handle()->SetRulesetFile(testing::TestRuleset::Open(ruleset()));
+  auto ruleset_handle = CreateRulesetHandle();
+
+  AsyncDocumentSubresourceFilter::InitializationParams params(
+      GURL("http://example.com"), ActivationLevel::ENABLED, false);
+
+  TestActivationStateCallbackReceiver activation_state;
+  auto filter = base::MakeUnique<AsyncDocumentSubresourceFilter>(
+      ruleset_handle.get(), std::move(params), activation_state.callback(),
+      base::OnceClosure());
+
+  LoadPolicyCallbackReceiver load_policy_1;
+  LoadPolicyCallbackReceiver load_policy_2;
+  filter->GetLoadPolicyForSubdocument(GURL("http://example.com/allowed.html"),
+                                      load_policy_1.callback());
+  filter->GetLoadPolicyForSubdocument(
+      GURL("http://example.com/disallowed.html"), load_policy_2.callback());
+
+  RunUntilIdle();
+  load_policy_1.ExpectReceivedOnce(LoadPolicy::ALLOW);
+  load_policy_2.ExpectReceivedOnce(LoadPolicy::DISALLOW);
+}
+
+TEST_F(AsyncDocumentSubresourceFilterTest, FirstDisallowedLoadIsReported) {
+  dealer_handle()->SetRulesetFile(testing::TestRuleset::Open(ruleset()));
+  auto ruleset_handle = CreateRulesetHandle();
+
+  TestCallbackReceiver first_disallowed_load_receiver;
+  AsyncDocumentSubresourceFilter::InitializationParams params(
+      GURL("http://example.com"), ActivationLevel::ENABLED, false);
+
+  TestActivationStateCallbackReceiver activation_state;
+  auto filter = base::MakeUnique<AsyncDocumentSubresourceFilter>(
+      ruleset_handle.get(), std::move(params), activation_state.callback(),
+      first_disallowed_load_receiver.closure());
+
+  LoadPolicyCallbackReceiver load_policy_1;
+  filter->GetLoadPolicyForSubdocument(GURL("http://example.com/allowed.html"),
+                                      load_policy_1.callback());
+  RunUntilIdle();
+  load_policy_1.ExpectReceivedOnce(LoadPolicy::ALLOW);
+  EXPECT_EQ(0, first_disallowed_load_receiver.callback_count());
+
+  LoadPolicyCallbackReceiver load_policy_2;
+  filter->GetLoadPolicyForSubdocument(
+      GURL("http://example.com/disallowed.html"), load_policy_2.callback());
+  RunUntilIdle();
+  load_policy_2.ExpectReceivedOnce(LoadPolicy::DISALLOW);
+  EXPECT_EQ(0, first_disallowed_load_receiver.callback_count());
+
+  filter->ReportDisallowedLoad();
+  EXPECT_EQ(1, first_disallowed_load_receiver.callback_count());
+  RunUntilIdle();
+}
+
+}  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/verified_ruleset_dealer.h b/components/subresource_filter/content/browser/verified_ruleset_dealer.h
index e3e248a6..b49246b 100644
--- a/components/subresource_filter/content/browser/verified_ruleset_dealer.h
+++ b/components/subresource_filter/content/browser/verified_ruleset_dealer.h
@@ -141,6 +141,9 @@
   void GetRulesetAsync(base::Callback<void(VerifiedRuleset*)> callback);
 
  private:
+  // This is to allow ADSF to post |ruleset_.get()| pointer to |task_runner_|.
+  friend class AsyncDocumentSubresourceFilter;
+
   // Note: Raw pointer, |ruleset_| already holds a reference to |task_runner_|.
   base::SequencedTaskRunner* task_runner_;
   std::unique_ptr<VerifiedRuleset, base::OnTaskRunnerDeleter> ruleset_;
diff --git a/components/subresource_filter/core/common/indexed_ruleset.cc b/components/subresource_filter/core/common/indexed_ruleset.cc
index 75ac717..b5455cc 100644
--- a/components/subresource_filter/core/common/indexed_ruleset.cc
+++ b/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -470,10 +470,10 @@
 
 }  // namespace
 
+// static
 bool IndexedRulesetMatcher::Verify(const uint8_t* buffer, size_t size) {
-  const auto* indexed_ruleset = flat::GetIndexedRuleset(buffer);
   flatbuffers::Verifier verifier(buffer, size);
-  return indexed_ruleset->Verify(verifier);
+  return flat::VerifyIndexedRulesetBuffer(verifier);
 }
 
 IndexedRulesetMatcher::IndexedRulesetMatcher(const uint8_t* buffer, size_t size)
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc
index 04c07a467..880d0a21 100644
--- a/content/browser/frame_host/navigation_entry_impl.cc
+++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -702,6 +702,8 @@
 
 RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams(
     const FrameNavigationEntry& frame_entry,
+    const GURL& original_url,
+    const std::string& original_method,
     bool is_history_navigation_in_new_child,
     const std::map<std::string, bool>& subframe_unique_names,
     bool has_committed_real_load,
@@ -733,8 +735,8 @@
   user_gesture = has_user_gesture();
 #endif
   RequestNavigationParams request_params(
-      GetIsOverridingUserAgent(), redirects, GetCanLoadLocalResources(),
-      frame_entry.page_state(), GetUniqueID(),
+      GetIsOverridingUserAgent(), redirects, original_url, original_method,
+      GetCanLoadLocalResources(), frame_entry.page_state(), GetUniqueID(),
       is_history_navigation_in_new_child, subframe_unique_names,
       has_committed_real_load, intended_as_new_entry, pending_offset_to_send,
       current_offset_to_send, current_length_to_send, IsViewSourceMode(),
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h
index 96f7ef8..4f3183b 100644
--- a/content/browser/frame_host/navigation_entry_impl.h
+++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -186,6 +186,8 @@
   StartNavigationParams ConstructStartNavigationParams() const;
   RequestNavigationParams ConstructRequestNavigationParams(
       const FrameNavigationEntry& frame_entry,
+      const GURL& original_url,
+      const std::string& original_method,
       bool is_history_navigation_in_new_child,
       const std::map<std::string, bool>& subframe_unique_names,
       bool has_committed_real_load,
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index cce1817..263a9475 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -206,10 +206,12 @@
   // the renderer in the first place as part of OpenURL.
   bool browser_initiated = !entry.is_renderer_initiated();
 
+  CommonNavigationParams common_params = entry.ConstructCommonNavigationParams(
+      frame_entry, request_body, dest_url, dest_referrer, navigation_type,
+      previews_state, navigation_start);
+
   std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
-      frame_tree_node, entry.ConstructCommonNavigationParams(
-                           frame_entry, request_body, dest_url, dest_referrer,
-                           navigation_type, previews_state, navigation_start),
+      frame_tree_node, common_params,
       BeginNavigationParams(entry.extra_headers(), net::LOAD_NORMAL,
                             false,  // has_user_gestures
                             false,  // skip_service_worker
@@ -217,7 +219,8 @@
                             blink::WebMixedContentContextType::Blockable,
                             initiator),
       entry.ConstructRequestNavigationParams(
-          frame_entry, is_history_navigation_in_new_child,
+          frame_entry, common_params.url, common_params.method,
+          is_history_navigation_in_new_child,
           entry.GetSubframeUniqueNames(frame_tree_node),
           frame_tree_node->has_committed_real_load(),
           controller->GetPendingEntryIndex() == -1,
@@ -254,8 +257,9 @@
   // renderer and sent to the browser instead of being measured here.
   // TODO(clamy): The pending history list offset should be properly set.
   RequestNavigationParams request_params(
-      false,                          // is_overriding_user_agent
-      std::vector<GURL>(),            // redirects
+      false,                // is_overriding_user_agent
+      std::vector<GURL>(),  // redirects
+      common_params.url, common_params.method,
       false,                          // can_load_local_resources
       PageState(),                    // page_state
       0,                              // nav_entry_id
@@ -432,6 +436,7 @@
   request_params_.navigation_timing.fetch_start = base::TimeTicks::Now();
 
   request_params_.redirect_response.push_back(response->head);
+  request_params_.redirect_infos.push_back(redirect_info);
 
   request_params_.redirects.push_back(common_params_.url);
   common_params_.url = redirect_info.new_url;
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 19f822f..b9e03c5 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -455,7 +455,8 @@
               previews_state, navigation_start),
           entry.ConstructStartNavigationParams(),
           entry.ConstructRequestNavigationParams(
-              frame_entry, is_history_navigation_in_new_child,
+              frame_entry, GURL(), std::string(),
+              is_history_navigation_in_new_child,
               entry.GetSubframeUniqueNames(frame_tree_node),
               frame_tree_node->has_committed_real_load(),
               controller_->GetPendingEntryIndex() == -1,
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index 7ed0fab..454cbd7d 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -710,29 +710,24 @@
         stream_override_->response.encoded_data_length -
         initial_info.encoded_data_length;
     info = stream_override_->response;
+
+    // Replay the redirects that happened during navigation.
+    DCHECK_EQ(stream_override_->redirect_responses.size(),
+              stream_override_->redirect_infos.size());
+    for (size_t i = 0; i < stream_override_->redirect_responses.size(); ++i) {
+      bool result = OnReceivedRedirect(stream_override_->redirect_infos[i],
+                                       stream_override_->redirect_responses[i]);
+      if (!result) {
+        NOTREACHED();
+        return;
+      }
+    }
   }
 
   WebURLResponse response;
   GURL url(request_.url());
   PopulateURLResponse(url, info, &response, request_.reportRawHeaders());
 
-  if (stream_override_.get()) {
-    CHECK(IsBrowserSideNavigationEnabled());
-    DCHECK(stream_override_->redirect_responses.size() ==
-           stream_override_->redirects.size());
-    for (size_t i = 0; i < stream_override_->redirects.size(); ++i) {
-      WebURLResponse previous_response;
-      // TODO(arthursonzogni) Once Devtool is supported by PlzNavigate, the
-      // |report_raw_header| argument must be checked.
-      WebURLLoaderImpl::PopulateURLResponse(
-          stream_override_->redirects[i],
-          stream_override_->redirect_responses[i],
-          &previous_response,
-          request_.reportRawHeaders());
-      response.appendRedirectResponse(previous_response);
-    }
-  }
-
   bool show_raw_listing = false;
   if (info.mime_type == "text/vnd.chromium.ftp-dir") {
     if (url.query_piece() == "raw") {
@@ -1191,6 +1186,10 @@
   new_request.setHTTPMethod(WebString::fromUTF8(redirect_info.new_method));
   if (redirect_info.new_method == old_method)
     new_request.setHTTPBody(request.httpBody());
+
+  new_request.setCheckForBrowserSideNavigation(
+      request.checkForBrowserSideNavigation());
+
   return new_request;
 }
 
diff --git a/content/child/web_url_loader_impl.h b/content/child/web_url_loader_impl.h
index c516452..27b4b2f 100644
--- a/content/child/web_url_loader_impl.h
+++ b/content/child/web_url_loader_impl.h
@@ -30,6 +30,7 @@
   ResourceResponseHead response;
   std::vector<GURL> redirects;
   std::vector<ResourceResponseInfo> redirect_responses;
+  std::vector<net::RedirectInfo> redirect_infos;
 
   // The delta between the actual transfer size and the one reported by the
   // AsyncResourceLoader due to not having the ResourceResponse.
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 35126af..b0528d68 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -371,6 +371,9 @@
   IPC_STRUCT_TRAITS_MEMBER(is_overriding_user_agent)
   IPC_STRUCT_TRAITS_MEMBER(redirects)
   IPC_STRUCT_TRAITS_MEMBER(redirect_response)
+  IPC_STRUCT_TRAITS_MEMBER(redirect_infos)
+  IPC_STRUCT_TRAITS_MEMBER(original_url)
+  IPC_STRUCT_TRAITS_MEMBER(original_method)
   IPC_STRUCT_TRAITS_MEMBER(can_load_local_resources)
   IPC_STRUCT_TRAITS_MEMBER(page_state)
   IPC_STRUCT_TRAITS_MEMBER(nav_entry_id)
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc
index b232ce3..613918e 100644
--- a/content/common/navigation_params.cc
+++ b/content/common/navigation_params.cc
@@ -148,6 +148,8 @@
 RequestNavigationParams::RequestNavigationParams(
     bool is_overriding_user_agent,
     const std::vector<GURL>& redirects,
+    const GURL& original_url,
+    const std::string& original_method,
     bool can_load_local_resources,
     const PageState& page_state,
     int nav_entry_id,
@@ -163,6 +165,8 @@
     bool has_user_gesture)
     : is_overriding_user_agent(is_overriding_user_agent),
       redirects(redirects),
+      original_url(original_url),
+      original_method(original_method),
       can_load_local_resources(can_load_local_resources),
       page_state(page_state),
       nav_entry_id(nav_entry_id),
@@ -178,8 +182,7 @@
       should_create_service_worker(false),
       service_worker_provider_id(kInvalidServiceWorkerProviderId),
       appcache_host_id(kAppCacheNoHostId),
-      has_user_gesture(has_user_gesture) {
-}
+      has_user_gesture(has_user_gesture) {}
 
 RequestNavigationParams::RequestNavigationParams(
     const RequestNavigationParams& other) = default;
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h
index c47da6b8..1051307 100644
--- a/content/common/navigation_params.h
+++ b/content/common/navigation_params.h
@@ -22,6 +22,7 @@
 #include "content/public/common/referrer.h"
 #include "content/public/common/request_context_type.h"
 #include "content/public/common/resource_response.h"
+#include "net/url_request/redirect_info.h"
 #include "third_party/WebKit/public/platform/WebMixedContentContextType.h"
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
@@ -228,6 +229,8 @@
   RequestNavigationParams();
   RequestNavigationParams(bool is_overriding_user_agent,
                           const std::vector<GURL>& redirects,
+                          const GURL& original_url,
+                          const std::string& original_method,
                           bool can_load_local_resources,
                           const PageState& page_state,
                           int nav_entry_id,
@@ -254,6 +257,15 @@
   // The ResourceResponseInfos received during redirects.
   std::vector<ResourceResponseInfo> redirect_response;
 
+  // PlzNavigate
+  // The RedirectInfos received during redirects.
+  std::vector<net::RedirectInfo> redirect_infos;
+
+  // PlzNavigate
+  // The original URL & method for this navigation.
+  GURL original_url;
+  std::string original_method;
+
   // Whether or not this url should be allowed to access local file://
   // resources.
   bool can_load_local_resources;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 092fac7..6e997a6 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -561,15 +561,28 @@
 
 WebURLRequest CreateURLRequestForNavigation(
     const CommonNavigationParams& common_params,
+    const RequestNavigationParams& request_params,
     std::unique_ptr<StreamOverrideParameters> stream_override,
     bool is_view_source_mode_enabled,
-    bool is_same_document_navigation,
-    int nav_entry_id) {
-  WebURLRequest request(common_params.url);
+    bool is_same_document_navigation) {
+  // PlzNavigate: use the original navigation url to construct the
+  // WebURLRequest. The WebURLloaderImpl will replay the redirects afterwards
+  // and will eventually commit the final url.
+  const GURL navigation_url = IsBrowserSideNavigationEnabled() &&
+                                      !request_params.original_url.is_empty()
+                                  ? request_params.original_url
+                                  : common_params.url;
+  const std::string navigation_method =
+      IsBrowserSideNavigationEnabled() &&
+              !request_params.original_method.empty()
+          ? request_params.original_method
+          : common_params.method;
+  WebURLRequest request(navigation_url);
+  request.setHTTPMethod(WebString::fromUTF8(navigation_method));
+
   if (is_view_source_mode_enabled)
     request.setCachePolicy(WebCachePolicy::ReturnCacheDataElseLoad);
 
-  request.setHTTPMethod(WebString::fromUTF8(common_params.method));
   if (common_params.referrer.url.is_valid()) {
     WebString web_referrer = WebSecurityPolicy::generateReferrerHeader(
         common_params.referrer.policy, common_params.url,
@@ -587,7 +600,8 @@
 
   RequestExtraData* extra_data = new RequestExtraData();
   extra_data->set_stream_override(std::move(stream_override));
-  extra_data->set_navigation_initiated_by_renderer(nav_entry_id == 0);
+  extra_data->set_navigation_initiated_by_renderer(
+      request_params.nav_entry_id == 0);
   request.setExtraData(extra_data);
 
   // Set the ui timestamp for this navigation. Currently the timestamp here is
@@ -3347,7 +3361,7 @@
   bool content_initiated = !pending_navigation_params_.get();
 
   // Make sure any previous redirect URLs end up in our new data source.
-  if (pending_navigation_params_.get()) {
+  if (pending_navigation_params_.get() && !IsBrowserSideNavigationEnabled()) {
     for (const auto& i :
          pending_navigation_params_->request_params.redirects) {
       datasource->appendRedirect(i);
@@ -3404,12 +3418,10 @@
         navigation_state->request_params().navigation_timing.redirect_end);
     double fetch_start = ConvertToBlinkTime(
         navigation_state->request_params().navigation_timing.fetch_start);
-    std::vector<GURL> redirectChain =
-        navigation_state->request_params().redirects;
-    redirectChain.push_back(navigation_state->common_params().url);
 
-    datasource->updateNavigation(redirect_start, redirect_end, fetch_start,
-                                 redirectChain);
+    datasource->updateNavigation(
+        redirect_start, redirect_end, fetch_start,
+        !navigation_state->request_params().redirects.empty());
     // TODO(clamy) We need to provide additional timing values for the
     // Navigation Timing API to work with browser-side navigations.
     // UnloadEventStart and UnloadEventEnd are still missing.
@@ -5140,6 +5152,7 @@
   stream_override->response = response;
   stream_override->redirects = request_params.redirects;
   stream_override->redirect_responses = request_params.redirect_response;
+  stream_override->redirect_infos = request_params.redirect_infos;
 
   // If the request was initiated in the context of a user gesture then make
   // sure that the navigation also executes in the context of a user gesture.
@@ -5183,11 +5196,11 @@
   // Send the provisional load failure.
   blink::WebURLError error =
       CreateWebURLError(common_params.url, has_stale_copy_in_cache, error_code);
-  WebURLRequest failed_request = CreateURLRequestForNavigation(
-      common_params, std::unique_ptr<StreamOverrideParameters>(),
-      frame_->isViewSourceModeEnabled(),
-      false,  // is_same_document_navigation
-      request_params.nav_entry_id);
+  WebURLRequest failed_request =
+      CreateURLRequestForNavigation(common_params, request_params,
+                                    std::unique_ptr<StreamOverrideParameters>(),
+                                    frame_->isViewSourceModeEnabled(),
+                                    false);  // is_same_document_navigation
 
   if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) {
     // The browser expects this frame to be loading an error page. Inform it
@@ -5890,9 +5903,8 @@
       FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type);
 
   WebURLRequest request = CreateURLRequestForNavigation(
-      common_params, std::move(stream_params),
-      frame_->isViewSourceModeEnabled(), is_same_document,
-      request_params.nav_entry_id);
+      common_params, request_params, std::move(stream_params),
+      frame_->isViewSourceModeEnabled(), is_same_document);
   request.setFrameType(IsTopLevelNavigation(frame_)
                            ? blink::WebURLRequest::FrameTypeTopLevel
                            : blink::WebURLRequest::FrameTypeNested);
diff --git a/extensions/browser/api/web_request/web_request_resource_type.cc b/extensions/browser/api/web_request/web_request_resource_type.cc
index e92a5b2..c0329c38 100644
--- a/extensions/browser/api/web_request/web_request_resource_type.cc
+++ b/extensions/browser/api/web_request/web_request_resource_type.cc
@@ -26,6 +26,7 @@
     {"object", WebRequestResourceType::OBJECT},
     {"xmlhttprequest", WebRequestResourceType::XHR},
     {"ping", WebRequestResourceType::PING},
+    {"csp_report", WebRequestResourceType::CSP_REPORT},
     {"media", WebRequestResourceType::MEDIA},
     {"websocket", WebRequestResourceType::WEB_SOCKET},
     {"other", WebRequestResourceType::OTHER},
@@ -73,7 +74,7 @@
     case content::RESOURCE_TYPE_SERVICE_WORKER:
       return WebRequestResourceType::SCRIPT;
     case content::RESOURCE_TYPE_CSP_REPORT:
-      return WebRequestResourceType::OTHER;
+      return WebRequestResourceType::CSP_REPORT;
     case content::RESOURCE_TYPE_PLUGIN_RESOURCE:
       return WebRequestResourceType::OBJECT;
     case content::RESOURCE_TYPE_LAST_TYPE:
diff --git a/extensions/browser/api/web_request/web_request_resource_type.h b/extensions/browser/api/web_request/web_request_resource_type.h
index 9cecc2f..af24532b 100644
--- a/extensions/browser/api/web_request/web_request_resource_type.h
+++ b/extensions/browser/api/web_request/web_request_resource_type.h
@@ -27,6 +27,7 @@
   OBJECT,
   XHR,
   PING,
+  CSP_REPORT,
   MEDIA,
   WEB_SOCKET,
 
diff --git a/extensions/common/api/web_request.json b/extensions/common/api/web_request.json
index b676a02..1fe511a 100644
--- a/extensions/common/api/web_request.json
+++ b/extensions/common/api/web_request.json
@@ -16,7 +16,7 @@
       {
         "id": "ResourceType",
         "type": "string",
-        "enum": ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "media", "websocket", "other"]
+        "enum": ["main_frame", "sub_frame", "stylesheet", "script", "image", "font", "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", "other"]
       },
       {
         "id": "OnBeforeRequestOptions",
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h
index b108fad8..e622227 100644
--- a/headless/lib/browser/headless_browser_impl.h
+++ b/headless/lib/browser/headless_browser_impl.h
@@ -21,9 +21,6 @@
 #include "headless/lib/browser/headless_window_tree_host.h"
 #endif
 
-// Note: unused but needed to make sure this header gets generated.
-#include "headless/public/version.h"
-
 namespace headless {
 
 class HeadlessBrowserContextImpl;
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn
index cf22cd0b..0bc6858 100644
--- a/ios/chrome/app/application_delegate/BUILD.gn
+++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -18,6 +18,7 @@
 }
 
 source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
     "app_state_unittest.mm",
diff --git a/ios/chrome/app/application_delegate/app_state_unittest.mm b/ios/chrome/app/application_delegate/app_state_unittest.mm
index 1be7e7e..76ae229 100644
--- a/ios/chrome/app/application_delegate/app_state_unittest.mm
+++ b/ios/chrome/app/application_delegate/app_state_unittest.mm
@@ -8,7 +8,6 @@
 
 #include "base/ios/block_types.h"
 #include "base/mac/scoped_block.h"
-#import "base/mac/scoped_nsobject.h"
 #include "base/memory/ptr_util.h"
 #include "base/synchronization/lock.h"
 #import "ios/chrome/app/application_delegate/app_navigation.h"
@@ -44,6 +43,10 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #include "third_party/ocmock/gtest_support.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 #pragma mark - Class definition.
 
 namespace {
@@ -159,9 +162,9 @@
   }
 
   void swizzleSafeModeShouldStart(BOOL shouldStart) {
-    safe_mode_swizzle_block_.reset([^BOOL(id self) {
+    safe_mode_swizzle_block_ = ^BOOL(id self) {
       return shouldStart;
-    } copy]);
+    };
     safe_mode_swizzler_.reset(new ScopedBlockSwizzler(
         [SafeModeCoordinator class], @selector(shouldStart),
         safe_mode_swizzle_block_));
@@ -170,9 +173,9 @@
   void swizzleMetricsMediatorDisableReporting() {
     metrics_mediator_called_ = NO;
 
-    metrics_mediator_swizzle_block_.reset([^(id self) {
+    metrics_mediator_swizzle_block_ = ^() {
       metrics_mediator_called_ = YES;
-    } copy]);
+    };
 
     metrics_mediator_swizzler_.reset(new ScopedBlockSwizzler(
         [MetricsMediator class], @selector(disableReporting),
@@ -182,15 +185,14 @@
   void swizzleHandleStartupParameters(
       id<TabOpening> expectedTabOpener,
       id<BrowserViewInformation> expectedBrowserViewInformation) {
-    handle_startup_swizzle_block_.reset(
+    handle_startup_swizzle_block_ =
         ^(id self, id<TabOpening> tabOpener,
           id<StartupInformation> startupInformation,
           id<BrowserViewInformation> browserViewInformation) {
           ASSERT_EQ(startup_information_mock_, startupInformation);
           ASSERT_EQ(expectedTabOpener, tabOpener);
           ASSERT_EQ(expectedBrowserViewInformation, browserViewInformation);
-        },
-        base::scoped_policy::RETAIN);
+        };
 
     handle_startup_swizzler_.reset(new ScopedBlockSwizzler(
         [UserActivityHandler class],
@@ -242,10 +244,10 @@
 
   AppState* getAppStateWithMock() {
     if (!app_state_) {
-      app_state_.reset([[AppState alloc]
-          initWithBrowserLauncher:browser_launcher_mock_
-               startupInformation:startup_information_mock_
-              applicationDelegate:main_application_delegate_]);
+      app_state_ =
+          [[AppState alloc] initWithBrowserLauncher:browser_launcher_mock_
+                                 startupInformation:startup_information_mock_
+                                applicationDelegate:main_application_delegate_];
       [app_state_ setWindow:window_];
     }
     return app_state_;
@@ -253,10 +255,10 @@
 
   AppState* getAppStateWithRealWindow(UIWindow* window) {
     if (!app_state_) {
-      app_state_.reset([[AppState alloc]
-          initWithBrowserLauncher:browser_launcher_mock_
-               startupInformation:startup_information_mock_
-              applicationDelegate:main_application_delegate_]);
+      app_state_ =
+          [[AppState alloc] initWithBrowserLauncher:browser_launcher_mock_
+                                 startupInformation:startup_information_mock_
+                                applicationDelegate:main_application_delegate_];
       [app_state_ setWindow:window];
     }
     return app_state_;
@@ -271,15 +273,15 @@
   BOOL metricsMediatorHasBeenCalled() { return metrics_mediator_called_; }
 
  private:
-  base::scoped_nsobject<AppState> app_state_;
+  AppState* app_state_;
   id browser_launcher_mock_;
   id startup_information_mock_;
   id main_application_delegate_;
   id window_;
   id browser_view_information_;
-  base::mac::ScopedBlock<DecisionBlock> safe_mode_swizzle_block_;
-  base::mac::ScopedBlock<HandleStartupParam> handle_startup_swizzle_block_;
-  base::mac::ScopedBlock<ProceduralBlock> metrics_mediator_swizzle_block_;
+  DecisionBlock safe_mode_swizzle_block_;
+  HandleStartupParam handle_startup_swizzle_block_;
+  ProceduralBlock metrics_mediator_swizzle_block_;
   std::unique_ptr<ScopedBlockSwizzler> safe_mode_swizzler_;
   std::unique_ptr<ScopedBlockSwizzler> handle_startup_swizzler_;
   std::unique_ptr<ScopedBlockSwizzler> metrics_mediator_swizzler_;
@@ -468,14 +470,14 @@
       [OCMockObject mockForClass:[MainApplicationDelegate class]];
   id window = [OCMockObject mockForClass:[UIWindow class]];
 
-  base::scoped_nsobject<FakeStartupInformation> startupInformation(
-      [[FakeStartupInformation alloc] init]);
+  FakeStartupInformation* startupInformation =
+      [[FakeStartupInformation alloc] init];
   [startupInformation setIsColdStart:YES];
 
-  base::scoped_nsobject<AppState> appState([[AppState alloc]
-      initWithBrowserLauncher:browserLauncher
-           startupInformation:startupInformation
-          applicationDelegate:applicationDelegate]);
+  AppState* appState =
+      [[AppState alloc] initWithBrowserLauncher:browserLauncher
+                             startupInformation:startupInformation
+                            applicationDelegate:applicationDelegate];
   [appState setWindow:window];
 
   ASSERT_TRUE([startupInformation isColdStart]);
@@ -521,10 +523,10 @@
       [OCMockObject mockForProtocol:@protocol(StartupInformation)];
   [[startupInformation expect] stopChromeMain];
 
-  base::scoped_nsobject<AppState> appState([[AppState alloc]
-      initWithBrowserLauncher:browserLauncher
-           startupInformation:startupInformation
-          applicationDelegate:applicationDelegate]);
+  AppState* appState =
+      [[AppState alloc] initWithBrowserLauncher:browserLauncher
+                             startupInformation:startupInformation
+                            applicationDelegate:applicationDelegate];
   [appState setWindow:window];
 
   id application = [OCMockObject mockForClass:[UIApplication class]];
@@ -579,7 +581,7 @@
   // Swizzle Startup Parameters.
   swizzleHandleStartupParameters(tabOpener, browserViewInformation);
 
-  UIWindow* window = [[[UIWindow alloc] init] autorelease];
+  UIWindow* window = [[UIWindow alloc] init];
   AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(NO, window);
 
   ASSERT_EQ(NSUInteger(1), [window subviews].count);
@@ -621,7 +623,7 @@
   id tabSwitcher = [OCMockObject mockForProtocol:@protocol(TabSwitching)];
   [[[tabSwitcher stub] andReturnValue:@YES] openNewTabFromTabSwitcher];
 
-  UIWindow* window = [[[UIWindow alloc] init] autorelease];
+  UIWindow* window = [[UIWindow alloc] init];
   AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(YES, window);
 
   ASSERT_EQ(NSUInteger(1), [window subviews].count);
@@ -668,7 +670,7 @@
   id tabSwitcher = [OCMockObject mockForProtocol:@protocol(TabSwitching)];
   [[[tabSwitcher stub] andReturnValue:@NO] openNewTabFromTabSwitcher];
 
-  UIWindow* window = [[[UIWindow alloc] init] autorelease];
+  UIWindow* window = [[UIWindow alloc] init];
   AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(YES, window);
 
   // incognitoBlocker.
@@ -816,9 +818,9 @@
 
   AppState* appState = getAppStateWithMock();
 
-  UIWindow* window = [[[UIWindow alloc] init] autorelease];
+  UIWindow* window = [[UIWindow alloc] init];
   appState.safeModeCoordinator =
-      [[[SafeModeCoordinator alloc] initWithWindow:window] autorelease];
+      [[SafeModeCoordinator alloc] initWithWindow:window];
 
   ASSERT_TRUE([appState isInSafeMode]);
 
@@ -833,7 +835,7 @@
 // Tests that -applicationDidEnterBackground creates an incognito blocker.
 TEST_F(AppStateTest, applicationDidEnterBackgroundIncognito) {
   // Setup.
-  UIWindow* window = [[[UIWindow alloc] init] autorelease];
+  UIWindow* window = [[UIWindow alloc] init];
   id application = [OCMockObject niceMockForClass:[UIApplication class]];
   id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
   id browserViewInformation = getBrowserViewInformationMock();
@@ -873,7 +875,7 @@
 // never been in a Foreground stage.
 TEST_F(AppStateTest, applicationDidEnterBackgroundStageBackground) {
   // Setup.
-  UIWindow* window = [[[UIWindow alloc] init] autorelease];
+  UIWindow* window = [[UIWindow alloc] init];
   id application = [OCMockObject mockForClass:[UIApplication class]];
   id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
   id browserLauncher = getBrowserLauncherMock();
@@ -896,7 +898,7 @@
 // blocker if there is no incognito tab.
 TEST_F(AppStateTest, applicationDidEnterBackgroundNoIncognitoBlocker) {
   // Setup.
-  UIWindow* window = [[[UIWindow alloc] init] autorelease];
+  UIWindow* window = [[UIWindow alloc] init];
   id application = [OCMockObject niceMockForClass:[UIApplication class]];
   id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]];
   id browserViewInformation = getBrowserViewInformationMock();
diff --git a/ios/chrome/app/application_delegate/background_activity_unittest.mm b/ios/chrome/app/application_delegate/background_activity_unittest.mm
index d9f4788..2c6a5d3 100644
--- a/ios/chrome/app/application_delegate/background_activity_unittest.mm
+++ b/ios/chrome/app/application_delegate/background_activity_unittest.mm
@@ -14,6 +14,10 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "third_party/ocmock/gtest_support.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 // Verifies that -application:performFetchWithCompletionHandler: calls the
 // browser launcher in background state and uploads the report.
 TEST(BackgroundActivityTest, performFetchWithCompletionHandler) {
diff --git a/ios/chrome/app/application_delegate/memory_warning_helper_unittest.mm b/ios/chrome/app/application_delegate/memory_warning_helper_unittest.mm
index 8052c01..718f19d 100644
--- a/ios/chrome/app/application_delegate/memory_warning_helper_unittest.mm
+++ b/ios/chrome/app/application_delegate/memory_warning_helper_unittest.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/app/application_delegate/memory_warning_helper.h"
 
 #include "base/mac/bind_objc_block.h"
-#import "base/mac/scoped_nsobject.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
@@ -13,6 +12,10 @@
 #import "ios/chrome/browser/metrics/previous_session_info.h"
 #include "testing/platform_test.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 using previous_session_info_constants::
     kDidSeeMemoryWarningShortlyBeforeTerminating;
 
@@ -34,7 +37,7 @@
 
   MemoryWarningHelper* GetMemoryHelper() {
     if (!memory_helper_) {
-      memory_helper_.reset([[MemoryWarningHelper alloc] init]);
+      memory_helper_ = [[MemoryWarningHelper alloc] init];
     }
     return memory_helper_;
   }
@@ -53,7 +56,7 @@
   base::RunLoop run_loop_;
   base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level_;
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
-  base::scoped_nsobject<MemoryWarningHelper> memory_helper_;
+  MemoryWarningHelper* memory_helper_;
 
   DISALLOW_COPY_AND_ASSIGN(MemoryWarningHelperTest);
 };
diff --git a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
index 67b1ca2..8c03bd4c 100644
--- a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
+++ b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
@@ -8,7 +8,6 @@
 #import <Foundation/Foundation.h>
 
 #include "base/mac/scoped_block.h"
-#include "base/mac/scoped_nsobject.h"
 #import "breakpad/src/client/ios/BreakpadController.h"
 #include "components/metrics/metrics_service.h"
 #import "ios/chrome/app/application_delegate/startup_information.h"
@@ -24,6 +23,10 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #include "third_party/ocmock/gtest_support.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 #pragma mark - connectionTypeChanged tests.
 
 // Mock class for testing MetricsMediator.
@@ -93,8 +96,7 @@
 // uploading in the breakpad and in the metrics service.
 TEST(MetricsMediatorTest, connectionTypeChanged) {
   [[PreviousSessionInfo sharedInstance] setIsFirstSessionAfterUpgrade:NO];
-  base::scoped_nsobject<MetricsMediatorMock> mock_metrics_helper(
-      [[MetricsMediatorMock alloc] init]);
+  MetricsMediatorMock* mock_metrics_helper = [[MetricsMediatorMock alloc] init];
 
   // Checks all different scenarios.
   for (int i = 0; i < 8; ++i) {
@@ -126,11 +128,11 @@
         [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
     [[[browser_view_information_ stub] andReturn:mainTabModel] mainTabModel];
 
-    swizzle_block_.reset([^(id self, int numTab) {
+    swizzle_block_ = [^(id self, int numTab) {
       has_been_called_ = YES;
       // Tests.
       EXPECT_EQ(tabCount, numTab);
-    } copy]);
+    } copy];
     if (coldStart) {
       uma_histogram_swizzler_.reset(new ScopedBlockSwizzler(
           [MetricsMediator class], @selector(recordNumTabAtStartup:),
@@ -149,7 +151,7 @@
  private:
   id browser_view_information_;
   __block BOOL has_been_called_;
-  base::mac::ScopedBlock<logLaunchMetricsBlock> swizzle_block_;
+  logLaunchMetricsBlock swizzle_block_;
   std::unique_ptr<ScopedBlockSwizzler> uma_histogram_swizzler_;
 };
 
@@ -245,17 +247,16 @@
 // count waiting to be processed.
 TEST_P(MetricsMediatorShutdownTypeTest, ProcessCrashReportsPresentAtStartup) {
   // Create a MainController.
-  base::scoped_nsobject<MetricsMediator> metric_helper(
-      [[MetricsMediator alloc] init]);
+  MetricsMediator* metric_helper = [[MetricsMediator alloc] init];
 
   // Create a mock for BreakpadController and swizzle
   // +[BreakpadController sharedInstance] to return the mock instead of the
   // normal singleton instance.
-  base::scoped_nsobject<id> mock_breakpad_controller(
-      [[OCMockObject mockForClass:[BreakpadController class]] retain]);
+  id mock_breakpad_controller =
+      [OCMockObject mockForClass:[BreakpadController class]];
 
   id implementation_block = ^BreakpadController*(id self) {
-    return mock_breakpad_controller.get();
+    return mock_breakpad_controller;
   };
   ScopedBlockSwizzler breakpad_controller_shared_instance_swizzler(
       [BreakpadController class], @selector(sharedInstance),
@@ -268,7 +269,7 @@
   // Now call the method under test and verify that the Breakpad controller got
   // called appropriately.
   [metric_helper processCrashReportsPresentAtStartup];
-  EXPECT_OCMOCK_VERIFY(mock_breakpad_controller.get());
+  EXPECT_OCMOCK_VERIFY(mock_breakpad_controller);
 }
 
 INSTANTIATE_TEST_CASE_P(/* No InstantiationName */,
diff --git a/ios/chrome/app/application_delegate/url_opener_unittest.mm b/ios/chrome/app/application_delegate/url_opener_unittest.mm
index 481213c..b2aee14 100644
--- a/ios/chrome/app/application_delegate/url_opener_unittest.mm
+++ b/ios/chrome/app/application_delegate/url_opener_unittest.mm
@@ -6,7 +6,6 @@
 
 #import <Foundation/Foundation.h>
 
-#include "base/mac/scoped_nsobject.h"
 #include "ios/chrome/app/application_delegate/app_state.h"
 #include "ios/chrome/app/application_delegate/app_state_testing.h"
 #include "ios/chrome/app/application_delegate/mock_tab_opener.h"
@@ -24,6 +23,10 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #include "third_party/ocmock/gtest_support.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 #pragma mark - Tab Switcher Mock
 
 // This mocks either a iPad tab switcher controller or a iPhone stack view
@@ -112,8 +115,8 @@
 class URLOpenerTest : public PlatformTest {
  protected:
   MainController* GetMainController() {
-    if (!main_controller_.get()) {
-      main_controller_.reset([[MainController alloc] init]);
+    if (!main_controller_) {
+      main_controller_ = [[MainController alloc] init];
       [main_controller_ setUpAsForegrounded];
       id mainTabModel = [OCMockObject mockForClass:[TabModel class]];
       [[mainTabModel stub] resetSessionMetrics];
@@ -122,34 +125,34 @@
       [[mainTabModel stub] removeObserver:[OCMArg any]];
       [[main_controller_ browserViewInformation] setMainTabModel:mainTabModel];
     }
-    return main_controller_.get();
+    return main_controller_;
   }
 
  private:
-  base::scoped_nsobject<MainController> main_controller_;
+  MainController* main_controller_;
 };
 
 TEST_F(URLOpenerTest, HandleOpenURLWithNoOpenTab) {
   // The tab switcher controller should be dismissed with a new tab containing
   // the external URL.
   NSURL* url = [NSURL URLWithString:@"chromium://www.google.com"];
-  base::scoped_nsobject<ChromeAppStartupParameters> params(
+  ChromeAppStartupParameters* params =
       [ChromeAppStartupParameters newChromeAppStartupParametersWithURL:url
-                                                 fromSourceApplication:nil]);
+                                                 fromSourceApplication:nil];
 
-  base::scoped_nsobject<id> bvcMock([[URLOpenerMockBVC alloc] init]);
+  id bvcMock = [[URLOpenerMockBVC alloc] init];
 
-  base::scoped_nsobject<id> tabSwitcherController;
-  tabSwitcherController.reset([[URLOpenerOCMockComplexTypeHandler alloc]
+  id tabSwitcherController;
+  tabSwitcherController = [[URLOpenerOCMockComplexTypeHandler alloc]
       initWithRepresentedObject:[OCMockObject
-                                    mockForProtocol:@protocol(UrlLoader)]]);
+                                    mockForProtocol:@protocol(UrlLoader)]];
 
-  base::scoped_nsobject<id> block([(id) ^ (const GURL& url, NSUInteger position,
-                                           ui::PageTransition transition) {
+  id block = [(id) ^ (const GURL& url, NSUInteger position,
+                      ui::PageTransition transition) {
     EXPECT_EQ(url, [params externalURL]);
     EXPECT_EQ(NSNotFound, static_cast<NSInteger>(position));
     EXPECT_TRUE(PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK));
-  } copy]);
+  } copy];
   SEL dismissSelector =
       @selector(dismissWithNewTabAnimationToModel:withURL:atIndex:transition:);
   [tabSwitcherController onSelector:dismissSelector callBlockExpectation:block];
@@ -164,11 +167,11 @@
       [OCMockObject mockForClass:[MainApplicationDelegate class]];
 
   AppState* appState =
-      [[[AppState alloc] initWithBrowserLauncher:controller
-                              startupInformation:controller
-                             applicationDelegate:mainApplicationDelegate
-                                          window:controller.window
-                                   shouldOpenNTP:YES] autorelease];
+      [[AppState alloc] initWithBrowserLauncher:controller
+                             startupInformation:controller
+                            applicationDelegate:mainApplicationDelegate
+                                         window:controller.window
+                                  shouldOpenNTP:YES];
   controller.appState = appState;
 
   NSDictionary<NSString*, id>* options = nil;
@@ -183,21 +186,19 @@
 
 TEST_F(URLOpenerTest, HandleOpenURLWithOpenTabs) {
   NSURL* url = [NSURL URLWithString:@"chromium://www.google.com"];
-  base::scoped_nsobject<URLOpenerMockBVC> bvc_mock(
-      [[URLOpenerMockBVC alloc] init]);
-  base::scoped_nsobject<URLOpenerMockBVC> otr_bvc_mock(
-      [[URLOpenerMockBVC alloc] init]);
+  URLOpenerMockBVC* bvc_mock = [[URLOpenerMockBVC alloc] init];
+  URLOpenerMockBVC* otr_bvc_mock = [[URLOpenerMockBVC alloc] init];
   TestChromeBrowserState::Builder main_browser_state_builder;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state =
       main_browser_state_builder.Build();
-  bvc_mock.get().browserState = chrome_browser_state.get();
+  bvc_mock.browserState = chrome_browser_state.get();
 
   // Setup main controller.
   MainController* controller = GetMainController();
   controller.browserViewInformation.mainBVC =
-      static_cast<BrowserViewController*>(bvc_mock.get());
+      static_cast<BrowserViewController*>(bvc_mock);
   controller.browserViewInformation.otrBVC =
-      static_cast<BrowserViewController*>(otr_bvc_mock.get());
+      static_cast<BrowserViewController*>(otr_bvc_mock);
 
   NSDictionary<NSString*, id>* options = nil;
   [URLOpener openURL:url
@@ -225,7 +226,7 @@
   NSArray* applicationStatesToTest = @[ @YES, @NO ];
 
   // Mock of TabOpening, preventing the creation of a new tab.
-  base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]);
+  MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
 
   // The keys for this dictionary is the URL to call openURL:. The value
   // from the key is either YES or NO to indicate if this is a valid URL
@@ -281,8 +282,7 @@
                                ? nil
                                : [NSURL URLWithString:urlString];
           BOOL isValid = [[urlsToTest objectForKey:urlString] boolValue];
-          base::scoped_nsobject<NSMutableDictionary> options(
-              [[NSMutableDictionary alloc] init]);
+          NSMutableDictionary* options = [[NSMutableDictionary alloc] init];
           if (source != [NSNull null]) {
             [options setObject:source
                         forKey:UIApplicationOpenURLOptionsSourceApplicationKey];
@@ -291,10 +291,9 @@
             [options setObject:annotation
                         forKey:UIApplicationOpenURLOptionsAnnotationKey];
           }
-          base::scoped_nsobject<ChromeAppStartupParameters> params(
-              [ChromeAppStartupParameters
-                  newChromeAppStartupParametersWithURL:testUrl
-                                 fromSourceApplication:nil]);
+          ChromeAppStartupParameters* params = [ChromeAppStartupParameters
+              newChromeAppStartupParametersWithURL:testUrl
+                             fromSourceApplication:nil];
 
           // Action.
           BOOL result = [URLOpener openURL:testUrl
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
index d1125e1..6cedf957 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -10,7 +10,6 @@
 
 #include "base/ios/ios_util.h"
 #include "base/mac/scoped_block.h"
-#include "base/mac/scoped_nsobject.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/test/scoped_command_line.h"
 #include "components/handoff/handoff_utility.h"
@@ -38,13 +37,17 @@
 #include "ui/base/page_transition_types.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 #pragma mark - Tab Mock
 
 // Tab mock for using in UserActivity tests.
 @interface UserActivityHandlerTabMock : NSObject
 
 @property(nonatomic, readonly) GURL url;
-@property(nonatomic, readonly) NSString* tabId;
+@property(nonatomic, copy, readonly) NSString* tabId;
 
 @end
 
@@ -63,7 +66,7 @@
 // TabModel mock for using in UserActivity tests.
 @interface UserActivityHandlerTabModelMock : NSObject<NSFastEnumeration> {
  @private
-  base::scoped_nsobject<NSMutableArray> _tabs;
+  NSMutableArray* _tabs;
 }
 
 - (void)addTab:(Tab*)tab;
@@ -76,13 +79,14 @@
 
 - (instancetype)init {
   if ((self = [super init])) {
-    _tabs.reset([[NSMutableArray alloc] init]);
+    _tabs = [[NSMutableArray alloc] init];
   }
   return self;
 }
 
 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState*)state
-                                  objects:(id*)stackbuf
+                                  objects:
+                                      (__unsafe_unretained id _Nonnull*)stackbuf
                                     count:(NSUInteger)len {
   return [_tabs countByEnumeratingWithState:state objects:stackbuf count:len];
 }
@@ -117,9 +121,9 @@
  protected:
   void swizzleHandleStartupParameters() {
     handle_startup_parameters_has_been_called_ = NO;
-    swizzle_block_.reset([^(id self) {
+    swizzle_block_ = [^(id self) {
       handle_startup_parameters_has_been_called_ = YES;
-    } copy]);
+    } copy];
     user_activity_handler_swizzler_.reset(new ScopedBlockSwizzler(
         [UserActivityHandler class],
         @selector(handleStartupParametersWithTabOpener:
@@ -139,10 +143,10 @@
   conditionBlock getCompletionHandler() {
     if (!completion_block_) {
       block_executed_ = NO;
-      completion_block_.reset([^(BOOL arg) {
+      completion_block_ = [^(BOOL arg) {
         block_executed_ = YES;
         block_argument_ = arg;
-      } copy]);
+      } copy];
     }
     return completion_block_;
   }
@@ -155,8 +159,8 @@
   __block BOOL block_executed_;
   __block BOOL block_argument_;
   std::unique_ptr<ScopedBlockSwizzler> user_activity_handler_swizzler_;
-  base::mac::ScopedBlock<startupParameterBlock> swizzle_block_;
-  base::mac::ScopedBlock<conditionBlock> completion_block_;
+  startupParameterBlock swizzle_block_;
+  conditionBlock completion_block_;
   __block BOOL handle_startup_parameters_has_been_called_;
 };
 
@@ -203,8 +207,8 @@
     @"thisIsGarbage", @"it.does.not.work", handoffWithSuffix, handoffWithPrefix
   ];
   for (NSString* userActivityType in userActivityTypes) {
-    base::scoped_nsobject<NSUserActivity> userActivity(
-        [[NSUserActivity alloc] initWithActivityType:userActivityType]);
+    NSUserActivity* userActivity =
+        [[NSUserActivity alloc] initWithActivityType:userActivityType];
     [userActivity setWebpageURL:[NSURL URLWithString:@"http://www.google.com"]];
 
     // The test will fail is a method of those objects is called.
@@ -228,8 +232,8 @@
 // set.
 TEST(UserActivityHandlerNoFixtureTest, continueUserActivityNoWebpage) {
   // Setup.
-  base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc]
-      initWithActivityType:handoff::kChromeHandoffActivityType]);
+  NSUserActivity* userActivity = [[NSUserActivity alloc]
+      initWithActivityType:handoff::kChromeHandoffActivityType];
 
   // The test will fail is a method of those objects is called.
   id tabOpenerMock = [OCMockObject mockForProtocol:@protocol(TabOpening)];
@@ -256,8 +260,8 @@
     return;
   }
   // Setup.
-  base::scoped_nsobject<NSUserActivity> userActivity(
-      [[NSUserActivity alloc] initWithActivityType:CSSearchableItemActionType]);
+  NSUserActivity* userActivity =
+      [[NSUserActivity alloc] initWithActivityType:CSSearchableItemActionType];
   NSString* invalidAction =
       [NSString stringWithFormat:@"%@.invalidAction",
                                  spotlight::StringFromSpotlightDomain(
@@ -290,8 +294,8 @@
 // by saving the url to startupParameters.
 TEST(UserActivityHandlerNoFixtureTest, continueUserActivityBackground) {
   // Setup.
-  base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc]
-      initWithActivityType:handoff::kChromeHandoffActivityType]);
+  NSUserActivity* userActivity = [[NSUserActivity alloc]
+      initWithActivityType:handoff::kChromeHandoffActivityType];
   NSURL* nsurl = [NSURL URLWithString:@"http://www.google.com"];
   [userActivity setWebpageURL:nsurl];
 
@@ -325,20 +329,19 @@
 // by opening a new tab.
 TEST(UserActivityHandlerNoFixtureTest, continueUserActivityForeground) {
   // Setup.
-  base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc]
-      initWithActivityType:handoff::kChromeHandoffActivityType]);
+  NSUserActivity* userActivity = [[NSUserActivity alloc]
+      initWithActivityType:handoff::kChromeHandoffActivityType];
   NSURL* nsurl = [NSURL URLWithString:@"http://www.google.com"];
   [userActivity setWebpageURL:nsurl];
 
-  base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]);
+  MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
 
   id startupInformationMock =
       [OCMockObject mockForProtocol:@protocol(StartupInformation)];
   [[[startupInformationMock stub] andReturnValue:@NO] isPresentingFirstRunUI];
 
-  base::scoped_nsobject<AppStartupParameters> startupParams(
-      [[AppStartupParameters alloc]
-          initWithExternalURL:(GURL("http://www.google.com"))]);
+  AppStartupParameters* startupParams = [[AppStartupParameters alloc]
+      initWithExternalURL:(GURL("http://www.google.com"))];
   [[[startupInformationMock stub] andReturn:startupParams] startupParameters];
 
   // Action.
@@ -356,18 +359,18 @@
 // Tests that a new tab is created when application is started via Universal
 // Link.
 TEST_F(UserActivityHandlerTest, continueUserActivityBrowsingWeb) {
-  base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc]
-      initWithActivityType:NSUserActivityTypeBrowsingWeb]);
+  NSUserActivity* userActivity = [[NSUserActivity alloc]
+      initWithActivityType:NSUserActivityTypeBrowsingWeb];
   // This URL is passed to application by iOS but is not used in this part
   // of application logic.
   NSURL* nsurl = [NSURL URLWithString:@"http://goo.gl/foo/bar"];
   [userActivity setWebpageURL:nsurl];
 
-  base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]);
+  MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
 
   // Use an object to capture the startup paramters set by UserActivityHandler.
-  base::scoped_nsobject<FakeStartupInformation> fakeStartupInformation(
-      [[FakeStartupInformation alloc] init]);
+  FakeStartupInformation* fakeStartupInformation =
+      [[FakeStartupInformation alloc] init];
   [fakeStartupInformation setIsPresentingFirstRunUI:NO];
 
   BOOL result =
@@ -395,8 +398,8 @@
   }
   // Setup.
   GURL gurlNewTab(kChromeUINewTabURL);
-  base::scoped_nsobject<FakeStartupInformation> fakeStartupInformation(
-      [[FakeStartupInformation alloc] init]);
+  FakeStartupInformation* fakeStartupInformation =
+      [[FakeStartupInformation alloc] init];
 
   NSArray* parametersToTest = @[
     @[
@@ -422,8 +425,8 @@
       switches::kEnableSpotlightActions);
 
   for (id parameters in parametersToTest) {
-    base::scoped_nsobject<NSUserActivity> userActivity([[NSUserActivity alloc]
-        initWithActivityType:CSSearchableItemActionType]);
+    NSUserActivity* userActivity = [[NSUserActivity alloc]
+        initWithActivityType:CSSearchableItemActionType];
     NSString* action = [NSString
         stringWithFormat:@"%@.%@", spotlight::StringFromSpotlightDomain(
                                        spotlight::DOMAIN_ACTIONS),
@@ -458,8 +461,8 @@
   // Setup.
   GURL gurl("http://www.google.com");
 
-  base::scoped_nsobject<AppStartupParameters> startupParams(
-      [[AppStartupParameters alloc] initWithExternalURL:gurl]);
+  AppStartupParameters* startupParams =
+      [[AppStartupParameters alloc] initWithExternalURL:gurl];
   [startupParams setLaunchInIncognito:YES];
 
   id startupInformationMock =
@@ -468,7 +471,7 @@
   [[[startupInformationMock stub] andReturn:startupParams] startupParameters];
   [[startupInformationMock expect] setStartupParameters:nil];
 
-  base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]);
+  MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
 
   // The test will fail is a method of this object is called.
   id browserViewMock =
@@ -493,18 +496,18 @@
   GURL gurl("chromium://u2f-callback?isU2F=1&tabID=B05B1860");
   NSString* tabID = [U2FController tabIDFromResponseURL:gurl];
 
-  base::scoped_nsobject<AppStartupParameters> startupParams(
-      [[AppStartupParameters alloc] initWithExternalURL:gurl]);
+  AppStartupParameters* startupParams =
+      [[AppStartupParameters alloc] initWithExternalURL:gurl];
   [startupParams setLaunchInIncognito:YES];
 
-  base::scoped_nsobject<UserActivityHandlerTabMock> tabMock(
-      [[UserActivityHandlerTabMock alloc] init]);
+  UserActivityHandlerTabMock* tabMock =
+      [[UserActivityHandlerTabMock alloc] init];
   id tabOCMock = [OCMockObject partialMockForObject:tabMock];
   [[[tabOCMock stub] andReturn:tabID] tabId];
 
-  base::scoped_nsobject<UserActivityHandlerTabModelMock> tabModel(
-      [[UserActivityHandlerTabModelMock alloc] init]);
-  [tabModel addTab:(Tab*)tabMock.get()];
+  UserActivityHandlerTabModelMock* tabModel =
+      [[UserActivityHandlerTabModelMock alloc] init];
+  [tabModel addTab:(Tab*)tabMock];
 
   id startupInformationMock =
       [OCMockObject mockForProtocol:@protocol(StartupInformation)];
@@ -514,12 +517,12 @@
 
   id browserViewInformationMock =
       [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
-  [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel.get()]
+  [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel]
       mainTabModel];
-  [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel.get()]
+  [[[browserViewInformationMock stub] andReturn:(TabModel*)tabModel]
       otrTabModel];
 
-  base::scoped_nsobject<MockTabOpener> tabOpener([[MockTabOpener alloc] init]);
+  MockTabOpener* tabOpener = [[MockTabOpener alloc] init];
 
   // Action.
   [UserActivityHandler
@@ -538,8 +541,8 @@
   // Setup.
   GURL gurlNewTab("chrome://newtab/");
 
-  base::scoped_nsobject<FakeStartupInformation> fakeStartupInformation(
-      [[FakeStartupInformation alloc] init]);
+  FakeStartupInformation* fakeStartupInformation =
+      [[FakeStartupInformation alloc] init];
   [fakeStartupInformation setIsPresentingFirstRunUI:NO];
 
   NSArray* parametersToTest = @[
@@ -551,9 +554,9 @@
   swizzleHandleStartupParameters();
 
   for (id parameters in parametersToTest) {
-    base::scoped_nsobject<UIApplicationShortcutItem> shortcut(
+    UIApplicationShortcutItem* shortcut =
         [[UIApplicationShortcutItem alloc] initWithType:parameters[0]
-                                         localizedTitle:parameters[0]]);
+                                         localizedTitle:parameters[0]];
 
     resetHandleStartupParametersHasBeenCalled();
 
@@ -593,9 +596,9 @@
       [OCMockObject mockForProtocol:@protocol(StartupInformation)];
   [[[startupInformationMock stub] andReturnValue:@YES] isPresentingFirstRunUI];
 
-  base::scoped_nsobject<UIApplicationShortcutItem> shortcut(
+  UIApplicationShortcutItem* shortcut =
       [[UIApplicationShortcutItem alloc] initWithType:@"OpenNewTab"
-                                       localizedTitle:@""]);
+                                       localizedTitle:@""];
 
   swizzleHandleStartupParameters();
 
diff --git a/ios/chrome/app/spotlight/BUILD.gn b/ios/chrome/app/spotlight/BUILD.gn
index b872afa..5a49178 100644
--- a/ios/chrome/app/spotlight/BUILD.gn
+++ b/ios/chrome/app/spotlight/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 source_set("spotlight") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
     "actions_spotlight_manager.h",
     "actions_spotlight_manager.mm",
diff --git a/ios/chrome/app/spotlight/actions_spotlight_manager.mm b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
index 5702538..1d453c5 100644
--- a/ios/chrome/app/spotlight/actions_spotlight_manager.mm
+++ b/ios/chrome/app/spotlight/actions_spotlight_manager.mm
@@ -6,7 +6,6 @@
 
 #import <CoreSpotlight/CoreSpotlight.h>
 
-#include "base/ios/weak_nsobject.h"
 #include "base/mac/foundation_util.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/sys_string_conversions.h"
@@ -18,6 +17,10 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 NSString* SpotlightActionFromString(NSString* query) {
@@ -108,20 +111,19 @@
 @implementation ActionsSpotlightManager
 
 + (ActionsSpotlightManager*)actionsSpotlightManager {
-  return [[[ActionsSpotlightManager alloc]
+  return [[ActionsSpotlightManager alloc]
       initWithLargeIconService:nil
-                        domain:spotlight::DOMAIN_ACTIONS] autorelease];
+                        domain:spotlight::DOMAIN_ACTIONS];
 }
 
 #pragma mark public methods
 
 - (void)indexActions {
-  base::WeakNSObject<ActionsSpotlightManager> weakSelf(self);
+  __weak ActionsSpotlightManager* weakSelf = self;
   dispatch_after(
       dispatch_time(DISPATCH_TIME_NOW, static_cast<int64_t>(1 * NSEC_PER_SEC)),
       dispatch_get_main_queue(), ^{
-        base::scoped_nsobject<ActionsSpotlightManager> strongSelf(
-            [weakSelf retain]);
+        ActionsSpotlightManager* strongSelf = weakSelf;
         [strongSelf clearAndAddSpotlightActions];
       });
 }
@@ -133,13 +135,12 @@
     if (!experimental_flags::IsSpotlightActionsEnabled()) {
       return;
     }
-    base::WeakNSObject<ActionsSpotlightManager> weakSelf(self);
+    __weak ActionsSpotlightManager* weakSelf = self;
     dispatch_after(
         dispatch_time(DISPATCH_TIME_NOW,
                       static_cast<int64_t>(1 * NSEC_PER_SEC)),
         dispatch_get_main_queue(), ^{
-          base::scoped_nsobject<ActionsSpotlightManager> strongSelf(
-              [weakSelf retain]);
+          ActionsSpotlightManager* strongSelf = weakSelf;
 
           if (!strongSelf) {
             return;
@@ -181,10 +182,10 @@
 }
 
 - (CSSearchableItem*)getItemForAction:(NSString*)action title:(NSString*)title {
-  base::scoped_nsobject<CSSearchableItemAttributeSet> attributeSet(
+  CSSearchableItemAttributeSet* attributeSet =
       [[CSSearchableItemAttributeSet alloc]
           initWithItemContentType:spotlight::StringFromSpotlightDomain(
-                                      spotlight::DOMAIN_ACTIONS)]);
+                                      spotlight::DOMAIN_ACTIONS)];
   [attributeSet setTitle:title];
   [attributeSet setDisplayName:title];
 
diff --git a/ios/chrome/app/spotlight/base_spotlight_manager.mm b/ios/chrome/app/spotlight/base_spotlight_manager.mm
index 4d497c1..6fb7759 100644
--- a/ios/chrome/app/spotlight/base_spotlight_manager.mm
+++ b/ios/chrome/app/spotlight/base_spotlight_manager.mm
@@ -7,7 +7,6 @@
 #import <CommonCrypto/CommonCrypto.h>
 #import <MobileCoreServices/MobileCoreServices.h>
 
-#include "base/ios/weak_nsobject.h"
 #include "base/mac/bind_objc_block.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/task/cancelable_task_tracker.h"
@@ -23,6 +22,10 @@
 #include "skia/ext/skia_utils_ios.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 // Minimum size of the icon to be used in Spotlight.
 const NSInteger kMinIconSize = 32;
@@ -48,7 +51,7 @@
   base::CancelableTaskTracker _largeIconTaskTracker;
 
   // Dictionary to track the tasks querying the large icons.
-  base::scoped_nsobject<NSMutableDictionary> _pendingTasks;
+  NSMutableDictionary* _pendingTasks;
 }
 
 // Compute a hash consisting of the first 8 bytes of the MD5 hash of a string
@@ -75,7 +78,7 @@
   if (self) {
     _spotlightDomain = domain;
     _largeIconService = largeIconService;
-    _pendingTasks.reset([[NSMutableDictionary alloc] init]);
+    _pendingTasks = [[NSMutableDictionary alloc] init];
   }
   return self;
 }
@@ -117,21 +120,20 @@
 - (CSSearchableItem*)spotlightItemWithItemID:(NSString*)itemID
                                 attributeSet:(CSSearchableItemAttributeSet*)
                                                  attributeSet {
-  CSCustomAttributeKey* key = [[[CSCustomAttributeKey alloc]
+  CSCustomAttributeKey* key = [[CSCustomAttributeKey alloc]
           initWithKeyName:spotlight::GetSpotlightCustomAttributeItemID()
                searchable:YES
       searchableByDefault:YES
                    unique:YES
-              multiValued:NO] autorelease];
+              multiValued:NO];
   [attributeSet setValue:itemID forCustomKey:key];
   attributeSet.keywords = [self keywordsForSpotlightItems];
 
   NSString* domainID = spotlight::StringFromSpotlightDomain(_spotlightDomain);
 
-  return [[[CSSearchableItem alloc] initWithUniqueIdentifier:itemID
-                                            domainIdentifier:domainID
-                                                attributeSet:attributeSet]
-      autorelease];
+  return [[CSSearchableItem alloc] initWithUniqueIdentifier:itemID
+                                           domainIdentifier:domainID
+                                               attributeSet:attributeSet];
 }
 
 - (NSArray*)spotlightItemsWithURL:(const GURL&)indexedURL
@@ -143,9 +145,9 @@
                                 ? indexedURL.GetOrigin().spec()
                                 : indexedURL.spec();
 
-  base::scoped_nsobject<CSSearchableItemAttributeSet> attributeSet(
+  CSSearchableItemAttributeSet* attributeSet =
       [[CSSearchableItemAttributeSet alloc]
-          initWithItemContentType:(NSString*)kUTTypeURL]);
+          initWithItemContentType:(NSString*)kUTTypeURL];
   [attributeSet setTitle:defaultTitle];
   [attributeSet setDisplayName:defaultTitle];
   [attributeSet setURL:nsURL];
@@ -174,11 +176,10 @@
   font = [font fontWithSize:(kFallbackIconSize / 2)];
   CGRect textRect = CGRectMake(0, (kFallbackIconSize - [font lineHeight]) / 2,
                                kFallbackIconSize, [font lineHeight]);
-  base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
-      [[NSMutableParagraphStyle alloc] init]);
+  NSMutableParagraphStyle* paragraphStyle =
+      [[NSMutableParagraphStyle alloc] init];
   [paragraphStyle setAlignment:NSTextAlignmentCenter];
-  base::scoped_nsobject<NSMutableDictionary> attributes(
-      [[NSMutableDictionary alloc] init]);
+  NSMutableDictionary* attributes = [[NSMutableDictionary alloc] init];
   [attributes setValue:font forKey:NSFontAttributeName];
   [attributes setValue:textColor forKey:NSForegroundColorAttributeName];
   [attributes setValue:paragraphStyle forKey:NSParagraphStyleAttributeName];
@@ -196,15 +197,15 @@
     return;
   }
 
-  base::WeakNSObject<BaseSpotlightManager> weakSelf(self);
+  __weak BaseSpotlightManager* weakSelf = self;
   GURL URL = URLToRefresh;
   void (^faviconBlock)(const favicon_base::LargeIconResult&) = ^(
       const favicon_base::LargeIconResult& result) {
-    base::scoped_nsobject<BaseSpotlightManager> strongSelf([weakSelf retain]);
+    BaseSpotlightManager* strongSelf = weakSelf;
     if (!strongSelf) {
       return;
     }
-    [strongSelf.get()->_pendingTasks removeObjectForKey:NSURL];
+    [strongSelf->_pendingTasks removeObjectForKey:NSURL];
     UIImage* favicon;
     if (result.bitmap.is_valid()) {
       scoped_refptr<base::RefCountedMemory> data =
@@ -237,7 +238,7 @@
       _largeIconService->GetLargeIconOrFallbackStyle(
           URL, kMinIconSize * [UIScreen mainScreen].scale,
           kIconSize * [UIScreen mainScreen].scale,
-          base::BindBlock(faviconBlock), &_largeIconTaskTracker);
+          base::BindBlockArc(faviconBlock), &_largeIconTaskTracker);
   [_pendingTasks setObject:[NSNumber numberWithLongLong:taskID] forKey:NSURL];
 }
 
diff --git a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h
index 31534ed..30e46e2 100644
--- a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h
+++ b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.h
@@ -29,7 +29,7 @@
 @interface BookmarksSpotlightManager : BaseSpotlightManager
 
 // The delegate notified when a bookmark is updated.
-@property(nonatomic, assign) id<BookmarkUpdatedDelegate> delegate;
+@property(nonatomic, weak) id<BookmarkUpdatedDelegate> delegate;
 
 + (BookmarksSpotlightManager*)bookmarksSpotlightManagerWithBrowserState:
     (ios::ChromeBrowserState*)browserState;
diff --git a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm
index 7cee4eb9..c096c432 100644
--- a/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm
+++ b/ios/chrome/app/spotlight/bookmarks_spotlight_manager.mm
@@ -8,7 +8,6 @@
 
 #import <CoreSpotlight/CoreSpotlight.h>
 
-#include "base/ios/weak_nsobject.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/version.h"
@@ -17,6 +16,10 @@
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 // Limit the size of the initial indexing. This will not limit the size of the
 // index as new bookmarks can be added afterwards.
@@ -31,7 +34,7 @@
 
 // Called from the BrowserBookmarkModelBridge from C++ -> ObjC.
 @interface BookmarksSpotlightManager () {
-  base::WeakNSProtocol<id<BookmarkUpdatedDelegate>> _delegate;
+  __weak id<BookmarkUpdatedDelegate> _delegate;
 
   // Bridge to register for bookmark changes.
   std::unique_ptr<SpotlightBookmarkModelBridge> _bookmarkModelBridge;
@@ -141,18 +144,18 @@
   };
 
  private:
-  __unsafe_unretained BookmarksSpotlightManager* owner_;  // Weak.
+  __weak BookmarksSpotlightManager* owner_;
 };
 
 @implementation BookmarksSpotlightManager
 
 + (BookmarksSpotlightManager*)bookmarksSpotlightManagerWithBrowserState:
     (ios::ChromeBrowserState*)browserState {
-  return [[[BookmarksSpotlightManager alloc]
+  return [[BookmarksSpotlightManager alloc]
       initWithLargeIconService:IOSChromeLargeIconServiceFactory::
                                    GetForBrowserState(browserState)
                  bookmarkModel:ios::BookmarkModelFactory::GetForBrowserState(
-                                   browserState)] autorelease];
+                                   browserState)];
 }
 
 - (instancetype)
@@ -170,7 +173,6 @@
 
 - (void)dealloc {
   [self detachBookmarkModel];
-  [super dealloc];
 }
 
 - (void)detachBookmarkModel {
@@ -186,7 +188,7 @@
 }
 
 - (void)setDelegate:(id<BookmarkUpdatedDelegate>)delegate {
-  _delegate.reset(delegate);
+  _delegate = delegate;
 }
 
 - (void)getParentKeywordsForNode:(const bookmarks::BookmarkNode*)node
@@ -205,7 +207,7 @@
     GURL url(node->url());
     NSString* title = base::SysUTF16ToNSString(node->GetTitle());
     NSString* spotlightID = [self spotlightIDForURL:url title:title];
-    base::WeakNSObject<BookmarksSpotlightManager> weakself(self);
+    __weak BookmarksSpotlightManager* weakself = self;
     BlockWithError completion = ^(NSError* error) {
       dispatch_async(dispatch_get_main_queue(), ^{
         [weakself refreshItemsWithURL:url title:nil];
@@ -284,8 +286,7 @@
 - (NSArray*)spotlightItemsWithURL:(const GURL&)URL
                           favicon:(UIImage*)favicon
                      defaultTitle:(NSString*)defaultTitle {
-  base::scoped_nsobject<NSMutableDictionary> spotlightItems(
-      [[NSMutableDictionary alloc] init]);
+  NSMutableDictionary* spotlightItems = [[NSMutableDictionary alloc] init];
   std::vector<const bookmarks::BookmarkNode*> nodes;
   _bookmarkModel->GetNodesByURL(URL, &nodes);
   for (auto node : nodes) {
@@ -297,9 +298,8 @@
                                    favicon:favicon
                               defaultTitle:nodeTitle] objectAtIndex:0];
     }
-    base::scoped_nsobject<NSMutableArray> nodeKeywords(
-        [[NSMutableArray alloc] init]);
-    [self getParentKeywordsForNode:node inArray:nodeKeywords.get()];
+    NSMutableArray* nodeKeywords = [[NSMutableArray alloc] init];
+    [self getParentKeywordsForNode:node inArray:nodeKeywords];
     [self addKeywords:nodeKeywords toSearchableItem:item];
     [spotlightItems setObject:item forKey:spotlightID];
   }
@@ -308,20 +308,18 @@
 
 - (void)clearAndReindexModel {
   [self cancelAllLargeIconPendingTasks];
-  base::WeakNSObject<BookmarksSpotlightManager> weakself(self);
+  __weak BookmarksSpotlightManager* weakself = self;
   BlockWithError completion = ^(NSError* error) {
     if (!error) {
       dispatch_async(dispatch_get_main_queue(), ^{
-        base::scoped_nsobject<BookmarksSpotlightManager> strongSelf(
-            [weakself retain]);
+        BookmarksSpotlightManager* strongSelf = weakself;
         if (!strongSelf)
           return;
 
         NSDate* startOfReindexing = [NSDate date];
-        strongSelf.get()->_nodesIndexed = 0;
-        [strongSelf
-            refreshNodeInIndex:strongSelf.get()->_bookmarkModel->root_node()
-                       initial:YES];
+        strongSelf->_nodesIndexed = 0;
+        [strongSelf refreshNodeInIndex:strongSelf->_bookmarkModel->root_node()
+                               initial:YES];
         NSDate* endOfReindexing = [NSDate date];
         NSTimeInterval indexingDuration =
             [endOfReindexing timeIntervalSinceDate:startOfReindexing];
diff --git a/ios/chrome/app/spotlight/spotlight_manager.mm b/ios/chrome/app/spotlight/spotlight_manager.mm
index b4d05739..3baf66b 100644
--- a/ios/chrome/app/spotlight/spotlight_manager.mm
+++ b/ios/chrome/app/spotlight/spotlight_manager.mm
@@ -5,17 +5,20 @@
 #import "ios/chrome/app/spotlight/spotlight_manager.h"
 
 #include "base/logging.h"
-#include "base/mac/scoped_nsobject.h"
 #include "ios/chrome/app/spotlight/actions_spotlight_manager.h"
 #include "ios/chrome/app/spotlight/bookmarks_spotlight_manager.h"
 #include "ios/chrome/app/spotlight/topsites_spotlight_manager.h"
 #include "ios/chrome/browser/experimental_flags.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 // Called from the BrowserBookmarkModelBridge from C++ -> ObjC.
 @interface SpotlightManager ()<BookmarkUpdatedDelegate> {
-  base::scoped_nsobject<BookmarksSpotlightManager> _bookmarkManager;
-  base::scoped_nsobject<TopSitesSpotlightManager> _topSitesManager;
-  base::scoped_nsobject<ActionsSpotlightManager> _actionsManager;
+  BookmarksSpotlightManager* _bookmarkManager;
+  TopSitesSpotlightManager* _topSitesManager;
+  ActionsSpotlightManager* _actionsManager;
 }
 
 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
@@ -29,8 +32,7 @@
 + (SpotlightManager*)spotlightManagerWithBrowserState:
     (ios::ChromeBrowserState*)browserState {
   if (spotlight::IsSpotlightAvailable()) {
-    return [[[SpotlightManager alloc] initWithBrowserState:browserState]
-        autorelease];
+    return [[SpotlightManager alloc] initWithBrowserState:browserState];
   }
   return nil;
 }
@@ -39,13 +41,12 @@
   DCHECK(spotlight::IsSpotlightAvailable());
   self = [super init];
   if (self) {
-    _topSitesManager.reset([[TopSitesSpotlightManager
-        topSitesSpotlightManagerWithBrowserState:browserState] retain]);
-    _bookmarkManager.reset([[BookmarksSpotlightManager
-        bookmarksSpotlightManagerWithBrowserState:browserState] retain]);
+    _topSitesManager = [TopSitesSpotlightManager
+        topSitesSpotlightManagerWithBrowserState:browserState];
+    _bookmarkManager = [BookmarksSpotlightManager
+        bookmarksSpotlightManagerWithBrowserState:browserState];
     [_bookmarkManager setDelegate:self];
-    _actionsManager.reset(
-        [[ActionsSpotlightManager actionsSpotlightManager] retain]);
+    _actionsManager = [ActionsSpotlightManager actionsSpotlightManager];
   }
   return self;
 }
@@ -55,9 +56,6 @@
   return nil;
 }
 
-- (void)dealloc {
-  [super dealloc];
-}
 
 - (void)resyncIndex {
   [_bookmarkManager reindexBookmarksIfNeeded];
diff --git a/ios/chrome/app/spotlight/spotlight_util.mm b/ios/chrome/app/spotlight/spotlight_util.mm
index fd33c146..6bd9e55 100644
--- a/ios/chrome/app/spotlight/spotlight_util.mm
+++ b/ios/chrome/app/spotlight/spotlight_util.mm
@@ -12,6 +12,10 @@
 #include "ios/public/provider/chrome/browser/spotlight/spotlight_provider.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 // This enum is used for Histogram. Items should not be removed or reordered and
 // this enum should be kept synced with histograms.xml.
diff --git a/ios/chrome/app/spotlight/topsites_spotlight_manager.mm b/ios/chrome/app/spotlight/topsites_spotlight_manager.mm
index 33bb2315..58b45fe 100644
--- a/ios/chrome/app/spotlight/topsites_spotlight_manager.mm
+++ b/ios/chrome/app/spotlight/topsites_spotlight_manager.mm
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/ios/weak_nsobject.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/bookmarks/browser/bookmark_model.h"
@@ -23,6 +22,10 @@
 #include "ios/chrome/browser/sync/sync_observer_bridge.h"
 #include "ios/chrome/browser/ui/ntp/google_landing_controller.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 class SpotlightTopSitesBridge;
 class SpotlightTopSitesCallbackBridge;
 class SpotlightSuggestionsBridge;
@@ -97,7 +100,7 @@
   }
 
  private:
-  __unsafe_unretained TopSitesSpotlightManager* owner_;  // weak, owns us
+  __weak TopSitesSpotlightManager* owner_;
 };
 
 class SpotlightTopSitesBridge : public history::TopSitesObserver {
@@ -119,7 +122,7 @@
   }
 
  private:
-  __unsafe_unretained TopSitesSpotlightManager* owner_;  // weak
+  __weak TopSitesSpotlightManager* owner_;
 };
 
 class SpotlightSuggestionsBridge
@@ -136,7 +139,7 @@
   }
 
  private:
-  __unsafe_unretained TopSitesSpotlightManager* owner_;  // weak, owns us
+  __weak TopSitesSpotlightManager* owner_;
 };
 
 @implementation TopSitesSpotlightManager
@@ -144,7 +147,7 @@
 
 + (TopSitesSpotlightManager*)topSitesSpotlightManagerWithBrowserState:
     (ios::ChromeBrowserState*)browserState {
-  return [[[TopSitesSpotlightManager alloc]
+  return [[TopSitesSpotlightManager alloc]
       initWithLargeIconService:IOSChromeLargeIconServiceFactory::
                                    GetForBrowserState(browserState)
                       topSites:ios::TopSitesFactory::GetForBrowserState(
@@ -154,8 +157,7 @@
             profileSyncService:IOSChromeProfileSyncServiceFactory::
                                    GetForBrowserState(browserState)
             suggestionsService:suggestions::SuggestionsServiceFactory::
-                                   GetForBrowserState(browserState)]
-      autorelease];
+                                   GetForBrowserState(browserState)];
 }
 
 - (instancetype)
@@ -186,7 +188,7 @@
 }
 
 - (void)updateAllTopSitesSpotlightItems {
-  base::WeakNSObject<TopSitesSpotlightManager> weakSelf(self);
+  __weak TopSitesSpotlightManager* weakSelf = self;
   [self clearAllSpotlightItems:^(NSError* error) {
     dispatch_async(dispatch_get_main_queue(), ^{
       [weakSelf addAllTopSitesSpotlightItems];
@@ -269,12 +271,16 @@
     return;
   }
   _isReindexPending = true;
-  base::WeakNSObject<TopSitesSpotlightManager> weakSelf(self);
+  __weak TopSitesSpotlightManager* weakSelf = self;
   dispatch_after(
       dispatch_time(DISPATCH_TIME_NOW, static_cast<int64_t>(1 * NSEC_PER_SEC)),
       dispatch_get_main_queue(), ^{
-        [weakSelf updateAllTopSitesSpotlightItems];
-        weakSelf.get()->_isReindexPending = false;
+        TopSitesSpotlightManager* strongSelf = weakSelf;
+        if (!strongSelf) {
+          return;
+        }
+        [strongSelf updateAllTopSitesSpotlightItems];
+        strongSelf->_isReindexPending = false;
       });
 }
 
diff --git a/ios/chrome/browser/reading_list/reading_list_distiller_page.mm b/ios/chrome/browser/reading_list/reading_list_distiller_page.mm
index b456e90..e774a3c2 100644
--- a/ios/chrome/browser/reading_list/reading_list_distiller_page.mm
+++ b/ios/chrome/browser/reading_list/reading_list_distiller_page.mm
@@ -72,6 +72,20 @@
   FetchFavicon(url);
 
   DistillerPageIOS::DistillPageImpl(url, script);
+
+  // WKWebView sets the document.hidden property to true and the
+  // document.visibilityState to prerender if the page is not added to a view
+  // hierarchy. Some pages may not render their content in these conditions.
+  // Add the view and move it out of the screen far in the top left corner of
+  // the coordinate space.
+  CGRect frame = [[[UIApplication sharedApplication] keyWindow] frame];
+  frame.origin.x = -5 * std::max(frame.size.width, frame.size.height);
+  frame.origin.y = frame.origin.x;
+  DCHECK(![CurrentWebState()->GetView() superview]);
+  [CurrentWebState()->GetView() setFrame:frame];
+  [[[UIApplication sharedApplication] keyWindow]
+      insertSubview:CurrentWebState()->GetView()
+            atIndex:0];
 }
 
 void ReadingListDistillerPage::FetchFavicon(const GURL& page_url) {
@@ -88,6 +102,7 @@
                                                   const base::Value* value) {
   std::unique_ptr<web::WebState> old_web_state = DetachWebState();
   if (old_web_state) {
+    [old_web_state->GetView() removeFromSuperview];
     web_state_dispatcher_->ReturnWebState(std::move(old_web_state));
   }
   DistillerPageIOS::OnDistillationDone(page_url, value);
diff --git a/ios/chrome/browser/reading_list/reading_list_download_service.cc b/ios/chrome/browser/reading_list/reading_list_download_service.cc
index 7b9c4f5..e44d1a7d 100644
--- a/ios/chrome/browser/reading_list/reading_list_download_service.cc
+++ b/ios/chrome/browser/reading_list/reading_list_download_service.cc
@@ -235,43 +235,46 @@
     const base::FilePath& distilled_path,
     const std::string& title) {
   DCHECK(reading_list_model_->loaded());
-  if ((success == URLDownloader::DOWNLOAD_SUCCESS ||
-       success == URLDownloader::DOWNLOAD_EXISTS) &&
-      !distilled_path.empty()) {
-    reading_list_model_->SetEntryDistilledInfo(url, distilled_path,
-                                               distilled_url);
+  URLDownloader::SuccessState real_success_value = success;
+  if (distilled_path.empty()) {
+    real_success_value = URLDownloader::ERROR;
+  }
+  switch (real_success_value) {
+    case URLDownloader::DOWNLOAD_SUCCESS:
+    case URLDownloader::DOWNLOAD_EXISTS: {
+      reading_list_model_->SetEntryDistilledInfo(url, distilled_path,
+                                                 distilled_url);
 
-    std::string trimmed_title = base::CollapseWhitespaceASCII(title, false);
-    if (!trimmed_title.empty())
-      reading_list_model_->SetEntryTitle(url, trimmed_title);
+      std::string trimmed_title = base::CollapseWhitespaceASCII(title, false);
+      if (!trimmed_title.empty())
+        reading_list_model_->SetEntryTitle(url, trimmed_title);
 
-    const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
-    if (entry)
-      UMA_HISTOGRAM_COUNTS_100("ReadingList.Download.Failures",
-                               entry->FailedDownloadCounter());
-    UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", SUCCESS,
-                              STATUS_MAX);
-
-  } else if (success == URLDownloader::ERROR_RETRY) {
-    reading_list_model_->SetEntryDistilledState(url,
-                                                ReadingListEntry::WILL_RETRY);
-    ScheduleDownloadEntry(url);
-
-    const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
-    if (entry) {
-      if (entry->FailedDownloadCounter() < kNumberOfFailsBeforeStop) {
+      const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
+      if (entry)
+        UMA_HISTOGRAM_COUNTS_100("ReadingList.Download.Failures",
+                                 entry->FailedDownloadCounter());
+      UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", SUCCESS,
+                                STATUS_MAX);
+      break;
+    }
+    case URLDownloader::ERROR: {
+      const ReadingListEntry* entry = reading_list_model_->GetEntryByURL(url);
+      // Add this failure to the total failure count.
+      if (entry &&
+          entry->FailedDownloadCounter() + 1 < kNumberOfFailsBeforeStop) {
+        reading_list_model_->SetEntryDistilledState(
+            url, ReadingListEntry::WILL_RETRY);
+        ScheduleDownloadEntry(url);
         UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", RETRY,
                                   STATUS_MAX);
       } else {
         UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", FAILURE,
                                   STATUS_MAX);
+        reading_list_model_->SetEntryDistilledState(url,
+                                                    ReadingListEntry::ERROR);
       }
+      break;
     }
-
-  } else if (success == URLDownloader::ERROR_PERMANENT) {
-    reading_list_model_->SetEntryDistilledState(url, ReadingListEntry::ERROR);
-    UMA_HISTOGRAM_ENUMERATION("ReadingList.Download.Status", FAILURE,
-                              STATUS_MAX);
   }
 }
 
diff --git a/ios/chrome/browser/reading_list/url_downloader.cc b/ios/chrome/browser/reading_list/url_downloader.cc
index b73616b..d458867 100644
--- a/ios/chrome/browser/reading_list/url_downloader.cc
+++ b/ios/chrome/browser/reading_list/url_downloader.cc
@@ -112,7 +112,7 @@
       base::Unretained(this), url, title, offline_path, success);
 
   // If downloading failed, clean up any partial download.
-  if (success == ERROR_RETRY || success == ERROR_PERMANENT) {
+  if (success == ERROR) {
     base::FilePath directory_path =
         reading_list::OfflineURLDirectoryAbsolutePath(base_directory_, url);
     task_tracker_.PostTaskAndReply(
@@ -202,7 +202,7 @@
     fetcher_->GetResponseHeaders()->GetMimeType(&mime_type);
   }
   if (!fetcher_->GetStatus().is_success() || mime_type != mime_type_) {
-    return DownloadCompletionHandler(original_url_, "", path, ERROR_RETRY);
+    return DownloadCompletionHandler(original_url_, "", path, ERROR);
   }
   base::FilePath temporary_path;
   // Do not take ownership of the file until the file is moved. This ensures
@@ -240,11 +240,11 @@
     if (base::Move(temporary_path, absolute_path)) {
       return DOWNLOAD_SUCCESS;
     } else {
-      return ERROR_PERMANENT;
+      return ERROR;
     }
   }
 
-  return ERROR_PERMANENT;
+  return ERROR;
 }
 
 void URLDownloader::DistillerCallback(
@@ -262,8 +262,7 @@
       return;
     }
     // This content cannot be processed, return an error value to the client.
-    DownloadCompletionHandler(page_url, std::string(), base::FilePath(),
-                              ERROR_RETRY);
+    DownloadCompletionHandler(page_url, std::string(), base::FilePath(), ERROR);
     return;
   }
 
@@ -288,9 +287,9 @@
   if (CreateOfflineURLDirectory(url)) {
     return SaveHTMLForURL(SaveAndReplaceImagesInHTML(url, html, images), url)
                ? DOWNLOAD_SUCCESS
-               : ERROR_PERMANENT;
+               : ERROR;
   }
-  return ERROR_PERMANENT;
+  return ERROR;
 }
 
 bool URLDownloader::CreateOfflineURLDirectory(const GURL& url) {
diff --git a/ios/chrome/browser/reading_list/url_downloader.h b/ios/chrome/browser/reading_list/url_downloader.h
index 862df2a..793bd3c 100644
--- a/ios/chrome/browser/reading_list/url_downloader.h
+++ b/ios/chrome/browser/reading_list/url_downloader.h
@@ -48,12 +48,9 @@
     DOWNLOAD_SUCCESS,
     // The URL was already available offline. No action was done.
     DOWNLOAD_EXISTS,
-    // The URL could not be downloaded because of a temporary error. Client may
-    // want to try again later.
-    ERROR_RETRY,
-    // The URL could not be dowmloaded and URLDownloader thinks a retry would
-    // end with the same result. There is no need to retry.
-    ERROR_PERMANENT
+    // The URL could not be downloaded because of an error. Client may want to
+    // try again later.
+    ERROR,
   };
 
   // A completion callback that takes a GURL and a bool indicating the
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm
index 1c01fe30..96a88858 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.mm
@@ -357,8 +357,8 @@
   self.nameItem.delegate = self;
   [model addItem:self.nameItem toSectionWithIdentifier:SectionIdentifierInfo];
 
-  self.folderItem =
-      [[BookmarkParentFolderItem alloc] initWithType:ItemTypeFolder];
+  self.folderItem = [[[BookmarkParentFolderItem alloc]
+      initWithType:ItemTypeFolder] autorelease];
   self.folderItem.title = bookmark_utils_ios::TitleForBookmarkNode(self.folder);
   [model addItem:self.folderItem toSectionWithIdentifier:SectionIdentifierInfo];
 
diff --git a/ios/clean/chrome/browser/ui/commands/tab_commands.h b/ios/clean/chrome/browser/ui/commands/tab_commands.h
index 0f62ecb..6094c6ca 100644
--- a/ios/clean/chrome/browser/ui/commands/tab_commands.h
+++ b/ios/clean/chrome/browser/ui/commands/tab_commands.h
@@ -15,6 +15,9 @@
 // Display the tab corresponding to |indexPath|. The receiver determines how
 // this correspondence relates to the tab model(s) it knows about.
 - (void)showTabAtIndexPath:(NSIndexPath*)indexPath;
+
+// Remove tab from the tab model(s) the receiver knows about.
+- (void)closeTabAtIndexPath:(NSIndexPath*)indexPath;
 @end
 
 #endif  // IOS_CLEAN_CHROME_BROWSER_UI_COMMANDS_TAB_COMMANDS_H_
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index 51a42f85..8fd156fa 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -108,6 +108,12 @@
   _activeWebStateIndex = index;
 }
 
+- (void)closeTabAtIndexPath:(NSIndexPath*)indexPath {
+  size_t index = static_cast<size_t>(indexPath.item);
+  DCHECK(index < _webStates.size());
+  _webStates.erase(_webStates.begin() + index);
+}
+
 #pragma mark - TabGridCommands
 
 - (void)showTabGrid {
diff --git a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index e5a8980..6296bbe1 100644
--- a/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/clean/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -157,7 +157,12 @@
 }
 
 - (void)deleteButtonPressedForCell:(UICollectionViewCell*)cell {
-  // PLACEHOLDER: handle close tab button.
+  auto updateBlock = ^{
+    NSIndexPath* indexPath = [self.grid indexPathForCell:cell];
+    [self.tabCommandHandler closeTabAtIndexPath:indexPath];
+    [self.grid deleteItemsAtIndexPaths:@[ indexPath ]];
+  };
+  [self.grid performBatchUpdates:updateBlock completion:nil];
 }
 
 @end
diff --git a/ios/showcase/README.md b/ios/showcase/README.md
new file mode 100644
index 0000000..2f985f3
--- /dev/null
+++ b/ios/showcase/README.md
@@ -0,0 +1,221 @@
+# Chrome for iOS Showcase development app
+
+This folder holds the code for a dev-only, standalone app for Chrome for iOS
+development. It showcases (and is restricted to) UI elements used and developed
+for Chrome for iOS.
+Goals for this app are to be as simple, as easy to maintain, and as useful as
+possible.
+
+## Detailed Design
+
+This is a standalone app that is built by the bots, much like `ios_web_shell`
+and `chrome_clean_skeleton`.
+
+### src/ios/showcase
+
+```
+ios/chrome/app:app
+ios/chrome/app:chrome_clean_skeleton
+ios/showcase:showcase
+ios/showcase:all_tests
+ios/web/shell:ios_web_shell
+```
+
+Much like `experimental/`, the app lives in its own folder. It depends on
+Chrome UI code for the production code, but the architecture of the Showcase app
+is separate.
+
+### Language and build
+
+* **Objective-C++** needed to interact with the view controller classes likely
+  to be in Objective-C++ as well.
+
+* **ARC**
+
+* **GN and Ninja.** The showcase and `showcase:all_tests` targets are linked to
+  `gn_all`.
+
+### Features
+
+* **Class and use cases**
+Table of use cases demoing view controller classes under different sets of entry
+data. There can be several use cases for the same class so each gets an entry.
+Cells on homepage display the use case name and the class name of the view
+controller they link to.
+
+* **Search**
+Search box at the top to filter the cells based on the class and use case name.
+
+* **Simple, tailor-made coordinators**
+Coordinators handle flow, so Showcase shouldn't host any of Chrome's
+coordinators. Instead, simple and lightweight coordinators will be used in
+Showcase. They will handle the initialization of a production view controller,
+and setup all mock data needed to display this view controller.
+
+### Isolation from Chrome
+
+View controllers in the New Architecture shouldn't need the BrowserProfile, etc.
+So mocking the inputs and outputs of a single VC should be easy and not require
+the core of Chrome.
+
+### Non-goals
+
+* ~~Table views with TableViewModel/CollectionViewModel?~~
+    * We want to make the app as small and simple as possible. The fewer
+      dependencies the better.
+
+* ~~Can we configure from within the app what these inputs and outputs are?~~
+    * Not desirable. Too complex for what we want to achieve.
+
+## How do I showcase a Chrome UI feature?
+
+The following nomenclature is used:
+
+* A **feature** is a Chrome UI feature such as a full-screen or partial-screen
+  view controller, a cell, a view, or a UI control (such as a custom button).
+
+### To add a feature to Showcase
+
+1. Add an entry to the Showcase configuration file, which requires 3 pieces of
+   information:
+
+    1. **_ClassForDisplay_** - The UI feature that you want to showcase, such
+       as a SettingsViewController, or AccountCell, or TabContainer. It appears
+       as the title of the cell in Showcase.
+
+        1. **_ClassForInstantiation_** - The actual class that is instantiated
+           by Showcase. This is either a view controller or a custom
+           coordinator. (*More information below*).
+
+    2. **_UseCase_** - A short description that is helpful to the user about
+       what is being showcased.
+
+    ```
+    @{
+      showcase::kClassForDisplayKey : @"SettingsViewController",
+      showcase::kClassForInstantiationKey : @"SettingsCoordinator",
+      showcase::kUseCaseKey : @"Main settings screen",
+    },
+    ```
+
+2. Add the target that contains *ClassForInstantiation* to `showcase/BUILD.gn`.
+
+    ```
+    group("features") {
+      deps = [
+        "//ios/chrome/browser/ui/tools:tools_ui",
+        "//ios/showcase/settings",
+        "//ios/showcase/tab_bottom",
+        "//ios/showcase/tab_grid",
+        "//ios/showcase/tab_top",
+        "//ios/showcase/uikit_table_view_cell",
+        # Insert additional feature targets here.
+      ]
+    }
+    ```
+
+3. Add the target that contains Earl Grey tests (if any) to `showcase/BUILD.gn`.
+
+    ```
+    ios_eg_test("ios_showcase_egtests") {
+      deps = [
+        "//ios/showcase/core:eg_tests",
+        "//ios/showcase/tab_grid:eg_tests",
+        # Insert additional feature eg_tests targets here.
+      ]
+    }
+    ```
+
+### More on ClassForInstantiation
+
+There are 3 scenarios for adding features to Showcase:
+
+* Directly use the ClassForDisplay when it can be fully initialized with a call
+  to `-init`.
+
+    ```
+    showcase::kClassForDisplayKey : @"FeatureViewController",
+    showcase::kClassForInstantiationKey : @"FeatureViewController",
+    ```
+
+* Use a custom coordinator when you need to showcase a view controller that
+  requires special initialization or setup (e.g., requires model objects).
+
+    ```
+    showcase::kClassForDisplayKey : @"FeatureViewController",
+    showcase::kClassForInstantiationKey : @"FeatureCoordinator",
+    ```
+
+* Use a custom view controller when you need to showcase a cell, view, or UI
+  control.
+
+    ```
+    showcase::kClassForDisplayKey : @"FeatureView",
+    showcase::kClassForInstantiationKey : @"FeatureViewViewController",
+    ```
+
+### How to create a custom coordinator
+
+See example: `SettingsCoordinator - Main settings screen`
+
+1. Create a folder for `/showcase/feature/`.
+
+2. Create `feature_use_case_coordinator.h|mm`.
+
+    * Must conform to the `Coordinator` protocol provided under
+      `/showcase/common/`.
+
+    * Must support being initialized with `-init`.
+
+    * In the `-start` method, instantiate and setup your `FeatureViewController`
+      with all the mock data necessary to recreate the use case you are
+      showcasing. Then the view controller is pushed onto the navigation
+      controller.
+
+3. Create `/showcase/feature/BUILD.gn`.
+
+    ```
+    source_set("feature) {
+      sources = [
+        "feature_use_case_coordinator.h",
+        "feature_use_case_coordinator.mm",
+      ]
+      deps = [
+        "//ios/showcase/common",
+        # Insert target for ClassForDisplay here.
+      ]
+      libs = [ "UIKit.framework" ]
+      configs += [ "//build/config/compiler:enable_arc" ]
+    }
+    ```
+
+### How to showcase a view (not view controller)
+
+See example: `UIKitTableViewCellViewController - UIKit Table Cells`
+
+You will need a glue view controller.
+
+1. Create a folder for `/showcase/feature_view/`.
+
+2. Create `feature_view_view_controller.h|mm`.
+
+    1. Must support being initialized with `-init`.
+
+    2. Add your view to the view controller and set it up the way you want
+       (usually in `-viewDidLoad`).
+
+3. Create `/showcase/feature/BUILD.gn`.
+
+    ```
+    source_set("feature) {
+      sources = [
+        "feature_view_view_controller.h",
+        "feature_view_view_controller.mm",
+      ]
+      deps = [
+        # Insert target for ClassForDisplay here.
+      ]
+      libs = [ "UIKit.framework" ]
+      configs += [ "//build/config/compiler:enable_arc" ]
+    }
+    ```
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
index 20de8a1..fa4bb572 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -8,10 +8,7 @@
 crbug.com/551000 http/tests/inspector/console-resource-errors.html [ Failure ]
 crbug.com/551000 virtual/mojo-loading/http/tests/inspector/console-resource-errors.html [ Failure ]
 
-#  Forward redirect info to the renderer. Fixed by https://codereview.chromium.org/2653953005/.
-crbug.com/551000 http/tests/inspector/extensions-network-redirect.html [ Timeout ]
-crbug.com/551000 virtual/mojo-loading/http/tests/inspector/extensions-network-redirect.html [ Timeout ]
-#  These ones have an additional issue with a flipped order between diStartProvisionalLoad & willSendRequest
+# Flipped order between diStartProvisionalLoad & willSendRequest
 crbug.com/625765 virtual/mojo-loading/http/tests/loading/redirect-methods.html [ Crash Failure ]
 crbug.com/625765 http/tests/loading/redirect-methods.html [ Crash Failure ]
 
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f4f1d110..e7457a2 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -145,6 +145,10 @@
 crbug.com/681471 paint/invalidation/media-audio-no-spurious-repaints.html [ Failure Pass Timeout ]
 crbug.com/681471 virtual/disable-spinvalidation/paint/invalidation/media-audio-no-spurious-repaints.html [ Failure Pass Timeout ]
 
+# Added 2017-02-20
+crbug.com/693510 compositing/reflections/nested-reflection-anchor-point.html [ Failure Pass ]
+crbug.com/693510 compositing/reflections/nested-reflection-animated.html [ Failure Pass ]
+
 # ====== Paint team owned tests to here ======
 
 # ====== LayoutNG-only failures from here ======
@@ -1918,6 +1922,7 @@
 crbug.com/626703 external/wpt/streams/writable-streams/close.html [ Timeout ]
 crbug.com/626703 external/wpt/streams/writable-streams/close.serviceworker.https.html [ Timeout ]
 crbug.com/626703 external/wpt/service-workers/service-worker/registration-useCache.https.html [ Timeout ]
+crbug.com/626703 external/wpt/service-workers/service-worker/multi-globals/url-parsing.https.html [ Pass Failure ]
 crbug.com/626703 external/wpt/streams/writable-streams/close.sharedworker.html [ Timeout ]
 crbug.com/626703 external/wpt/html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html [ Timeout ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/deleteFromDocument-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/deleteFromDocument-expected.txt
deleted file mode 100644
index 86c25d5..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/deleteFromDocument-expected.txt
+++ /dev/null
@@ -1,101 +0,0 @@
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-CONSOLE ERROR: line 66: The given range isn't in document.
-This is a testharness.js-based test.
-Found 60 tests; 38 PASS, 22 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS Selection.prototype.deleteFromDocument.length must equal 0 
-PASS Range 0: empty 
-PASS Range 1: [paras[0].firstChild, 0, paras[0].firstChild, 0] 
-FAIL Range 2: [paras[0].firstChild, 0, paras[0].firstChild, 1] assert_true: First differing node: expected Text node "̈b̈c̈d̈ëf̈g̈ḧ
-", got Text node "b̈c̈d̈ëf̈g̈ḧ
-" expected true got false
-PASS Range 3: [paras[0].firstChild, 2, paras[0].firstChild, 8] 
-FAIL Range 4: [paras[0].firstChild, 2, paras[0].firstChild, 9] assert_true: First differing node: expected Text node "Ä̈f̈g̈ḧ
-", got Text node "Äf̈g̈ḧ
-" expected true got false
-PASS Range 5: [paras[1].firstChild, 0, paras[1].firstChild, 0] 
-FAIL Range 6: [paras[1].firstChild, 0, paras[1].firstChild, 1] assert_true: First differing node: expected Text node "jklmnop
-", got Text node "Ijklmnop
-" expected true got false
-FAIL Range 7: [paras[1].firstChild, 2, paras[1].firstChild, 8] assert_true: First differing node: expected Text node "Ij
-", got Text node "Ijklmnop
-" expected true got false
-FAIL Range 8: [paras[1].firstChild, 2, paras[1].firstChild, 9] assert_true: First differing node: expected Text node "Ij", got Text node "Ijklmnop
-" expected true got false
-PASS Range 9: [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] 
-PASS Range 10: [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] 
-PASS Range 11: [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] 
-PASS Range 12: [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] 
-PASS Range 13: [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] 
-PASS Range 14: [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] 
-FAIL Range 15: [document.documentElement, 0, document.documentElement, 1] assert_true: First differing node: expected Element node <html><body><div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p..., got Element node <html><head><title>Selection test iframe</title>
-<link re... expected true got false
-FAIL Range 16: [document.documentElement, 0, document.documentElement, 2] assert_true: First differing node: expected Element node <html></html>, got Element node <html><head><title>Selection test iframe</title>
-<link re... expected true got false
-FAIL Range 17: [document.documentElement, 1, document.documentElement, 2] assert_true: First differing node: expected Element node <html><head><title>Selection test iframe</title>
-<link re..., got Element node <html><head><title>Selection test iframe</title>
-<link re... expected true got false
-PASS Range 18: [document.head, 1, document.head, 1] 
-FAIL Range 19: [document.body, 0, document.body, 1] assert_true: First differing node: expected Element node <body>
-
-
-</body>, got Element node <body><div id="test"><p id="a"></p><p id="c"></p><p id="d... expected true got false
-PASS Range 20: [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] 
-PASS Range 21: [foreignDoc.head, 1, foreignDoc.head, 1] 
-PASS Range 22: [foreignDoc.body, 0, foreignDoc.body, 0] 
-PASS Range 23: [paras[0], 0, paras[0], 0] 
-FAIL Range 24: [paras[0], 0, paras[0], 1] assert_true: First differing node: expected Element node <p id="a"></p>, got Element node <p id="a">
-</p> expected true got false
-PASS Range 25: [detachedPara1, 0, detachedPara1, 0] 
-PASS Range 26: [detachedPara1, 0, detachedPara1, 1] 
-FAIL Range 27: [paras[0].firstChild, 0, paras[1].firstChild, 0] assert_true: First differing node: expected Element node <div id="test"><p id="a"></p><p id="b" style="display:non..., got Element node <div id="test"><p id="a"></p><p id="c">Qrstuvwx</p><p id=... expected true got false
-FAIL Range 28: [paras[0].firstChild, 0, paras[1].firstChild, 8] assert_true: First differing node: expected Element node <div id="test"><p id="a"></p><p id="b" style="display:non..., got Element node <div id="test"><p id="a"></p><p id="c">Qrstuvwx</p><p id=... expected true got false
-FAIL Range 29: [paras[0].firstChild, 3, paras[3], 1] assert_true: First differing node: expected Element node <div id="test"><p id="a">Äb</p><p id="d" style="display:..., got Element node <div id="test"><p id="a">Äb̈</p><p id="c"></p><p id="d" ... expected true got false
-FAIL Range 30: [paras[0], 0, paras[0].firstChild, 7] assert_true: First differing node: expected Text node "̈ëf̈g̈ḧ
-", got Text node "ëf̈g̈ḧ
-" expected true got false
-FAIL Range 31: [testDiv, 2, paras[4], 1] assert_true: First differing node: expected Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="b" s..., got Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="b" s... expected true got false
-FAIL Range 32: [testDiv, 1, paras[2].firstChild, 5] assert_true: First differing node: expected Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="c">v..., got Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="b" s... expected true got false
-PASS Range 33: [document.documentElement, 1, document.body, 0] 
-PASS Range 34: [foreignDoc.documentElement, 1, foreignDoc.body, 0] 
-FAIL Range 35: [document, 0, document, 1] assert_true: First differing node: expected Document node with 1 child, got Document node with 2 children expected true got false
-FAIL Range 36: [document, 0, document, 2] assert_true: First differing node: expected Document node with 0 children, got Document node with 2 children expected true got false
-FAIL Range 37: [document, 1, document, 2] assert_true: First differing node: expected Document node with 1 child, got Document node with 2 children expected true got false
-FAIL Range 38: [testDiv, 0, comment, 5] assert_true: First differing node: expected Element node <div id="test"><!--bet soup?--></div>, got Element node <div id="test"><p id="a"></p><p id="c"></p><p id="d" styl... expected true got false
-FAIL Range 39: [paras[2].firstChild, 4, comment, 2] assert_true: First differing node: expected Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="b" s..., got Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="b" s... expected true got false
-FAIL Range 40: [paras[3], 1, comment, 8] assert_true: First differing node: expected Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="b" s..., got Element node <div id="test"><p id="a">Äb̈c̈d̈ëf̈g̈ḧ
-</p><p id="b" s... expected true got false
-PASS Range 41: [foreignDoc, 0, foreignDoc, 0] 
-PASS Range 42: [foreignDoc, 1, foreignComment, 2] 
-PASS Range 43: [foreignDoc.body, 0, foreignTextNode, 36] 
-PASS Range 44: [xmlDoc, 0, xmlDoc, 0] 
-PASS Range 45: [xmlDoc, 1, xmlComment, 0] 
-PASS Range 46: [detachedTextNode, 0, detachedTextNode, 8] 
-PASS Range 47: [detachedForeignTextNode, 7, detachedForeignTextNode, 7] 
-PASS Range 48: [detachedForeignTextNode, 0, detachedForeignTextNode, 8] 
-PASS Range 49: [detachedXmlTextNode, 7, detachedXmlTextNode, 7] 
-PASS Range 50: [detachedXmlTextNode, 0, detachedXmlTextNode, 8] 
-PASS Range 51: [detachedComment, 3, detachedComment, 4] 
-PASS Range 52: [detachedComment, 5, detachedComment, 5] 
-PASS Range 53: [detachedForeignComment, 0, detachedForeignComment, 1] 
-PASS Range 54: [detachedForeignComment, 4, detachedForeignComment, 4] 
-PASS Range 55: [detachedXmlComment, 2, detachedXmlComment, 6] 
-PASS Range 56: [docfrag, 0, docfrag, 0] 
-PASS Range 57: [foreignDocfrag, 0, foreignDocfrag, 0] 
-PASS Range 58: [xmlDocfrag, 0, xmlDocfrag, 0] 
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/base-uri-self.html b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/base-uri-self.html
new file mode 100644
index 0000000..e2bbfd3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/1.1/base-uri-self.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="Content-Security-Policy" content="base-uri 'self'">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <script src="/security/contentSecurityPolicy/resources/testharness-helper.js"></script>
+</head>
+<body>
+  <script>
+    async_test(t => {
+      assert_equals(document.baseURI, window.location.href);
+
+      var b = document.createElement("base");
+      b.href = "http://127.0.0.1:8000/";
+      document.head.appendChild(b);
+
+      document.addEventListener("securitypolicyviolation", e => t.unreached_func());
+
+      // Wait until the next frame to give the report time to fire
+      requestAnimationFrame(t.step_func_done(_ => {
+        assert_equals(document.baseURI, "http://127.0.0.1:8000/");
+      }));
+    }, "'self' works at top-level.");
+
+    async_test(t => {
+      var i = document.createElement("iframe");
+      i.sandbox = "allow-scripts";
+      i.srcdoc = `
+        <script>
+          document.addEventListener("securitypolicyviolation", e => top.postMessage("FAIL", "*"));
+        </scr` + `ipt>
+        <base href="http://127.0.0.1:8000/">
+        <script>
+          requestAnimationFrame(_ => { 
+            top.postMessage(document.baseURI, "*");
+          });
+        </scr` + `ipt>`;
+  
+      waitUntilEvent(window, "message")
+        .then(t.step_func_done(e => {
+          assert_equals(e.data, "http://127.0.0.1:8000/");
+        }));
+
+      document.body.appendChild(i);
+    }, "'self' works in a sandbox.");
+  </script>
+</body>
+</html>
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
index 5391482..41c662e 100644
--- a/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/V8ScriptRunner.cpp
@@ -25,6 +25,7 @@
 
 #include "bindings/core/v8/V8ScriptRunner.h"
 
+#include "bindings/core/v8/BindingSecurity.h"
 #include "bindings/core/v8/ScriptSourceCode.h"
 #include "bindings/core/v8/ScriptStreamer.h"
 #include "bindings/core/v8/V8Binding.h"
@@ -32,6 +33,7 @@
 #include "bindings/core/v8/V8ThrowException.h"
 #include "core/dom/Document.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/frame/LocalDOMWindow.h"
 #include "core/frame/LocalFrame.h"
 #include "core/frame/PerformanceMonitor.h"
 #include "core/inspector/InspectorTraceEvents.h"
@@ -630,8 +632,9 @@
     int argc,
     v8::Local<v8::Value> args[],
     v8::Isolate* isolate) {
-  ScopedFrameBlamer frameBlamer(
-      context->isDocument() ? toDocument(context)->frame() : nullptr);
+  LocalFrame* frame =
+      context->isDocument() ? toDocument(context)->frame() : nullptr;
+  ScopedFrameBlamer frameBlamer(frame);
   TRACE_EVENT0("v8", "v8.callFunction");
 
   int depth = v8::MicrotasksScope::GetCurrentDepth(isolate);
@@ -649,6 +652,11 @@
     TRACE_EVENT_BEGIN1("devtools.timeline", "FunctionCall", "data",
                        InspectorFunctionCallEvent::data(context, function));
 
+  if (frame) {
+    CHECK(BindingSecurity::shouldAllowAccessToFrame(
+        toDOMWindow(function->CreationContext())->toLocalDOMWindow(), frame,
+        BindingSecurity::ErrorReportOption::DoNotReport));
+  }
   CHECK(!ThreadState::current()->isWrapperTracingForbidden());
   v8::MicrotasksScope microtasksScope(isolate,
                                       v8::MicrotasksScope::kRunMicrotasks);
diff --git a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp
index f57a136..1e81a96 100644
--- a/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp
+++ b/third_party/WebKit/Source/core/clipboard/DataTransferItem.cpp
@@ -86,7 +86,7 @@
   ExecutionContext* context = scriptState->getExecutionContext();
   InspectorInstrumentation::asyncTaskScheduled(
       context, "DataTransferItem.getAsString", callback);
-  TaskRunnerHelper::get(TaskType::UserInteraction, context)
+  TaskRunnerHelper::get(TaskType::UserInteraction, scriptState)
       ->postTask(BLINK_FROM_HERE,
                  WTF::bind(&runGetAsStringTask, wrapWeakPersistent(context),
                            wrapPersistent(callback), m_item->getAsString()));
diff --git a/third_party/WebKit/Source/core/editing/DOMSelection.cpp b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
index b359dfe..3ab41952 100644
--- a/third_party/WebKit/Source/core/editing/DOMSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/DOMSelection.cpp
@@ -648,10 +648,24 @@
                                 UseCounter::SelectionAddRangeIntersect);
 }
 
+// https://www.w3.org/TR/selection-api/#dom-selection-deletefromdocument
 void DOMSelection::deleteFromDocument() {
   if (!isAvailable())
     return;
 
+  // The method must invoke deleteContents() ([DOM4]) on the context object's
+  // range if the context object is not empty. Otherwise the method must do
+  // nothing.
+  if (Range* range = documentCachedRange()) {
+    range->deleteContents(ASSERT_NO_EXCEPTION);
+    return;
+  }
+
+  // The following code is necessary for
+  // editing/selection/deleteFromDocument-crash.html, which assumes
+  // deleteFromDocument() for text selection in a TEXTAREA deletes the TEXTAREA
+  // value.
+
   FrameSelection& selection = frame()->selection();
 
   if (selection.isNone())
diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
index 78d0920..2064ac7 100644
--- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
@@ -157,11 +157,15 @@
   DCHECK(m_executionContext &&
          m_executionContext->securityContext().getSecurityOrigin());
 
-  setupSelf(*m_executionContext->securityContext().getSecurityOrigin());
 
   // If we're in a Document, set mixed content checking and sandbox
   // flags, then dump all the parsing error messages, then poke at histograms.
   if (Document* document = this->document()) {
+    // We use the origin of the document's base URL in order to deal correctly
+    // with things like 'about:srcdoc' and 'about:blank', which look to their
+    // parents for a reasonable URL.
+    setupSelf(*SecurityOrigin::create(document->baseURL()));
+
     if (m_sandboxMask != SandboxNone) {
       UseCounter::count(document, UseCounter::SandboxViaCSP);
       document->enforceSandboxFlags(m_sandboxMask);
@@ -186,6 +190,9 @@
       if (policy->allowDynamic())
         UseCounter::count(*document, UseCounter::CSPWithStrictDynamic);
     }
+  } else {
+    // If we're not in a document, set up 'self' with the Worker's origin:
+    setupSelf(*m_executionContext->securityContext().getSecurityOrigin());
   }
 
   // We disable 'eval()' even in the case of report-only policies, and rely on
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
index 643f57d..0a596c56 100644
--- a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
@@ -33,6 +33,7 @@
     KURL secureURL(ParsedURLString, "https://example.test/image.png");
     RefPtr<SecurityOrigin> secureOrigin(SecurityOrigin::create(secureURL));
     document = Document::create();
+    document->setURL(secureURL);
     document->setSecurityOrigin(secureOrigin);
     csp->bindToExecutionContext(document.get());
   }
@@ -41,6 +42,7 @@
     KURL secureURL(ParsedURLString, origin);
     RefPtr<SecurityOrigin> secureOrigin(SecurityOrigin::create(secureURL));
     Document* document = Document::create();
+    document->setURL(secureURL);
     document->setSecurityOrigin(secureOrigin);
     ContentSecurityPolicy* csp = ContentSecurityPolicy::create();
     csp->bindToExecutionContext(document);
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
index c527aa4..bf36005 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.cpp
@@ -227,15 +227,6 @@
   return resource;
 }
 
-void DocumentLoader::didRedirect(const KURL& oldURL, const KURL& newURL) {
-  timing().addRedirect(oldURL, newURL);
-
-  // If a redirection happens during a back/forward navigation, don't restore
-  // any state from the old HistoryItem. There is a provisional history item for
-  // back/forward navigation only. In the other case, clearing it is a no-op.
-  frameLoader().clearProvisionalHistoryItem();
-}
-
 void DocumentLoader::dispatchLinkHeaderPreloads(
     ViewportDescriptionWrapper* viewport,
     LinkLoader::MediaPreloadPolicy mediaPolicy) {
@@ -382,7 +373,13 @@
 
   DCHECK(timing().fetchStart());
   appendRedirect(requestURL);
-  didRedirect(redirectResponse.url(), requestURL);
+  timing().addRedirect(redirectResponse.url(), requestURL);
+
+  // If a redirection happens during a back/forward navigation, don't restore
+  // any state from the old HistoryItem. There is a provisional history item for
+  // back/forward navigation only. In the other case, clearing it is a no-op.
+  frameLoader().clearProvisionalHistoryItem();
+
   frameLoaderClient().dispatchDidReceiveServerRedirectForProvisionalLoad();
 
   return true;
diff --git a/third_party/WebKit/Source/core/loader/DocumentLoader.h b/third_party/WebKit/Source/core/loader/DocumentLoader.h
index 8023984b..2c12953 100644
--- a/third_party/WebKit/Source/core/loader/DocumentLoader.h
+++ b/third_party/WebKit/Source/core/loader/DocumentLoader.h
@@ -190,8 +190,6 @@
                  const SubstituteData&,
                  ClientRedirectPolicy);
 
-  void didRedirect(const KURL& oldURL, const KURL& newURL);
-
   Vector<KURL> m_redirectChain;
 
  private:
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.cpp b/third_party/WebKit/Source/core/loader/PingLoader.cpp
index b17334d..e138e8b 100644
--- a/third_party/WebKit/Source/core/loader/PingLoader.cpp
+++ b/third_party/WebKit/Source/core/loader/PingLoader.cpp
@@ -528,7 +528,7 @@
                                  : "application/json");
   request.setHTTPBody(std::move(report));
   finishPingRequestInitialization(request, frame,
-                                  WebURLRequest::RequestContextPing);
+                                  WebURLRequest::RequestContextCSPReport);
 
   StoredCredentials credentialsAllowed =
       SecurityOrigin::create(reportURL)->isSameSchemeHostPort(
diff --git a/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp b/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp
index 0fc83ca..715a428 100644
--- a/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp
+++ b/third_party/WebKit/Source/modules/quota/DeprecatedStorageInfo.cpp
@@ -54,8 +54,7 @@
   DeprecatedStorageQuota* storageQuota = getStorageQuota(storageType);
   if (!storageQuota) {
     // Unknown storage type is requested.
-    TaskRunnerHelper::get(TaskType::MiscPlatformAPI,
-                          scriptState->getExecutionContext())
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, scriptState)
         ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
                                         errorCallback, NotSupportedError));
     return;
@@ -73,8 +72,7 @@
   DeprecatedStorageQuota* storageQuota = getStorageQuota(storageType);
   if (!storageQuota) {
     // Unknown storage type is requested.
-    TaskRunnerHelper::get(TaskType::MiscPlatformAPI,
-                          scriptState->getExecutionContext())
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, scriptState)
         ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
                                         errorCallback, NotSupportedError));
     return;
diff --git a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
index f24868ab..ac25430 100644
--- a/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
+++ b/third_party/WebKit/Source/modules/quota/DeprecatedStorageQuota.cpp
@@ -62,7 +62,7 @@
   if (storageType != WebStorageQuotaTypeTemporary &&
       storageType != WebStorageQuotaTypePersistent) {
     // Unknown storage type is requested.
-    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, scriptState)
         ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
                                         errorCallback, NotSupportedError));
     return;
@@ -70,7 +70,7 @@
 
   SecurityOrigin* securityOrigin = executionContext->getSecurityOrigin();
   if (securityOrigin->isUnique()) {
-    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, scriptState)
         ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
                                         errorCallback, NotSupportedError));
     return;
@@ -95,7 +95,7 @@
   if (storageType != WebStorageQuotaTypeTemporary &&
       storageType != WebStorageQuotaTypePersistent) {
     // Unknown storage type is requested.
-    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, scriptState)
         ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
                                         errorCallback, NotSupportedError));
     return;
@@ -103,7 +103,7 @@
 
   StorageQuotaClient* client = StorageQuotaClient::from(executionContext);
   if (!client) {
-    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, executionContext)
+    TaskRunnerHelper::get(TaskType::MiscPlatformAPI, scriptState)
         ->postTask(BLINK_FROM_HERE, StorageErrorCallback::createSameThreadTask(
                                         errorCallback, NotSupportedError));
     return;
diff --git a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
index 10f8721..0934e36 100644
--- a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
+++ b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
@@ -74,16 +74,13 @@
   DocumentLoader::appendRedirect(url);
 }
 
-void WebDataSourceImpl::updateNavigation(
-    double redirectStartTime,
-    double redirectEndTime,
-    double fetchStartTime,
-    const WebVector<WebURL>& redirectChain) {
+void WebDataSourceImpl::updateNavigation(double redirectStartTime,
+                                         double redirectEndTime,
+                                         double fetchStartTime,
+                                         bool hasRedirect) {
   // Updates the redirection timing if there is at least one redirection
   // (between two URLs).
-  if (redirectChain.size() >= 2) {
-    for (size_t i = 0; i + 1 < redirectChain.size(); ++i)
-      didRedirect(redirectChain[i], redirectChain[i + 1]);
+  if (hasRedirect) {
     timing().setRedirectStart(redirectStartTime);
     timing().setRedirectEnd(redirectEndTime);
   }
diff --git a/third_party/WebKit/Source/web/WebDataSourceImpl.h b/third_party/WebKit/Source/web/WebDataSourceImpl.h
index 672b784..f0f464d 100644
--- a/third_party/WebKit/Source/web/WebDataSourceImpl.h
+++ b/third_party/WebKit/Source/web/WebDataSourceImpl.h
@@ -71,7 +71,7 @@
   void updateNavigation(double redirectStartTime,
                         double redirectEndTime,
                         double fetchStartTime,
-                        const WebVector<WebURL>& redirectChain) override;
+                        bool hasRedirect) override;
   void setSubresourceFilter(WebDocumentSubresourceFilter*) override;
 
   static WebNavigationType toWebNavigationType(NavigationType);
diff --git a/third_party/WebKit/public/web/WebDataSource.h b/third_party/WebKit/public/web/WebDataSource.h
index 7756cc86..c2b118a 100644
--- a/third_party/WebKit/public/web/WebDataSource.h
+++ b/third_party/WebKit/public/web/WebDataSource.h
@@ -112,7 +112,7 @@
   virtual void updateNavigation(double redirectStartTime,
                                 double redirectEndTime,
                                 double fetchStartTime,
-                                const WebVector<WebURL>& redirectChain) = 0;
+                                bool hasRedirect) = 0;
 
   // Allows the embedder to inject a filter that will be consulted for each
   // subsequent subresource load, and gets the final say in deciding whether
diff --git a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
index 5d46217..5805345 100755
--- a/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
+++ b/tools/android/customtabs_benchmark/scripts/customtabs_benchmark.py
@@ -35,7 +35,7 @@
 
 # Local build of Chrome (not Chromium).
 _CHROME_PACKAGE = 'com.google.android.apps.chrome'
-_COMMAND_LINE_PATH = '/data/local/tmp/chrome-command-line'
+_COMMAND_LINE_FILE = 'chrome-command-line'
 _TEST_APP_PACKAGE_NAME = 'org.chromium.customtabsclient.test'
 _INVALID_VALUE = -1
 
@@ -99,7 +99,7 @@
   logcat_timeout = int(timeout_s + delay_to_may_launch_url / 1000.
                        + delay_to_launch_url / 1000.) + 3;
 
-  with device_setup.FlagReplacer(device, _COMMAND_LINE_PATH, chrome_args):
+  with device_setup.FlagReplacer(device, _COMMAND_LINE_FILE, chrome_args):
     launch_intent = intent.Intent(
         action='android.intent.action.MAIN',
         package=_TEST_APP_PACKAGE_NAME,
@@ -186,13 +186,13 @@
           chrome_args.extend([
               '--force-fieldtrials=trial/group',
               '--force-fieldtrial-params=trial.group:mode/no_state_prefetch',
-              '--enable-features="NoStatePrefetch<trial"'])
+              '--enable-features=NoStatePrefetch<trial'])
         elif config['speculation_mode'] == 'speculative_prefetch':
           # Speculative Prefetch is enabled through an experiment.
           chrome_args.extend([
               '--force-fieldtrials=trial/group',
               '--force-fieldtrial-params=trial.group:mode/external-prefetching',
-              '--enable-features="SpeculativeResourcePrefetching<trial"'])
+              '--enable-features=SpeculativeResourcePrefetching<trial'])
 
         result = RunOnce(device, config['url'], config['warmup'],
                          config['speculation_mode'],
diff --git a/tools/android/loading/controller.py b/tools/android/loading/controller.py
index bbd4799a..ace200b03 100644
--- a/tools/android/loading/controller.py
+++ b/tools/android/loading/controller.py
@@ -339,13 +339,9 @@
       assert self._wpr_attributes.chrome_env_override == {}, \
           'Remote controller doesn\'t support chrome environment variables.'
     package_info = OPTIONS.ChromePackage()
-    command_line_path = '/data/local/tmp/chrome-command-line'
     self._device.ForceStop(package_info.package)
-    chrome_args = self._GetChromeArguments()
-    logging.info('Launching %s with flags: %s' % (package_info.package,
-        subprocess.list2cmdline(chrome_args)))
     with device_setup.FlagReplacer(
-        self._device, command_line_path, self._GetChromeArguments()):
+        self._device, package_info.cmdline_file, self._GetChromeArguments()):
       self._DismissCrashDialogIfNeeded()
       start_intent = intent.Intent(
           package=package_info.package, activity=package_info.activity,
diff --git a/tools/android/loading/device_setup.py b/tools/android/loading/device_setup.py
index fc22bdcb5..954ae09 100644
--- a/tools/android/loading/device_setup.py
+++ b/tools/android/loading/device_setup.py
@@ -234,16 +234,12 @@
                                       ' without a specified archive.')
 
 
-def _FormatWPRRelatedChromeArgumentFor(http_port, https_port, escape):
+def _FormatWPRRelatedChromeArgumentFor(http_port, https_port):
   HOST_RULES='MAP * 127.0.0.1,EXCLUDE localhost'
-  chrome_args = [
+  return [
       '--testing-fixed-http-port={}'.format(http_port),
-      '--testing-fixed-https-port={}'.format(https_port)]
-  if escape:
-    chrome_args.append('--host-resolver-rules="{}"'.format(HOST_RULES))
-  else:
-    chrome_args.append('--host-resolver-rules={}'.format(HOST_RULES))
-  return chrome_args
+      '--testing-fixed-https-port={}'.format(https_port),
+      '--host-resolver-rules={}'.format(HOST_RULES)]
 
 
 @contextlib.contextmanager
@@ -286,8 +282,7 @@
         disable_script_injection=disable_script_injection,
         wpr_ca_cert_path=private_ca_cert_path,
         out_log_path=out_log_path) as (http_port, https_port):
-      chrome_args = _FormatWPRRelatedChromeArgumentFor(http_port, https_port,
-                                                       escape=False)
+      chrome_args = _FormatWPRRelatedChromeArgumentFor(http_port, https_port)
       yield WprAttribute(chrome_args=chrome_args,
                          chrome_env_override={'HOME': temp_home_dir})
 
@@ -340,8 +335,7 @@
       device_https_port = forwarder.Forwarder.DevicePortForHostPort(https_port)
       try:
         chrome_args = _FormatWPRRelatedChromeArgumentFor(device_http_port,
-                                                         device_https_port,
-                                                         escape=True)
+                                                         device_https_port)
         yield WprAttribute(chrome_args=chrome_args, chrome_env_override={})
       finally:
         # Tear down the forwarder.
diff --git a/tools/cygprofile/profile_android_startup.py b/tools/cygprofile/profile_android_startup.py
index b4d011f1..96d1b4c 100755
--- a/tools/cygprofile/profile_android_startup.py
+++ b/tools/cygprofile/profile_android_startup.py
@@ -178,7 +178,7 @@
     self._flag_changer = flag_changer.FlagChanger(
         self._device, self._cmdline_file)
     self._flag_changer.AddFlags([
-        '--host-resolver-rules="MAP * 127.0.0.1,EXCLUDE localhost"',
+        '--host-resolver-rules=MAP * 127.0.0.1,EXCLUDE localhost',
         '--testing-fixed-http-port=%s' % device_http,
         '--testing-fixed-https-port=%s' % device_https])
 
@@ -416,4 +416,3 @@
 
 if __name__ == '__main__':
   sys.exit(main())
-
diff --git a/tools/resource_prefetch_predictor/generate_test_data.py b/tools/resource_prefetch_predictor/generate_test_data.py
index 58dd1da1..89986f1 100755
--- a/tools/resource_prefetch_predictor/generate_test_data.py
+++ b/tools/resource_prefetch_predictor/generate_test_data.py
@@ -36,7 +36,7 @@
 _LEARNING_FLAGS = [
     '--force-fieldtrials=trial/group',
     '--force-fieldtrial-params=trial.group:mode/learning',
-    '--enable-features="SpeculativeResourcePrefetching<trial"']
+    '--enable-features=SpeculativeResourcePrefetching<trial']
 
 
 def _CreateArgumentParser():
diff --git a/tools/resource_prefetch_predictor/prefetch_benchmark.py b/tools/resource_prefetch_predictor/prefetch_benchmark.py
index 586c2ebb..e31bd1d1 100755
--- a/tools/resource_prefetch_predictor/prefetch_benchmark.py
+++ b/tools/resource_prefetch_predictor/prefetch_benchmark.py
@@ -59,7 +59,7 @@
 
 def _Setup(device, database_filename):
   """Sets up a device and returns an instance of RemoteChromeController."""
-  chrome_controller = prefetch_predictor_common.Setup(device, [''])
+  chrome_controller = prefetch_predictor_common.Setup(device)
   chrome_package = OPTIONS.ChromePackage()
   device.ForceStop(chrome_package.package)
   chrome_controller.ResetBrowserState()
@@ -68,9 +68,8 @@
 
   # Make sure that the speculative prefetch predictor is enabled to ensure
   # that the disk database is re-created.
-  command_line_path = '/data/local/tmp/chrome-command-line'
   with device_setup.FlagReplacer(
-      device, command_line_path, ['--disable-fre']):
+      device, chrome_package.cmdline_file, ['--disable-fre']):
     # Launch Chrome for the first time to recreate the local state.
     launch_intent = intent.Intent(
         action='android.intent.action.MAIN',
@@ -104,7 +103,7 @@
   chrome_args.extend([
       '--force-fieldtrials=trial/group',
       '--force-fieldtrial-params=trial.group:mode/external-prefetching',
-      '--enable-features="SpeculativeResourcePrefetching<trial"'])
+      '--enable-features=SpeculativeResourcePrefetching<trial'])
 
   chrome_controller = controller.RemoteChromeController(device)
   device.ForceStop(OPTIONS.ChromePackage().package)