diff --git a/DEPS b/DEPS
index df88395..14e469d6 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '24a38ed5a84dc6414a938aee5cc7442e6b0faa7d',
+  'v8_revision': 'e4336dfaafc0494ff745a163aa458e90a8df39cc',
   # 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.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'cd5e12a9ea397b48056643a7b65126395eec3174',
+  'pdfium_revision': '64f4e25304dfd93651ac5c9d5379ed2fffbb993f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # 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': '11d3d44fb9d22dea38862472a620d4f0be67ae97',
+  'catapult_revision': '3838eb5d96b721896766c557a3d7b514fa427b21',
   # 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/android_webview/crash_reporter/aw_microdump_crash_reporter.cc b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc
index f813842..9f50704 100644
--- a/android_webview/crash_reporter/aw_microdump_crash_reporter.cc
+++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc
@@ -154,6 +154,10 @@
   breakpad::AddGpuFingerprintToMicrodumpCrashHandler(gpu_fingerprint);
 }
 
+void SetWebViewTextAddrRange(uintptr_t start, uintptr_t end) {
+  breakpad::SetNativeCodeTextAddrRange(start, end);
+}
+
 bool DumpWithoutCrashingToFd(int fd) {
   return g_crash_reporter_client.Pointer()->DumpWithoutCrashingToFd(fd);
 }
diff --git a/android_webview/crash_reporter/aw_microdump_crash_reporter.h b/android_webview/crash_reporter/aw_microdump_crash_reporter.h
index 33dcc344..cc83295 100644
--- a/android_webview/crash_reporter/aw_microdump_crash_reporter.h
+++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.h
@@ -14,6 +14,7 @@
                                   int crash_signal_fd);
 void AddGpuFingerprintToMicrodumpCrashHandler(
     const std::string& gpu_fingerprint);
+void SetWebViewTextAddrRange(uintptr_t start, uintptr_t end);
 bool DumpWithoutCrashingToFd(int fd);
 }  // namespace crash_reporter
 }  // namespace android_webview
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index 3c91dc7..457e91b 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -46,6 +46,21 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
 
+// These declarations just provide the addresses determined by the
+// linker to this source file in order to determine the extent of the
+// webview text section. The declared types are irrelevant - only the
+// symbol names and the addresses they reference are important.
+extern "C" {
+#if defined(ARCH_CPU_MIPSEL)
+// the mipsel linker script invoked as a result of chromium link args
+// doesn't define __executable_start.
+extern char _ftext;
+#else
+extern char __executable_start;
+#endif
+extern char __etext;
+}
+
 namespace android_webview {
 
 namespace {
@@ -209,7 +224,15 @@
     // crash handler on the same thread as the crash handler was initialized.
     crash_reporter::AddGpuFingerprintToMicrodumpCrashHandler(
         content_client_.gpu_fingerprint());
-
+#if !defined(COMPONENT_BUILD)
+    crash_reporter::SetWebViewTextAddrRange(
+#if defined(ARCH_CPU_MIPSEL)
+        reinterpret_cast<uintptr_t>(&_ftext),
+#else
+        reinterpret_cast<uintptr_t>(&__executable_start),
+#endif
+        reinterpret_cast<uintptr_t>(&__etext));
+#endif
     g_allow_wait_in_ui_thread.Get().reset(
         new ScopedAllowWaitForLegacyWebViewApi);
 
diff --git a/chrome/app/address_input_strings.grd b/chrome/app/address_input_strings.grd
index cc86c82..cc61b6c2 100644
--- a/chrome/app/address_input_strings.grd
+++ b/chrome/app/address_input_strings.grd
@@ -35,7 +35,13 @@
     <output filename="address_input_strings_en-GB.pak" type="data_package" lang="en-GB" />
     <output filename="address_input_strings_en-US.pak" type="data_package" lang="en" />
     <output filename="address_input_strings_es.pak" type="data_package" lang="es" />
-    <output filename="address_input_strings_es-419.pak" type="data_package" lang="es-419" />
+    <if expr="is_ios">
+      <!-- iOS uses es-MX for es-419 -->
+      <output filename="address_input_strings_es-MX.pak" type="data_package" lang="es-419" />
+    </if>
+    <if expr="not is_ios">
+      <output filename="address_input_strings_es-419.pak" type="data_package" lang="es-419" />
+    </if>
     <output filename="address_input_strings_et.pak" type="data_package" lang="et" />
     <output filename="address_input_strings_fa.pak" type="data_package" lang="fa" />
     <output filename="address_input_strings_fake-bidi.pak" type="data_package" lang="fake-bidi" />
@@ -62,7 +68,13 @@
          be 'nb'. -->
     <output filename="address_input_strings_nb.pak" type="data_package" lang="no" />
     <output filename="address_input_strings_pl.pak" type="data_package" lang="pl" />
-    <output filename="address_input_strings_pt-BR.pak" type="data_package" lang="pt-BR" />
+    <if expr="is_ios">
+      <!-- iOS uses pt for pt-BR -->
+      <output filename="address_input_strings_pt.pak" type="data_package" lang="pt-BR" />
+    </if>
+    <if expr="not is_ios">
+      <output filename="address_input_strings_pt-BR.pak" type="data_package" lang="pt-BR" />
+    </if>
     <output filename="address_input_strings_pt-PT.pak" type="data_package" lang="pt-PT" />
     <output filename="address_input_strings_ro.pak" type="data_package" lang="ro" />
     <output filename="address_input_strings_ru.pak" type="data_package" lang="ru" />
diff --git a/components/crash/content/app/breakpad_linux.cc b/components/crash/content/app/breakpad_linux.cc
index 9ebc33f..16c1e5b 100644
--- a/components/crash/content/app/breakpad_linux.cc
+++ b/components/crash/content/app/breakpad_linux.cc
@@ -110,7 +110,11 @@
   MicrodumpInfo()
       : microdump_build_fingerprint_(nullptr),
         microdump_product_info_(nullptr),
-        microdump_gpu_fingerprint_(nullptr) {}
+        microdump_gpu_fingerprint_(nullptr),
+        microdump_process_type_(nullptr),
+        interest_range_start_(0ul),
+        interest_range_end_(0ul),
+        suppress_microdump_based_on_interest_range_(false) {}
 
   // The order in which SetGpuFingerprint and Initialize are called
   // may be dependent on the timing of the availability of GPU
@@ -126,6 +130,7 @@
   // which a microdump is generated, then the GPU fingerprint will be
   // UNKNOWN.
   void SetGpuFingerprint(const std::string& gpu_fingerprint);
+  void SetMicrodumpInterestRange(uintptr_t start, uintptr_t end);
   void Initialize(const std::string& process_type,
                   const char* product_name,
                   const char* product_version,
@@ -137,6 +142,9 @@
   const char* microdump_product_info_;
   const char* microdump_gpu_fingerprint_;
   const char* microdump_process_type_;
+  uintptr_t interest_range_start_;
+  uintptr_t interest_range_end_;
+  bool suppress_microdump_based_on_interest_range_;
 };
 
 base::LazyInstance<MicrodumpInfo> g_microdump_info =
@@ -872,6 +880,22 @@
   }
 }
 
+void MicrodumpInfo::SetMicrodumpInterestRange(uintptr_t start, uintptr_t end) {
+  interest_range_start_ = start;
+  interest_range_end_ = end;
+  suppress_microdump_based_on_interest_range_ = true;
+
+  if (g_microdump) {
+    MinidumpDescriptor descriptor(g_microdump->minidump_descriptor());
+    google_breakpad::MicrodumpExtraInfo* microdump_extra_info =
+        descriptor.microdump_extra_info();
+    microdump_extra_info->interest_range_start = interest_range_start_;
+    microdump_extra_info->interest_range_end = interest_range_end_;
+    microdump_extra_info->suppress_microdump_based_on_interest_range = true;
+    g_microdump->set_minidump_descriptor(descriptor);
+  }
+}
+
 void MicrodumpInfo::Initialize(const std::string& process_type,
                                const char* product_name,
                                const char* product_version,
@@ -886,31 +910,36 @@
                             process_type == kBrowserProcessType;
 
   MinidumpDescriptor descriptor(MinidumpDescriptor::kMicrodumpOnConsole);
+  google_breakpad::MicrodumpExtraInfo* microdump_extra_info =
+      descriptor.microdump_extra_info();
 
   if (product_name && product_version) {
     microdump_product_info_ =
         strdup((product_name + std::string(":") + product_version).c_str());
     ANNOTATE_LEAKING_OBJECT_PTR(microdump_product_info_);
-    descriptor.microdump_extra_info()->product_info = microdump_product_info_;
+    microdump_extra_info->product_info = microdump_product_info_;
   }
 
   microdump_process_type_ =
       strdup(process_type.empty() ? kBrowserProcessType : process_type.c_str());
   ANNOTATE_LEAKING_OBJECT_PTR(microdump_process_type_);
-  descriptor.microdump_extra_info()->process_type = microdump_process_type_;
+  microdump_extra_info->process_type = microdump_process_type_;
 
   if (android_build_fp) {
     microdump_build_fingerprint_ = strdup(android_build_fp);
     ANNOTATE_LEAKING_OBJECT_PTR(microdump_build_fingerprint_);
-    descriptor.microdump_extra_info()->build_fingerprint =
-        microdump_build_fingerprint_;
+    microdump_extra_info->build_fingerprint = microdump_build_fingerprint_;
   }
 
   if (microdump_gpu_fingerprint_) {
-    descriptor.microdump_extra_info()->gpu_fingerprint =
-        microdump_gpu_fingerprint_;
+    microdump_extra_info->gpu_fingerprint = microdump_gpu_fingerprint_;
   }
 
+  microdump_extra_info->interest_range_start = interest_range_start_;
+  microdump_extra_info->interest_range_end = interest_range_end_;
+  microdump_extra_info->suppress_microdump_based_on_interest_range =
+      suppress_microdump_based_on_interest_range_;
+
   g_microdump =
       new ExceptionHandler(descriptor, nullptr, MicrodumpCrashDone,
                            reinterpret_cast<void*>(is_browser_process),
@@ -1934,6 +1963,10 @@
     const std::string& gpu_fingerprint) {
   g_microdump_info.Get().SetGpuFingerprint(gpu_fingerprint);
 }
+
+void SetNativeCodeTextAddrRange(uintptr_t start, uintptr_t end) {
+  g_microdump_info.Get().SetMicrodumpInterestRange(start, end);
+}
 #endif  // OS_ANDROID
 
 bool IsCrashReporterEnabled() {
diff --git a/components/crash/content/app/breakpad_linux.h b/components/crash/content/app/breakpad_linux.h
index 3316fa0..0d70a9d 100644
--- a/components/crash/content/app/breakpad_linux.h
+++ b/components/crash/content/app/breakpad_linux.h
@@ -31,6 +31,11 @@
 
 extern void AddGpuFingerprintToMicrodumpCrashHandler(
     const std::string& gpu_fingerprint);
+
+// Inform breakpad of the extent of the text section that is
+// considered interesting for the purpose of crashes so that this can
+// be used to elide crashes that do not reference interesting code.
+extern void SetNativeCodeTextAddrRange(uintptr_t start, uintptr_t end);
 #endif
 
 // Checks if crash reporting is enabled. Note that this is not the same as
diff --git a/components/ntp_snippets/pref_names.cc b/components/ntp_snippets/pref_names.cc
index 9b0ff032..0fe7edf 100644
--- a/components/ntp_snippets/pref_names.cc
+++ b/components/ntp_snippets/pref_names.cc
@@ -41,6 +41,9 @@
     "ntp_suggestions.foreign_sessions.dismissed_ids";
 const char kDismissedCategories[] = "ntp_suggestions.dismissed_categories";
 
+const char kLastSuccessfulBackgroundFetchTime[] =
+    "ntp_suggestions.remote.last_successful_background_fetch_time";
+
 const char kUserClassifierAverageNTPOpenedPerHour[] =
     "ntp_suggestions.user_classifier.average_ntp_opened_per_hour";
 const char kUserClassifierAverageSuggestionsShownPerHour[] =
diff --git a/components/ntp_snippets/pref_names.h b/components/ntp_snippets/pref_names.h
index d474d4c4..a1f7dd1 100644
--- a/components/ntp_snippets/pref_names.h
+++ b/components/ntp_snippets/pref_names.h
@@ -40,6 +40,9 @@
 // thumbnails.
 extern const char kSnippetThumbnailsRequestsDay[];
 
+// The pref name for the time of the last successful background fetch.
+extern const char kLastSuccessfulBackgroundFetchTime[];
+
 extern const char kDismissedAssetDownloadSuggestions[];
 extern const char kDismissedRecentOfflineTabSuggestions[];
 extern const char kDismissedOfflinePageDownloadSuggestions[];
diff --git a/components/ntp_snippets/remote/ntp_snippets_fetcher.cc b/components/ntp_snippets/remote/ntp_snippets_fetcher.cc
index 62236a8..76ec5f1e 100644
--- a/components/ntp_snippets/remote/ntp_snippets_fetcher.cc
+++ b/components/ntp_snippets/remote/ntp_snippets_fetcher.cc
@@ -1005,7 +1005,7 @@
 
   DVLOG(1) << "Fetch finished: " << last_status_;
 
-  std::move(callback).Run(std::move(categories));
+  std::move(callback).Run(status_code, std::move(categories));
 }
 
 bool NTPSnippetsFetcher::JsonToSnippets(const base::Value& parsed,
diff --git a/components/ntp_snippets/remote/ntp_snippets_fetcher.h b/components/ntp_snippets/remote/ntp_snippets_fetcher.h
index 62437c9..772aa05 100644
--- a/components/ntp_snippets/remote/ntp_snippets_fetcher.h
+++ b/components/ntp_snippets/remote/ntp_snippets_fetcher.h
@@ -80,12 +80,6 @@
   using FetchedCategoriesVector = std::vector<FetchedCategory>;
   using OptionalFetchedCategories = base::Optional<FetchedCategoriesVector>;
 
-  // |snippets| contains parsed snippets if a fetch succeeded. If problems
-  // occur, |snippets| contains no value (no actual vector in base::Optional).
-  // Error details can be retrieved using last_status().
-  using SnippetsAvailableCallback =
-      base::OnceCallback<void(OptionalFetchedCategories fetched_categories)>;
-
   // Enumeration listing all possible outcomes for fetch attempts. Used for UMA
   // histograms, so do not change existing values. Insert new values at the end,
   // and update the histogram definition.
@@ -102,6 +96,13 @@
     RESULT_MAX
   };
 
+  // |snippets| contains parsed snippets if a fetch succeeded. If problems
+  // occur, |snippets| contains no value (no actual vector in base::Optional).
+  // Error details can be retrieved using last_status().
+  using SnippetsAvailableCallback =
+      base::OnceCallback<void(FetchResult fetch_result,
+                              OptionalFetchedCategories fetched_categories)>;
+
   // Enumeration listing all possible variants of dealing with personalization.
   enum class Personalization { kPersonal, kNonPersonal, kBoth };
 
diff --git a/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc b/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc
index c02ffa4..dde8e381 100644
--- a/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc
+++ b/components/ntp_snippets/remote/ntp_snippets_fetcher_unittest.cc
@@ -60,8 +60,8 @@
 // Artificial time delay for JSON parsing.
 const int64_t kTestJsonParsingLatencyMs = 20;
 
-ACTION_P(MoveArgumentPointeeTo, ptr) {
-  *ptr = std::move(*arg0);
+ACTION_P(MoveArgument1PointeeTo, ptr) {
+  *ptr = std::move(*arg1);
 }
 
 MATCHER(HasValue, "") {
@@ -149,13 +149,15 @@
  public:
   // Workaround for gMock's lack of support for movable arguments.
   void WrappedRun(
+      NTPSnippetsFetcher::FetchResult fetch_result,
       NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) {
-    Run(&fetched_categories);
+    Run(fetch_result, &fetched_categories);
   }
 
-  MOCK_METHOD1(
+  MOCK_METHOD2(
       Run,
-      void(NTPSnippetsFetcher::OptionalFetchedCategories* fetched_categories));
+      void(NTPSnippetsFetcher::FetchResult fetch_result,
+           NTPSnippetsFetcher::OptionalFetchedCategories* fetched_categories));
 };
 
 // Factory for FakeURLFetcher objects that always generate errors.
@@ -610,10 +612,10 @@
       "}]}";
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(
-      mock_callback(),
-      Run(AllOf(IsSingleArticle("http://localhost/foobar"),
-                FirstCategoryHasInfo(IsCategoryInfoForArticles()))));
+  EXPECT_CALL(mock_callback(),
+              Run(NTPSnippetsFetcher::FetchResult::SUCCESS,
+                  AllOf(IsSingleArticle("http://localhost/foobar"),
+                        FirstCategoryHasInfo(IsCategoryInfoForArticles()))));
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -648,7 +650,8 @@
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
   EXPECT_CALL(mock_callback(),
-              Run(AllOf(IsSingleArticle("http://localhost/foobar"),
+              Run(NTPSnippetsFetcher::FetchResult::SUCCESS,
+                  AllOf(IsSingleArticle("http://localhost/foobar"),
                         FirstCategoryHasInfo(IsCategoryInfoForArticles()))));
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
@@ -671,7 +674,8 @@
       "}]}";
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList()));
+  EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS,
+                                   IsEmptyArticleList()));
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -722,8 +726,8 @@
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
   NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories;
-  EXPECT_CALL(mock_callback(), Run(_))
-      .WillOnce(MoveArgumentPointeeTo(&fetched_categories));
+  EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, _))
+      .WillOnce(MoveArgument1PointeeTo(&fetched_categories));
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -784,8 +788,8 @@
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
   NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories;
-  EXPECT_CALL(mock_callback(), Run(_))
-      .WillOnce(MoveArgumentPointeeTo(&fetched_categories));
+  EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, _))
+      .WillOnce(MoveArgument1PointeeTo(&fetched_categories));
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -848,8 +852,8 @@
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
   NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories;
-  EXPECT_CALL(mock_callback(), Run(_))
-      .WillOnce(MoveArgumentPointeeTo(&fetched_categories));
+  EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS, _))
+      .WillOnce(MoveArgument1PointeeTo(&fetched_categories));
 
   NTPSnippetsFetcher::Params params = test_params();
   params.exclusive_category = base::Optional<Category>(
@@ -892,7 +896,8 @@
   const std::string kJsonStr = "{\"recos\": []}";
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList()));
+  EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS,
+                                   IsEmptyArticleList()));
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -940,7 +945,10 @@
   // call to the delegate that usually happens on |Start|.
   // Without the call to the delegate, it leaks the request that owns itself.
   ASSERT_THAT(fetcher->delegate(), NotNull());
-  EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
+  EXPECT_CALL(mock_callback(),
+              Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR,
+                  /*snippets=*/Not(HasValue())))
+      .Times(1);
   // An 4XX response needs the least configuration to successfully invoke the
   // callback properly as the results are not important in this test.
   fetcher->set_response_code(net::HTTP_NOT_FOUND);
@@ -951,7 +959,10 @@
 TEST_F(NTPSnippetsFetcherTest, ShouldReportUrlStatusError) {
   SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
                   net::URLRequestStatus::FAILED);
-  EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
+  EXPECT_CALL(mock_callback(),
+              Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR,
+                  /*snippets=*/Not(HasValue())))
+      .Times(1);
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -971,7 +982,9 @@
 TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpError) {
   SetFakeResponse(/*response_data=*/std::string(), net::HTTP_NOT_FOUND,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
+  EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::HTTP_ERROR,
+                                   /*snippets=*/Not(HasValue())))
+      .Times(1);
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -990,7 +1003,10 @@
   const std::string kInvalidJsonStr = "{ \"recos\": []";
   SetFakeResponse(/*response_data=*/kInvalidJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
+  EXPECT_CALL(mock_callback(),
+              Run(NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR,
+                  /*snippets=*/Not(HasValue())))
+      .Times(1);
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -1011,7 +1027,10 @@
 TEST_F(NTPSnippetsFetcherTest, ShouldReportJsonErrorForEmptyResponse) {
   SetFakeResponse(/*response_data=*/std::string(), net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
+  EXPECT_CALL(mock_callback(),
+              Run(NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR,
+                  /*snippets=*/Not(HasValue())))
+      .Times(1);
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -1029,7 +1048,11 @@
       "{\"recos\": [{ \"contentInfo\": { \"foo\" : \"bar\" }}]}";
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
+  EXPECT_CALL(
+      mock_callback(),
+      Run(NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR,
+          /*snippets=*/Not(HasValue())))
+      .Times(1);
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -1048,7 +1071,10 @@
 // hard-to-reproduce test failures.
 TEST_F(NTPSnippetsFetcherTest, ShouldReportHttpErrorForMissingBakedResponse) {
   InitFakeURLFetcherFactory();
-  EXPECT_CALL(mock_callback(), Run(/*snippets=*/Not(HasValue()))).Times(1);
+  EXPECT_CALL(mock_callback(),
+              Run(NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR,
+                  /*snippets=*/Not(HasValue())))
+      .Times(1);
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   FastForwardUntilNoTasksRemain();
@@ -1058,7 +1084,9 @@
   const std::string kJsonStr = "{ \"recos\": [] }";
   SetFakeResponse(/*response_data=*/kJsonStr, net::HTTP_OK,
                   net::URLRequestStatus::SUCCESS);
-  EXPECT_CALL(mock_callback(), Run(IsEmptyArticleList())).Times(5);
+  EXPECT_CALL(mock_callback(), Run(NTPSnippetsFetcher::FetchResult::SUCCESS,
+                                   IsEmptyArticleList()))
+      .Times(5);
   snippets_fetcher().FetchSnippets(
       test_params(), ToSnippetsAvailableCallback(&mock_callback()));
   // More calls to FetchSnippets() do not interrupt the previous.
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider.cc b/components/ntp_snippets/remote/remote_suggestions_provider.cc
index 653c82b..4ff354f 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
+#include "base/time/default_tick_clock.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "components/data_use_measurement/core/data_use_user_data.h"
@@ -249,7 +250,8 @@
       nuke_when_initialized_(false),
       thumbnail_requests_throttler_(
           pref_service,
-          RequestThrottler::RequestType::CONTENT_SUGGESTION_THUMBNAIL) {
+          RequestThrottler::RequestType::CONTENT_SUGGESTION_THUMBNAIL),
+      tick_clock_(base::MakeUnique<base::DefaultTickClock>()) {
   pref_service_->ClearPref(kDeprecatedSnippetHostsPref);
 
   RestoreCategoriesFromPrefs();
@@ -290,6 +292,7 @@
   registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalWifi, 0);
   registry->RegisterInt64Pref(prefs::kSnippetBackgroundFetchingIntervalFallback,
                               0);
+  registry->RegisterInt64Pref(prefs::kLastSuccessfulBackgroundFetchTime, 0);
 
   RemoteSuggestionsStatusService::RegisterProfilePrefs(registry);
 }
@@ -331,7 +334,7 @@
   params.interactive_request = interactive_request;
   snippets_fetcher_->FetchSnippets(
       params, base::BindOnce(&RemoteSuggestionsProvider::OnFetchFinished,
-                             base::Unretained(this)));
+                             base::Unretained(this), interactive_request));
 }
 
 void RemoteSuggestionsProvider::Fetch(
@@ -641,6 +644,7 @@
 
 void RemoteSuggestionsProvider::OnFetchMoreFinished(
     const FetchDoneCallback& fetching_callback,
+    NTPSnippetsFetcher::FetchResult fetch_result,
     NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) {
   if (!fetched_categories) {
     // TODO(fhorschig): Disambiguate the kind of error that led here.
@@ -702,6 +706,8 @@
 }
 
 void RemoteSuggestionsProvider::OnFetchFinished(
+    bool interactive_request,
+    NTPSnippetsFetcher::FetchResult fetch_result,
     NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) {
   if (!ready()) {
     // TODO(tschumann): What happens if this was a user-triggered, interactive
@@ -709,6 +715,13 @@
     return;
   }
 
+  // Record the fetch time of a successfull background fetch.
+  if (!interactive_request &&
+      fetch_result == NTPSnippetsFetcher::FetchResult::SUCCESS) {
+    pref_service_->SetInt64(prefs::kLastSuccessfulBackgroundFetchTime,
+                            tick_clock_->NowTicks().ToInternalValue());
+  }
+
   // Mark all categories as not provided by the server in the latest fetch. The
   // ones we got will be marked again below.
   for (auto& item : category_contents_) {
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider.h b/components/ntp_snippets/remote/remote_suggestions_provider.h
index a8081b7e..1c76a58 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider.h
+++ b/components/ntp_snippets/remote/remote_suggestions_provider.h
@@ -151,6 +151,11 @@
     return category_contents_.find(category)->second.dismissed;
   }
 
+  // Overrides internal clock for testing purposes.
+  void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock) {
+    tick_clock_ = std::move(tick_clock);
+  }
+
  private:
   friend class RemoteSuggestionsProviderTest;
 
@@ -261,10 +266,13 @@
   // Callback for fetch-more requests with the NTPSnippetsFetcher.
   void OnFetchMoreFinished(
       const FetchDoneCallback& fetching_callback,
+      NTPSnippetsFetcher::FetchResult fetch_result,
       NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories);
 
   // Callback for regular fetch requests with the NTPSnippetsFetcher.
   void OnFetchFinished(
+      bool interactive_request,
+      NTPSnippetsFetcher::FetchResult fetch_status,
       NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories);
 
   // Moves all snippets from |to_archive| into the archive of the |content|.
@@ -407,6 +415,9 @@
   // Request throttler for limiting requests to thumbnail images.
   RequestThrottler thumbnail_requests_throttler_;
 
+  // A clock for getting the time. This allows to inject a tick clock in tests.
+  std::unique_ptr<base::TickClock> tick_clock_;
+
   DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsProvider);
 };
 
diff --git a/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc
index b593ee4..27ac0a2 100644
--- a/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_provider_unittest.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/simple_test_tick_clock.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "components/image_fetcher/image_decoder.h"
@@ -1593,4 +1594,37 @@
               SizeIs(service->GetMaxSnippetCountForTesting() + 1));
 }
 
+TEST_F(RemoteSuggestionsProviderTest, StoreLastSuccessfullBackgroundFetchTime) {
+  // On initialization of the RemoteSuggestionsProvider a background fetch is
+  // triggered since the snippets DB is empty. Therefore the service must not be
+  // initialized until the test clock is set.
+  auto service = MakeSnippetsServiceWithoutInitialization();
+
+  auto simple_test_tick_clock = base::MakeUnique<base::SimpleTestTickClock>();
+  base::SimpleTestTickClock* simple_test_tick_clock_ptr =
+      simple_test_tick_clock.get();
+  service->SetTickClockForTesting(std::move(simple_test_tick_clock));
+
+  // Test that the preference is correctly initialized with the default value 0.
+  EXPECT_EQ(
+      0, pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
+
+  WaitForSnippetsServiceInitialization(service.get(),
+                                       /*set_empty_response=*/true);
+  EXPECT_EQ(
+      simple_test_tick_clock_ptr->NowTicks().ToInternalValue(),
+      pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
+
+  // Advance the time and check whether the time was updated correctly after the
+  // background fetch.
+  simple_test_tick_clock_ptr->Advance(TimeDelta::FromHours(1));
+  service->FetchSnippetsInTheBackground();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(
+      simple_test_tick_clock_ptr->NowTicks().ToInternalValue(),
+      pref_service()->GetInt64(prefs::kLastSuccessfulBackgroundFetchTime));
+  // TODO(markusheintz): Add a test that simulates a browser restart once the
+  // scheduler refactoring is done (crbug.com/672434).
+}
+
 }  // namespace ntp_snippets
diff --git a/ios/chrome/app/resources/BUILD.gn b/ios/chrome/app/resources/BUILD.gn
index f83e2dc4..f89503e 100644
--- a/ios/chrome/app/resources/BUILD.gn
+++ b/ios/chrome/app/resources/BUILD.gn
@@ -113,50 +113,3 @@
     ios_launchscreen_assets_target,
   ]
 }
-
-bundle_data("terms_of_service_bundle") {
-  sources = [
-    "//components/resources/terms/terms_ar.html",
-    "//components/resources/terms/terms_bg.html",
-    "//components/resources/terms/terms_ca.html",
-    "//components/resources/terms/terms_cs.html",
-    "//components/resources/terms/terms_da.html",
-    "//components/resources/terms/terms_de.html",
-    "//components/resources/terms/terms_el.html",
-    "//components/resources/terms/terms_en-GB.html",
-    "//components/resources/terms/terms_en.html",
-    "//components/resources/terms/terms_es-419.html",
-    "//components/resources/terms/terms_es.html",
-    "//components/resources/terms/terms_fa.html",
-    "//components/resources/terms/terms_fi.html",
-    "//components/resources/terms/terms_fr.html",
-    "//components/resources/terms/terms_he.html",
-    "//components/resources/terms/terms_hi.html",
-    "//components/resources/terms/terms_hr.html",
-    "//components/resources/terms/terms_hu.html",
-    "//components/resources/terms/terms_id.html",
-    "//components/resources/terms/terms_it.html",
-    "//components/resources/terms/terms_ja.html",
-    "//components/resources/terms/terms_ko.html",
-    "//components/resources/terms/terms_lt.html",
-    "//components/resources/terms/terms_nb.html",
-    "//components/resources/terms/terms_nl.html",
-    "//components/resources/terms/terms_pl.html",
-    "//components/resources/terms/terms_pt-BR.html",
-    "//components/resources/terms/terms_pt-PT.html",
-    "//components/resources/terms/terms_ro.html",
-    "//components/resources/terms/terms_ru.html",
-    "//components/resources/terms/terms_sk.html",
-    "//components/resources/terms/terms_sr.html",
-    "//components/resources/terms/terms_sv.html",
-    "//components/resources/terms/terms_th.html",
-    "//components/resources/terms/terms_tr.html",
-    "//components/resources/terms/terms_uk.html",
-    "//components/resources/terms/terms_vi.html",
-    "//components/resources/terms/terms_zh-CN.html",
-    "//components/resources/terms/terms_zh-TW.html",
-  ]
-  outputs = [
-    "{{bundle_resources_dir}}/{{source_file_part}}",
-  ]
-}
diff --git a/ios/chrome/browser/passwords/BUILD.gn b/ios/chrome/browser/passwords/BUILD.gn
index d8ca5d4..8aea29c 100644
--- a/ios/chrome/browser/passwords/BUILD.gn
+++ b/ios/chrome/browser/passwords/BUILD.gn
@@ -96,6 +96,7 @@
 }
 
 source_set("unit_tests") {
+  configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
     "credential_manager_js_unittest.mm",
diff --git a/ios/chrome/browser/passwords/credential_manager_js_unittest.mm b/ios/chrome/browser/passwords/credential_manager_js_unittest.mm
index 37f0d66..f9f8fbf 100644
--- a/ios/chrome/browser/passwords/credential_manager_js_unittest.mm
+++ b/ios/chrome/browser/passwords/credential_manager_js_unittest.mm
@@ -5,7 +5,6 @@
 #include <memory>
 
 #include "base/mac/foundation_util.h"
-#import "base/mac/scoped_nsobject.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #import "ios/chrome/browser/passwords/js_credential_manager.h"
@@ -19,6 +18,10 @@
 #include "testing/gtest_mac.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 using ::testing::_;
@@ -59,9 +62,9 @@
 
   void SetUp() override {
     web::WebTestWithWebState::SetUp();
-    js_credential_manager_.reset(base::mac::ObjCCastStrict<JSCredentialManager>(
-        [[web_state()->GetJSInjectionReceiver()
-            instanceOfClass:[JSCredentialManager class]] retain]));
+    js_credential_manager_ = base::mac::ObjCCastStrict<JSCredentialManager>(
+        [web_state()->GetJSInjectionReceiver()
+            instanceOfClass:[JSCredentialManager class]]);
     observer_.reset(new MockWebStateObserver(web_state()));
   }
 
@@ -255,7 +258,7 @@
 
  private:
   // Manager for injected credential manager JavaScript.
-  base::scoped_nsobject<JSCredentialManager> js_credential_manager_;
+  JSCredentialManager* js_credential_manager_;
 
   // Mock observer for testing.
   std::unique_ptr<MockWebStateObserver> observer_;
diff --git a/ios/chrome/browser/passwords/credential_manager_unittest.mm b/ios/chrome/browser/passwords/credential_manager_unittest.mm
index a66d524..da6a3d07 100644
--- a/ios/chrome/browser/passwords/credential_manager_unittest.mm
+++ b/ios/chrome/browser/passwords/credential_manager_unittest.mm
@@ -7,7 +7,6 @@
 #include <memory>
 #include <utility>
 
-#include "base/mac/bind_objc_block.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -31,6 +30,10 @@
 #include "third_party/ocmock/gtest_support.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 using testing::Return;
 
 namespace {
@@ -105,9 +108,9 @@
 // Returns a block that takes a string argument and returns whether it is equal
 // to |string|.
 StringPredicate EqualsString(const char* string) {
-  return [[^BOOL(NSString* other) {
+  return [^BOOL(NSString* other) {
     return [base::SysUTF8ToNSString(string) isEqualToString:other];
-  } copy] autorelease];
+  } copy];
 }
 
 // A stub PasswordManagerClient for testing.
@@ -191,11 +194,11 @@
     web::WebTestWithWebState::SetUp();
     id originalMock =
         [OCMockObject niceMockForClass:[JSCredentialManager class]];
-    mock_js_credential_manager_.reset([[MockJSCredentialManager alloc]
-        initWithRepresentedObject:originalMock]);
-    credential_manager_.reset(new CredentialManager(
-        web_state(), &stub_client_, &stub_driver_,
-        static_cast<id>(mock_js_credential_manager_.get())));
+    mock_js_credential_manager_ = [[MockJSCredentialManager alloc]
+        initWithRepresentedObject:originalMock];
+    credential_manager_.reset(
+        new CredentialManager(web_state(), &stub_client_, &stub_driver_,
+                              static_cast<id>(mock_js_credential_manager_)));
     LoadHtml(@"", GURL(kTestURL));
   }
 
@@ -263,7 +266,7 @@
   password_manager::StubPasswordManagerDriver stub_driver_;
 
   // Mock for JSCredentialManager.
-  base::scoped_nsobject<MockJSCredentialManager> mock_js_credential_manager_;
+  MockJSCredentialManager* mock_js_credential_manager_;
 
   // CredentialManager for testing.
   std::unique_ptr<CredentialManager> credential_manager_;
diff --git a/ios/chrome/browser/passwords/password_controller_js_unittest.mm b/ios/chrome/browser/passwords/password_controller_js_unittest.mm
index 5b557d2..77f0e1d8 100644
--- a/ios/chrome/browser/passwords/password_controller_js_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_js_unittest.mm
@@ -10,6 +10,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 // Unit tests for ios/chrome/browser/web/resources/password_controller.js
 namespace {
 
diff --git a/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm b/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm
index ea5a861..8afcc2c 100644
--- a/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm
@@ -4,7 +4,6 @@
 
 #include <memory>
 
-#import "base/mac/scoped_nsobject.h"
 #include "base/memory/ptr_util.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
@@ -13,6 +12,10 @@
 #import "ios/web/public/test/web_test_with_web_state.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 class IncognitoPasswordManagerClient
@@ -42,11 +45,10 @@
  public:
   void SetUp() override {
     web::WebTestWithWebState::SetUp();
-    password_controller_.reset([[PasswordController alloc]
+    password_controller_ = [[PasswordController alloc]
            initWithWebState:&off_the_record_web_state_
         passwordsUiDelegate:nil
-                     client:base::MakeUnique<
-                                IncognitoPasswordManagerClient>()]);
+                     client:base::MakeUnique<IncognitoPasswordManagerClient>()];
   }
 
   void TearDown() override {
@@ -56,7 +58,7 @@
 
  protected:
   OffTheRecordWebState off_the_record_web_state_;
-  base::scoped_nsobject<PasswordController> password_controller_;
+  PasswordController* password_controller_;
 };
 
 // Check that if the PasswordController is told (by the PasswordManagerClient)
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm
index f02a0f7..fda0914 100644
--- a/ios/chrome/browser/passwords/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -11,7 +11,6 @@
 
 #include "base/json/json_reader.h"
 #include "base/mac/bind_objc_block.h"
-#import "base/mac/scoped_nsobject.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/sys_string_conversions.h"
@@ -39,6 +38,10 @@
 #import "third_party/ocmock/OCMock/OCPartialMockObject.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 using autofill::PasswordForm;
 using autofill::PasswordFormFillData;
 using testing::Return;
@@ -85,17 +88,16 @@
 // using the given |store|. If not null, |weak_client| is filled with a
 // non-owning pointer to the created client. The created controller is
 // returned.
-base::scoped_nsobject<PasswordController> CreatePasswordController(
+PasswordController* CreatePasswordController(
     web::WebState* web_state,
     password_manager::PasswordStore* store,
     MockPasswordManagerClient** weak_client) {
   auto client = base::MakeUnique<MockPasswordManagerClient>(store);
   if (weak_client)
     *weak_client = client.get();
-  return base::scoped_nsobject<PasswordController>([[PasswordController alloc]
-         initWithWebState:web_state
-      passwordsUiDelegate:nil
-                   client:std::move(client)]);
+  return [[PasswordController alloc] initWithWebState:web_state
+                                  passwordsUiDelegate:nil
+                                               client:std::move(client)];
 }
 
 }  // namespace
@@ -129,8 +131,6 @@
 
 @property(nonatomic, copy) NSArray* suggestions;
 
-- (void)dealloc;
-
 @end
 
 @implementation PasswordsTestSuggestionController
@@ -141,10 +141,6 @@
   self.suggestions = suggestions;
 }
 
-- (void)dealloc {
-  [_suggestions release];
-  [super dealloc];
-}
 
 @end
 
@@ -164,12 +160,12 @@
       // otherwise [passwordController_ suggestionProvider] will be retained
       // until PlatformTest teardown, at which point all Chrome objects are
       // already gone and teardown may access invalid memory.
-      suggestionController_.reset([[PasswordsTestSuggestionController alloc]
+      suggestionController_ = [[PasswordsTestSuggestionController alloc]
           initWithWebState:web_state()
-                 providers:@[ [passwordController_ suggestionProvider] ]]);
-      accessoryViewController_.reset([[FormInputAccessoryViewController alloc]
+                 providers:@[ [passwordController_ suggestionProvider] ]];
+      accessoryViewController_ = [[FormInputAccessoryViewController alloc]
           initWithWebState:web_state()
-                 providers:@[ [suggestionController_ accessoryViewProvider] ]]);
+                 providers:@[ [suggestionController_ accessoryViewProvider] ]];
     }
   }
 
@@ -218,7 +214,7 @@
         ++failure_count;
         // Fetches the completion handler from |invocation| and calls it with
         // failure status.
-        void (^completionHandler)(BOOL);
+        __unsafe_unretained void (^completionHandler)(BOOL);
         const NSInteger kArgOffset = 1;
         const NSInteger kCompletionHandlerArgIndex = 4;
         [invocation getArgument:&completionHandler
@@ -235,15 +231,13 @@
   }
 
   // SuggestionController for testing.
-  base::scoped_nsobject<PasswordsTestSuggestionController>
-      suggestionController_;
+  PasswordsTestSuggestionController* suggestionController_;
 
   // FormInputAccessoryViewController for testing.
-  base::scoped_nsobject<FormInputAccessoryViewController>
-      accessoryViewController_;
+  FormInputAccessoryViewController* accessoryViewController_;
 
   // PasswordController for testing.
-  base::scoped_nsobject<PasswordController> passwordController_;
+  PasswordController* passwordController_;
 
   scoped_refptr<password_manager::PasswordStore> store_;
 };
@@ -1266,7 +1260,7 @@
       .WillByDefault(testing::Return(browser_state.get()));
 
   MockPasswordManagerClient* weak_client = nullptr;
-  base::scoped_nsobject<PasswordController> passwordController =
+  PasswordController* passwordController =
       CreatePasswordController(&web_state, nullptr, &weak_client);
   static_cast<TestingPrefServiceSimple*>(weak_client->GetPrefs())
       ->registry()
diff --git a/ios/chrome/browser/passwords/password_generation_agent_unittest.mm b/ios/chrome/browser/passwords/password_generation_agent_unittest.mm
index 744518e..d96792be 100644
--- a/ios/chrome/browser/passwords/password_generation_agent_unittest.mm
+++ b/ios/chrome/browser/passwords/password_generation_agent_unittest.mm
@@ -9,9 +9,9 @@
 
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
-#import "base/mac/scoped_nsobject.h"
 #include "base/mac/scoped_objc_class_swizzler.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -35,6 +35,10 @@
 #include "third_party/ocmock/gtest_support.h"
 #include "url/gurl.h"
 
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
 namespace {
 
 NSString* const kAccountCreationFormName = @"create-foo-account";
@@ -94,7 +98,7 @@
 @implementation DonorWindow
 
 - (void)chromeExecuteCommand:(id)sender {
-  g_chrome_execute_command_sender = [sender retain];
+  g_chrome_execute_command_sender = sender;
 }
 
 @end
@@ -112,7 +116,6 @@
   }
 
   ~ScopedWindowSwizzler() {
-    [g_chrome_execute_command_sender release];
     g_chrome_execute_command_sender = nil;
   }
 
@@ -215,23 +218,23 @@
  public:
   void SetUp() override {
     web::WebTestWithWebState::SetUp();
-    mock_js_suggestion_manager_.reset(
-        [[OCMockObject niceMockForClass:[JsSuggestionManager class]] retain]);
-    mock_js_password_manager_.reset(
-        [[OCMockObject niceMockForClass:[JsPasswordManager class]] retain]);
-    mock_ui_delegate_.reset([[MockPasswordsUiDelegate alloc] init]);
-    test_web_state_.reset(new web::TestWebState);
-    agent_.reset([[PasswordGenerationAgent alloc]
+    mock_js_suggestion_manager_ =
+        [OCMockObject niceMockForClass:[JsSuggestionManager class]];
+    mock_js_password_manager_ =
+        [OCMockObject niceMockForClass:[JsPasswordManager class]];
+    mock_ui_delegate_ = [[MockPasswordsUiDelegate alloc] init];
+    test_web_state_ = base::MakeUnique<web::TestWebState>();
+    agent_ = [[PasswordGenerationAgent alloc]
              initWithWebState:test_web_state_.get()
               passwordManager:nullptr
         passwordManagerDriver:nullptr
             JSPasswordManager:mock_js_password_manager_
           JSSuggestionManager:mock_js_suggestion_manager_
-          passwordsUiDelegate:mock_ui_delegate_]);
+          passwordsUiDelegate:mock_ui_delegate_];
     @autoreleasepool {
-      accessory_view_controller_.reset([[FormInputAccessoryViewController alloc]
+      accessory_view_controller_ = [[FormInputAccessoryViewController alloc]
           initWithWebState:test_web_state_.get()
-                 providers:@[ agent_ ]]);
+                 providers:@[ agent_ ]];
     }
   }
 
@@ -287,11 +290,11 @@
 
  protected:
   // Returns the current generation agent.
-  PasswordGenerationAgent* agent() { return agent_.get(); }
+  PasswordGenerationAgent* agent() { return agent_; }
 
   // Returns the current accessory view controller.
   FormInputAccessoryViewController* accessory_controller() {
-    return accessory_view_controller_.get();
+    return accessory_view_controller_;
   }
 
  private:
@@ -299,20 +302,19 @@
   std::unique_ptr<web::TestWebState> test_web_state_;
 
   // Mock for JsSuggestionManager;
-  base::scoped_nsobject<id> mock_js_suggestion_manager_;
+  id mock_js_suggestion_manager_;
 
   // Mock for JsPasswordManager.
-  base::scoped_nsobject<id> mock_js_password_manager_;
+  id mock_js_password_manager_;
 
   // Mock for the UI delegate.
-  base::scoped_nsobject<MockPasswordsUiDelegate> mock_ui_delegate_;
+  MockPasswordsUiDelegate* mock_ui_delegate_;
 
   // Controller that shows custom input accessory views.
-  base::scoped_nsobject<FormInputAccessoryViewController>
-      accessory_view_controller_;
+  FormInputAccessoryViewController* accessory_view_controller_;
 
   // The current generation agent.
-  base::scoped_nsobject<PasswordGenerationAgent> agent_;
+  PasswordGenerationAgent* agent_;
 };
 
 // Tests that local heuristics skip forms with GAIA realm.
@@ -482,7 +484,7 @@
   NSString* password = @"abc";
 
   [[[mock_js_password_manager() stub] andDo:^(NSInvocation* invocation) {
-    void (^completion_handler)(BOOL);
+    __unsafe_unretained void (^completion_handler)(BOOL);
     [invocation getArgument:&completion_handler atIndex:4];
     completion_handler(YES);
   }] fillPasswordForm:kAccountCreationFormName
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index 9a17561..ebaf2c47 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -44,7 +44,6 @@
   deps = [
     "//base",
     "//base:i18n",
-    "//ios/chrome/app/resources:terms_of_service_bundle",
     "//ios/chrome/browser",
     "//ios/chrome/browser/favicon",
     "//ios/chrome/browser/ui/commands",
@@ -108,6 +107,49 @@
     "resources/keyboard_button@2x~ipad.png",
     "resources/keyboard_button@3x.png",
     "resources/keyboard_button~ipad.png",
+
+    # On iOS, the terms of service file need to be loaded from the application
+    # bundle, not from a datapack. As GetTermsOfServicePath() returns path to
+    # those files, they are added to //ios/chrome/browser/ui:resources.
+    "//components/resources/terms/terms_ar.html",
+    "//components/resources/terms/terms_bg.html",
+    "//components/resources/terms/terms_ca.html",
+    "//components/resources/terms/terms_cs.html",
+    "//components/resources/terms/terms_da.html",
+    "//components/resources/terms/terms_de.html",
+    "//components/resources/terms/terms_el.html",
+    "//components/resources/terms/terms_en-GB.html",
+    "//components/resources/terms/terms_en.html",
+    "//components/resources/terms/terms_es-419.html",
+    "//components/resources/terms/terms_es.html",
+    "//components/resources/terms/terms_fa.html",
+    "//components/resources/terms/terms_fi.html",
+    "//components/resources/terms/terms_fr.html",
+    "//components/resources/terms/terms_he.html",
+    "//components/resources/terms/terms_hi.html",
+    "//components/resources/terms/terms_hr.html",
+    "//components/resources/terms/terms_hu.html",
+    "//components/resources/terms/terms_id.html",
+    "//components/resources/terms/terms_it.html",
+    "//components/resources/terms/terms_ja.html",
+    "//components/resources/terms/terms_ko.html",
+    "//components/resources/terms/terms_lt.html",
+    "//components/resources/terms/terms_nb.html",
+    "//components/resources/terms/terms_nl.html",
+    "//components/resources/terms/terms_pl.html",
+    "//components/resources/terms/terms_pt-BR.html",
+    "//components/resources/terms/terms_pt-PT.html",
+    "//components/resources/terms/terms_ro.html",
+    "//components/resources/terms/terms_ru.html",
+    "//components/resources/terms/terms_sk.html",
+    "//components/resources/terms/terms_sr.html",
+    "//components/resources/terms/terms_sv.html",
+    "//components/resources/terms/terms_th.html",
+    "//components/resources/terms/terms_tr.html",
+    "//components/resources/terms/terms_uk.html",
+    "//components/resources/terms/terms_vi.html",
+    "//components/resources/terms/terms_zh-CN.html",
+    "//components/resources/terms/terms_zh-TW.html",
   ]
   outputs = [
     "{{bundle_resources_dir}}/{{source_file_part}}",
diff --git a/ios/chrome/test/earl_grey/resources/Chrome.entitlements b/ios/chrome/test/earl_grey/resources/Chrome.entitlements
new file mode 100644
index 0000000..682f4cb
--- /dev/null
+++ b/ios/chrome/test/earl_grey/resources/Chrome.entitlements
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>application-identifier</key>
+  <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string>
+</dict>
+</plist>
diff --git a/ios/web/public/test/test_web_state.h b/ios/web/public/test/test_web_state.h
index c156c80..4b7f139 100644
--- a/ios/web/public/test/test_web_state.h
+++ b/ios/web/public/test/test_web_state.h
@@ -9,6 +9,7 @@
 
 #include <string>
 
+#include "base/observer_list.h"
 #include "base/strings/string16.h"
 #include "ios/web/public/web_state/url_verification_constants.h"
 #include "ios/web/public/web_state/web_state.h"
@@ -57,8 +58,11 @@
   CRWWebViewProxyType GetWebViewProxy() const override;
   bool IsShowingWebInterstitial() const override;
   WebInterstitial* GetWebInterstitial() const override;
-  void AddObserver(WebStateObserver* observer) override {}
-  void RemoveObserver(WebStateObserver* observer) override {}
+
+  void AddObserver(WebStateObserver* observer) override;
+
+  void RemoveObserver(WebStateObserver* observer) override;
+
   void AddPolicyDecider(WebStatePolicyDecider* decider) override {}
   void RemovePolicyDecider(WebStatePolicyDecider* decider) override {}
   int DownloadImage(const GURL& url,
@@ -84,6 +88,9 @@
   bool content_is_html_;
   std::string mime_type_;
   std::string content_language_;
+
+  // A list of observers notified when page state changes. Weak references.
+  base::ObserverList<WebStateObserver, true> observers_;
 };
 
 }  // namespace web
diff --git a/ios/web/public/test/test_web_state.mm b/ios/web/public/test/test_web_state.mm
index 3906434..3d35c1f7 100644
--- a/ios/web/public/test/test_web_state.mm
+++ b/ios/web/public/test/test_web_state.mm
@@ -7,16 +7,30 @@
 #include <stdint.h>
 
 #include "base/callback.h"
+#include "ios/web/public/web_state/web_state_observer.h"
 
 namespace web {
 
+void TestWebState::AddObserver(WebStateObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void TestWebState::RemoveObserver(WebStateObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 TestWebState::TestWebState()
     : web_usage_enabled_(false),
       is_loading_(false),
       trust_level_(kAbsolute),
       content_is_html_(true) {}
 
-TestWebState::~TestWebState() = default;
+TestWebState::~TestWebState() {
+  for (auto& observer : observers_)
+    observer.WebStateDestroyed();
+  for (auto& observer : observers_)
+    observer.ResetWebState();
+};
 
 WebStateDelegate* TestWebState::GetDelegate() {
   return nil;
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h
index c48eed6..d0b76cd 100644
--- a/ios/web/public/web_state/web_state_observer.h
+++ b/ios/web/public/web_state/web_state_observer.h
@@ -20,6 +20,7 @@
 struct FaviconURL;
 struct LoadCommittedDetails;
 class WebState;
+class TestWebState;
 class WebStateImpl;
 
 enum class PageLoadCompletionStatus : bool { SUCCESS = 0, FAILURE = 1 };
@@ -156,6 +157,7 @@
 
  private:
   friend class WebStateImpl;
+  friend class TestWebState;
 
   // Stops observing the current web state.
   void ResetWebState();
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 198f007..988812a 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2162,3 +2162,8 @@
 
 # Added 2016-11-30
 crbug.com/669911 [ Win7 Win10 ] virtual/threaded/animations/zoom-responsive-transform-animation.html [ Pass Failure Timeout ]
+
+# Added 2016-12-06
+crbug.com/671618 http/tests/websocket/workers/worker-reload.html [ Pass Timeout ]
+crbug.com/671618 virtual/mojo-loading/http/tests/websocket/workers/worker-reload.html [ Pass Timeout ]
+crbug.com/671618 virtual/mojo-loading/http/tests/websocket/workers/worker-shutdown-race.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-motion-rotation.html b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-motion-rotation.html
new file mode 100644
index 0000000..3c696f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-motion-rotation.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+
+<div id="target" class="p"></div>
+<script>
+test(function() {
+  assert_false(internals.isCSSPropertyUseCounted(document, "motion-rotation"));
+
+  var styleElement = document.createElement('style');
+  styleElement.textContent = ".p { motion-rotation: 0deg; }";
+  document.head.appendChild(styleElement);
+  getComputedStyle(target);
+
+  assert_true(internals.isCSSPropertyUseCounted(document, "motion-rotation"));
+  assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotation"));
+  assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotate"));
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotate.html b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotate.html
new file mode 100644
index 0000000..34d93fe
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotate.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+
+<div id="target" class="p"></div>
+<script>
+test(function() {
+  assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotate"));
+
+  var styleElement = document.createElement('style');
+  styleElement.textContent = ".p { offset-rotate: 0deg; }";
+  document.head.appendChild(styleElement);
+  getComputedStyle(target);
+
+  assert_true(internals.isCSSPropertyUseCounted(document, "offset-rotate"));
+  assert_false(internals.isCSSPropertyUseCounted(document, "motion-rotation"));
+  assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotation"));
+});
+</script>
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotation.html b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotation.html
new file mode 100644
index 0000000..7deb34d7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/css3/motion-path/property-use-count-offset-rotation.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<head>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+</head>
+
+<div id="target" class="p"></div>
+<script>
+test(function() {
+  assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotation"));
+
+  var styleElement = document.createElement('style');
+  styleElement.textContent = ".p { offset-rotation: 0deg; }";
+  document.head.appendChild(styleElement);
+  getComputedStyle(target);
+
+  assert_true(internals.isCSSPropertyUseCounted(document, "offset-rotation"));
+  assert_false(internals.isCSSPropertyUseCounted(document, "motion-rotation"));
+  assert_false(internals.isCSSPropertyUseCounted(document, "offset-rotate"));
+});
+</script>
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index 34a22e9e..5a9b9f7c 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -1312,6 +1312,7 @@
     "timing/PerformanceObserverTest.cpp",
     "timing/PerformanceTest.cpp",
     "workers/DedicatedWorkerTest.cpp",
+    "workers/MainThreadWorkletTest.cpp",
     "workers/WorkerThreadTest.cpp",
     "workers/WorkerThreadTestHelper.h",
     "xml/XPathFunctionsTest.cpp",
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index 43d8097..3369b6a 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -10,7 +10,7 @@
 #include "core/frame/FrameHost.h"
 #include "core/frame/LocalFrame.h"
 #include "core/inspector/ConsoleMessage.h"
-#include "core/workers/WorkerGlobalScope.h"
+#include "core/workers/WorkerOrWorkletGlobalScope.h"
 
 namespace {
 
@@ -148,8 +148,8 @@
     Deprecation::countDeprecation(*toDocument(context), feature);
     return;
   }
-  if (context->isWorkerGlobalScope())
-    toWorkerGlobalScope(context)->countDeprecation(feature);
+  if (context->isWorkerOrWorkletGlobalScope())
+    toWorkerOrWorkletGlobalScope(context)->countDeprecation(feature);
 }
 
 void Deprecation::countDeprecation(const Document& document,
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp
index e07d0d6..80e9609 100644
--- a/third_party/WebKit/Source/core/frame/UseCounter.cpp
+++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -34,7 +34,7 @@
 #include "core/frame/FrameHost.h"
 #include "core/frame/LocalFrame.h"
 #include "core/inspector/ConsoleMessage.h"
-#include "core/workers/WorkerGlobalScope.h"
+#include "core/workers/WorkerOrWorkletGlobalScope.h"
 #include "platform/Histogram.h"
 #include "platform/tracing/TraceEvent.h"
 
@@ -45,7 +45,7 @@
 }
 
 // Make sure update_use_counter_css.py was run which updates histograms.xml.
-constexpr int kMaximumCSSSampleId = 547;
+constexpr int kMaximumCSSSampleId = 548;
 
 }  // namespace
 
@@ -1050,9 +1050,7 @@
       return 540;
     case CSSPropertyOffsetPath:
       return 541;
-    case CSSPropertyOffsetRotate:
     case CSSPropertyOffsetRotation:
-      // TODO(ericwilligers): Distinct use counter for CSSPropertyOffsetRotate.
       return 542;
     case CSSPropertyOffset:
       return 543;
@@ -1064,6 +1062,8 @@
       return 546;
     case CSSPropertyCaretColor:
       return 547;
+    case CSSPropertyOffsetRotate:
+      return 548;
     // 1. Add new features above this line (don't change the assigned numbers of
     // the existing items).
     // 2. Update kMaximumCSSSampleId with the new maximum value.
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp
index 49ae246..32d8071 100644
--- a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.cpp
@@ -618,6 +618,8 @@
   bool allowDynamicOther = other[0]->m_allowDynamic;
   bool allowHashedAttributesOther = other[0]->m_allowHashedAttributes;
   bool isHashOrNoncePresentOther = other[0]->isHashOrNoncePresent();
+  HashSet<String> noncesB = other[0]->m_nonces;
+  HashSet<CSPHashValue> hashesB = other[0]->m_hashes;
 
   for (size_t i = 1; i < other.size(); i++) {
     allowInlineOther = allowInlineOther && other[i]->m_allowInline;
@@ -627,9 +629,14 @@
         allowHashedAttributesOther && other[i]->m_allowHashedAttributes;
     isHashOrNoncePresentOther =
         isHashOrNoncePresentOther && other[i]->isHashOrNoncePresent();
+    noncesB = other[i]->getIntersectNonces(noncesB);
+    hashesB = other[i]->getIntersectHashes(hashesB);
     normalizedB = other[i]->getIntersectCSPSources(normalizedB);
   }
 
+  if (!subsumesNoncesAndHashes(noncesB, hashesB))
+    return false;
+
   const ContentSecurityPolicy::DirectiveType type =
       ContentSecurityPolicy::getDirectiveType(m_directiveName);
   if (type == ContentSecurityPolicy::DirectiveType::ScriptSrc ||
@@ -649,6 +656,49 @@
   return CSPSource::firstSubsumesSecond(normalizedA, normalizedB);
 }
 
+bool SourceListDirective::subsumesNoncesAndHashes(
+    const HashSet<String>& nonces,
+    const HashSet<CSPHashValue> hashes) const {
+  for (const auto& nonce : nonces) {
+    if (!m_nonces.contains(nonce))
+      return false;
+  }
+  for (const auto& hash : hashes) {
+    if (!m_hashes.contains(hash))
+      return false;
+  }
+
+  return true;
+}
+
+HashSet<String> SourceListDirective::getIntersectNonces(
+    const HashSet<String>& other) const {
+  if (!m_nonces.size() || !other.size())
+    return !m_nonces.size() ? m_nonces : other;
+
+  HashSet<String> normalized;
+  for (const auto& nonce : m_nonces) {
+    if (other.contains(nonce))
+      normalized.add(nonce);
+  }
+
+  return normalized;
+}
+
+HashSet<CSPHashValue> SourceListDirective::getIntersectHashes(
+    const HashSet<CSPHashValue>& other) const {
+  if (!m_hashes.size() || !other.size())
+    return !m_hashes.size() ? m_hashes : other;
+
+  HashSet<CSPHashValue> normalized;
+  for (const auto& hash : m_hashes) {
+    if (other.contains(hash))
+      normalized.add(hash);
+  }
+
+  return normalized;
+}
+
 HeapHashMap<String, Member<CSPSource>>
 SourceListDirective::getIntersectSchemesOnly(
     const HeapVector<Member<CSPSource>>& other) const {
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h
index 6a3bbd5..cd01cb5 100644
--- a/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h
+++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirective.h
@@ -56,6 +56,8 @@
   FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, GetIntersectCSPSources);
   FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest,
                            GetIntersectCSPSourcesSchemes);
+  FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, GetIntersectNonces);
+  FRIEND_TEST_ALL_PREFIXES(SourceListDirectiveTest, GetIntersectHashes);
   FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, GetSourceVector);
   FRIEND_TEST_ALL_PREFIXES(CSPDirectiveListTest, OperativeDirectiveGivenType);
 
@@ -97,10 +99,15 @@
                              CSPSource*);
 
   bool hasSourceMatchInList(const KURL&, ResourceRequest::RedirectStatus) const;
+  HashSet<String> getIntersectNonces(const HashSet<String>& other) const;
+  HashSet<CSPHashValue> getIntersectHashes(
+      const HashSet<CSPHashValue>& other) const;
   HeapVector<Member<CSPSource>> getIntersectCSPSources(
       const HeapVector<Member<CSPSource>>& other) const;
   HeapHashMap<String, Member<CSPSource>> getIntersectSchemesOnly(
       const HeapVector<Member<CSPSource>>& other) const;
+  bool subsumesNoncesAndHashes(const HashSet<String>& nonces,
+                               const HashSet<CSPHashValue> hashes) const;
 
   Member<ContentSecurityPolicy> m_policy;
   HeapVector<Member<CSPSource>> m_list;
diff --git a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
index 0e1fcc3..03f858d 100644
--- a/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/SourceListDirectiveTest.cpp
@@ -851,4 +851,204 @@
   }
 }
 
+TEST_F(SourceListDirectiveTest, GetIntersectNonces) {
+  SourceListDirective listA(
+      "script-src",
+      "http://example.com 'nonce-abc' 'nonce-xyz' 'nonce-' 'unsafe-inline'",
+      csp.get());
+  struct TestCase {
+    String sources;
+    String expected;
+  } cases[] = {
+      {"http:", ""},
+      {"http://example.com", ""},
+      {"example.com", ""},
+      {"'unsafe-inline'", ""},
+      {"'nonce-abc'", "'nonce-abc'"},
+      {"'nonce-xyz'", "'nonce-xyz'"},
+      {"'nonce-123'", ""},
+      {"'nonce-abc' 'nonce-xyz'", "'nonce-abc' 'nonce-xyz'"},
+      {"'nonce-abc' 'nonce-xyz' 'nonce'", "'nonce-abc' 'nonce-xyz'"},
+      {"'nonce-abc' 'nonce-123'", "'nonce-abc'"},
+      {"'nonce-123' 'nonce-123'", ""},
+      {"'nonce-123' 'nonce-abc'", "'nonce-abc'"},
+      {"'nonce-123' 'nonce-xyz'", "'nonce-xyz'"},
+      {"'nonce-123' 'nonce-xyx'", ""},
+  };
+
+  for (const auto& test : cases) {
+    SourceListDirective listB("script-src", test.sources, csp.get());
+    HashSet<String> normalized = listA.getIntersectNonces(listB.m_nonces);
+
+    SourceListDirective expectedList("script-src", test.expected, csp.get());
+    HashSet<String> expected = expectedList.m_nonces;
+    EXPECT_EQ(normalized.size(), expected.size());
+    for (const auto& nonce : normalized) {
+      EXPECT_TRUE(expected.contains(nonce));
+    }
+  }
+}
+
+TEST_F(SourceListDirectiveTest, GetIntersectHashes) {
+  SourceListDirective listA(
+      "script-src",
+      "http://example.com 'sha256-abc123' 'sha384-' 'sha512-321cba' 'self'",
+      csp.get());
+  struct TestCase {
+    String sources;
+    String expected;
+  } cases[] = {
+      {"http:", ""},
+      {"http://example.com", ""},
+      {"example.com", ""},
+      {"'unsafe-inline'", ""},
+      {"'sha384-abc'", ""},
+      {"'sha384-'", ""},
+      {"'sha256-abc123'", "'sha256-abc123'"},
+      {"'sha256-abc123' 'sha384-'", "'sha256-abc123'"},
+      {"'sha256-abc123' 'sha512-321cba'", "'sha512-321cba' 'sha256-abc123'"},
+      {"'sha256-abc123' 'sha384-' 'sha512-321cba'",
+       "'sha256-abc123' 'sha512-321cba' "},
+      {"'sha256-else' 'sha384-' 'sha512-321cba'", "'sha512-321cba' "},
+      {"'hash-123'", ""},
+      {"'sha256-123'", ""},
+  };
+
+  for (const auto& test : cases) {
+    SourceListDirective listB("script-src", test.sources, csp.get());
+    HashSet<CSPHashValue> normalized = listA.getIntersectHashes(listB.m_hashes);
+
+    SourceListDirective expectedList("script-src", test.expected, csp.get());
+    HashSet<CSPHashValue> expected = expectedList.m_hashes;
+    EXPECT_EQ(normalized.size(), expected.size());
+    for (const auto& hash : normalized) {
+      EXPECT_TRUE(expected.contains(hash));
+    }
+  }
+}
+
+TEST_F(SourceListDirectiveTest, SubsumesNoncesAndHashes) {
+  struct TestCase {
+    bool isScriptSrc;
+    String sourcesA;
+    std::vector<String> sourcesB;
+    bool expected;
+  } cases[] = {
+      // Check nonces.
+      {true,
+       "http://example1.com/foo/ 'unsafe-inline' 'nonce-abc'",
+       {"'unsafe-inline'"},
+       false},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'nonce-abc'",
+       {"'nonce-abc'"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline'",
+       {"'unsafe-inline' 'nonce-yay'", "'nonce-yay'"},
+       false},
+      {true,
+       "http://example1.com/foo/ 'self' 'nonce-yay'",
+       {"'unsafe-inline' 'nonce-yay'", "'nonce-yay'"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'nonce-abc' 'nonce-yay'",
+       {"'unsafe-inline' https://example.test/"},
+       false},
+      {true,
+       "http://example1.com/foo/ 'self' 'nonce-abc' 'nonce-yay'",
+       {"'nonce-abc' https://example1.com/foo/"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'nonce-yay' "
+       "'strict-dynamic'",
+       {"https://example.test/ 'nonce-yay'"},
+       false},
+      {false,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'nonce-yay' "
+       "'strict-dynamic'",
+       {"'nonce-yay' https://example1.com/foo/"},
+       true},
+      // Check hashes.
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'",
+       {"http://example1.com/foo/page.html 'strict-dynamic'",
+        "https://example1.com/foo/ 'sha512-321cba'"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'",
+       {"http://some-other.com/ 'strict-dynamic' 'sha512-321cba'",
+        "http://example1.com/foo/ 'unsafe-inline' 'sha512-321cba'"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'",
+       {"http://example1.com/foo/ 'sha512-321abc' 'sha512-321cba'",
+        "http://example1.com/foo/ 'sha512-321abc' 'sha512-321cba'"},
+       false},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321cba'",
+       {"http://example1.com/foo/ 'unsafe-inline'",
+        "http://example1.com/foo/ 'sha512-321cba'"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc'",
+       {"http://example1.com/foo/ 'unsafe-inline' 'sha512-321abc'",
+        "http://example1.com/foo/ 'sha512-321abc'"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc'",
+       {"'unsafe-inline' 'sha512-321abc'",
+        "http://example1.com/foo/ 'sha512-321abc'"},
+       true},
+      // Nonces and hashes together.
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' "
+       "'nonce-abc'",
+       {"'unsafe-inline' 'sha512-321abc' 'self'",
+        "'unsafe-inline''sha512-321abc' https://example.test/"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' "
+       "'nonce-abc'",
+       {"'unsafe-inline' 'sha512-321abc' 'self' 'nonce-abc'",
+        "'sha512-321abc' https://example.test/"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' "
+       "'nonce-abc'",
+       {"'unsafe-inline' 'sha512-321abc' 'self'",
+        " 'sha512-321abc' https://example.test/ 'nonce-abc'"},
+       true},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' "
+       "'nonce-abc'",
+       {"'unsafe-inline' 'sha512-321abc' 'self' 'nonce-xyz'",
+        "unsafe-inline' 'sha512-321abc' https://example.test/ 'nonce-xyz'"},
+       false},
+      {true,
+       "http://example1.com/foo/ 'self' 'unsafe-inline' 'sha512-321abc' "
+       "'nonce-abc'",
+       {"'unsafe-inline' 'sha512-321abc' 'self' 'sha512-xyz'",
+        "unsafe-inline' 'sha512-321abc' https://example.test/ 'sha512-xyz'"},
+       false},
+
+  };
+
+  for (const auto& test : cases) {
+    SourceListDirective A(test.isScriptSrc ? "script-src" : "style-src",
+                          test.sourcesA, csp.get());
+    ContentSecurityPolicy* cspB =
+        SetUpWithOrigin("https://another.test/image.png");
+
+    HeapVector<Member<SourceListDirective>> vectorB;
+    for (const auto& sources : test.sourcesB) {
+      SourceListDirective* member = new SourceListDirective(
+          test.isScriptSrc ? "script-src" : "style-src", sources, cspB);
+      vectorB.append(member);
+    }
+
+    EXPECT_EQ(A.subsumes(vectorB), test.expected);
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
index f017b2f0..95957ef3b 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.cpp
@@ -25,17 +25,19 @@
 MainThreadWorkletGlobalScope::~MainThreadWorkletGlobalScope() {}
 
 void MainThreadWorkletGlobalScope::countFeature(UseCounter::Feature feature) {
-  // TODO(nhiroki): Support UseCounter for main thread worklets. A parent
-  // document is on the same thread, so just record API use in the document's
-  // UseCounter (https://crbug.com/667357).
+  DCHECK(isMainThread());
+  // A parent document is on the same thread, so just record API use in the
+  // document's UseCounter.
+  UseCounter::count(frame(), feature);
 }
 
 void MainThreadWorkletGlobalScope::countDeprecation(
     UseCounter::Feature feature) {
+  DCHECK(isMainThread());
+  // A parent document is on the same thread, so just record API use in the
+  // document's UseCounter.
   addDeprecationMessage(feature);
-  // TODO(nhiroki): Support UseCounter for main thread worklets. A parent
-  // document is on the same thread, so just record API use in the document's
-  // UseCounter (https://crbug.com/667357).
+  Deprecation::countDeprecation(frame(), feature);
 }
 
 WorkerThread* MainThreadWorkletGlobalScope::thread() const {
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h
index 9c9e3e96..90505f6 100644
--- a/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletGlobalScope.h
@@ -20,7 +20,14 @@
 class CORE_EXPORT MainThreadWorkletGlobalScope : public WorkletGlobalScope,
                                                  public WorkletGlobalScopeProxy,
                                                  public DOMWindowProperty {
+  USING_GARBAGE_COLLECTED_MIXIN(MainThreadWorkletGlobalScope);
+
  public:
+  MainThreadWorkletGlobalScope(LocalFrame*,
+                               const KURL&,
+                               const String& userAgent,
+                               PassRefPtr<SecurityOrigin>,
+                               v8::Isolate*);
   ~MainThreadWorkletGlobalScope() override;
   bool isMainThreadWorkletGlobalScope() const final { return true; }
 
@@ -40,13 +47,6 @@
     WorkletGlobalScope::trace(visitor);
     DOMWindowProperty::trace(visitor);
   }
-
- protected:
-  MainThreadWorkletGlobalScope(LocalFrame*,
-                               const KURL&,
-                               const String& userAgent,
-                               PassRefPtr<SecurityOrigin>,
-                               v8::Isolate*);
 };
 
 DEFINE_TYPE_CASTS(MainThreadWorkletGlobalScope,
diff --git a/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
new file mode 100644
index 0000000..c5629a5
--- /dev/null
+++ b/third_party/WebKit/Source/core/workers/MainThreadWorkletTest.cpp
@@ -0,0 +1,54 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/frame/UseCounter.h"
+#include "core/testing/DummyPageHolder.h"
+#include "core/workers/MainThreadWorkletGlobalScope.h"
+#include "platform/weborigin/SecurityOrigin.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class MainThreadWorkletTest : public ::testing::Test {
+ public:
+  void SetUp() override {
+    KURL url(ParsedURLString, "https://example.com/");
+    m_page = DummyPageHolder::create();
+    m_securityOrigin = SecurityOrigin::create(url);
+    m_globalScope = new MainThreadWorkletGlobalScope(
+        &m_page->frame(), url, "fake user agent", m_securityOrigin.get(),
+        toIsolate(m_page->frame().document()));
+  }
+
+  void TearDown() override { m_globalScope->terminateWorkletGlobalScope(); }
+
+ protected:
+  RefPtr<SecurityOrigin> m_securityOrigin;
+  std::unique_ptr<DummyPageHolder> m_page;
+  Persistent<MainThreadWorkletGlobalScope> m_globalScope;
+};
+
+TEST_F(MainThreadWorkletTest, UseCounter) {
+  Document& document = *m_page->frame().document();
+
+  // This feature is randomly selected.
+  const UseCounter::Feature feature1 = UseCounter::Feature::RequestFileSystem;
+
+  // API use on the MainThreadWorkletGlobalScope should be recorded in
+  // UseCounter on the Document.
+  EXPECT_FALSE(UseCounter::isCounted(document, feature1));
+  UseCounter::count(m_globalScope, feature1);
+  EXPECT_TRUE(UseCounter::isCounted(document, feature1));
+
+  // This feature is randomly selected from Deprecation::deprecationMessage().
+  const UseCounter::Feature feature2 = UseCounter::Feature::PrefixedStorageInfo;
+
+  // Deprecated API use on the MainThreadWorkletGlobalScope should be recorded
+  // in UseCounter on the Document.
+  EXPECT_FALSE(UseCounter::isCounted(document, feature2));
+  Deprecation::countDeprecation(m_globalScope, feature2);
+  EXPECT_TRUE(UseCounter::isCounted(document, feature2));
+}
+
+}  // namespace blink
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 35be8bcd..a667b94 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -94133,6 +94133,8 @@
   <int value="544" label="offset-anchor"/>
   <int value="545" label="offset-position"/>
   <int value="546" label="text-decoration-skip"/>
+  <int value="547" label="caret-color"/>
+  <int value="548" label="offset-rotate"/>
 </enum>
 
 <enum name="MappedEditingCommands" type="int">
diff --git a/tools/metrics/histograms/update_use_counter_css.py b/tools/metrics/histograms/update_use_counter_css.py
index a598439..a4dd286 100755
--- a/tools/metrics/histograms/update_use_counter_css.py
+++ b/tools/metrics/histograms/update_use_counter_css.py
@@ -36,19 +36,23 @@
   with open(path_util.GetInputFile(filename)) as f:
     content = f.readlines()
 
-  # Looking for a line like "case CSSPropertyGrid: return 453;".
+  # Looking for a pair of lines like "case CSSPropertyGrid:\n return 453;".
   ENUM_REGEX = re.compile(r"""CSSProperty(.*):  # capture the enum name
                               \s*return\s*
                               ([0-9]+)          # capture the id
                               """, re.VERBOSE)
 
   properties = {}
+  previous_line = ''
   for line in content:
-    enum_match = ENUM_REGEX.search(line)
+    enum_match = ENUM_REGEX.search(previous_line + '\n' + line)
     if enum_match:
       enum_name = enum_match.group(1)
       property_id = int(enum_match.group(2))
       properties[property_id] = EnumToCssProperty(enum_name)
+      previous_line = ''
+    else:
+      previous_line = line
 
   return properties
 
diff --git a/tools/perf/page_sets/data/system_health_desktop.json b/tools/perf/page_sets/data/system_health_desktop.json
index 76d50bd..b6640c6 100644
--- a/tools/perf/page_sets/data/system_health_desktop.json
+++ b/tools/perf/page_sets/data/system_health_desktop.json
@@ -112,7 +112,10 @@
         ],
         "system_health_desktop_036.wpr": [
             "browse:media:tumblr"
+        ],
+        "system_health_desktop_037.wpr": [
+            "browse:search:google"
         ]
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating."
-}
+}
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_desktop_037.wpr.sha1 b/tools/perf/page_sets/data/system_health_desktop_037.wpr.sha1
new file mode 100644
index 0000000..c762889e
--- /dev/null
+++ b/tools/perf/page_sets/data/system_health_desktop_037.wpr.sha1
@@ -0,0 +1 @@
+f2a5ba6c89cbcf3ea63bfe58c022c36bf9cbba16
\ No newline at end of file
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py
index 10f97613..27ce50e 100644
--- a/tools/perf/page_sets/system_health/browsing_stories.py
+++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -234,6 +234,62 @@
 
 
 ##############################################################################
+# Search browsing stories.
+##############################################################################
+
+
+class GoogleDesktopStory(_NewsBrowsingStory):
+  """
+  A typical google search story:
+    _ Start at https://www.google.com/search?q=flower
+    _ Click on the wikipedia link & navigate to
+      https://en.wikipedia.org/wiki/Flower
+    _ Scroll down the wikipedia page about flower.
+    _ Back to the search main page.
+    _ Refine the search query to 'flower delivery'.
+    _ Scroll down the page.
+    _ Click the next page result of 'flower delivery'.
+    _ Scroll the search page.
+
+  """
+  NAME = 'browse:search:google'
+  URL = 'https://www.google.com/search?q=flower'
+  _SEARCH_BOX_SELECTOR = 'input[aria-label="Search"]'
+  _SEARCH_PAGE_2_SELECTOR = 'a[aria-label=\'Page 2\']'
+  SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
+
+  def _DidLoadDocument(self, action_runner):
+    # Click on flower Wikipedia link.
+    action_runner.Wait(2)
+    action_runner.ClickElement(text='Flower - Wikipedia')
+    action_runner.WaitForNavigate()
+
+    # Scroll the flower Wikipedia page, then navigate back.
+    action_runner.Wait(2)
+    action_runner.ScrollPage()
+    action_runner.Wait(2)
+    action_runner.NavigateBack()
+
+    # Click on the search box.
+    action_runner.WaitForElement(selector=self._SEARCH_BOX_SELECTOR)
+    action_runner.ClickElement(selector=self._SEARCH_BOX_SELECTOR)
+    action_runner.Wait(2)
+
+    # Submit search query.
+    action_runner.EnterText(' delivery')
+    action_runner.Wait(0.5)
+    action_runner.PressKey('Return')
+
+    # Scroll down & click next search result page.
+    action_runner.Wait(2)
+    action_runner.ScrollPageToElement(selector=self._SEARCH_PAGE_2_SELECTOR)
+    action_runner.Wait(2)
+    action_runner.ClickElement(selector=self._SEARCH_PAGE_2_SELECTOR)
+    action_runner.Wait(2)
+    action_runner.ScrollPage()
+
+
+##############################################################################
 # Media browsing stories.
 ##############################################################################