diff --git a/DEPS b/DEPS
index ab82ef5f..74f3749 100644
--- a/DEPS
+++ b/DEPS
@@ -74,11 +74,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': '79ee73938d7d3e82a893859cf9083653fff57012',
+  'skia_revision': 'a0985d960fb7c2010274a0fb4a8aa771ece6dc1f',
   # 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': '89d1f5af6e2ebb0e5d9d0972489be05453c45bdd',
+  'v8_revision': 'fb9e2b3a47879f6347907045d5c86b6bcf242280',
   # 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.
@@ -98,7 +98,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': '8509d3eaec1b2fac27a24de7bc586ad12b7bb178',
+  'pdfium_revision': 'c5bfeec86aa70c2ec573c183bd3a8390a3d903e6',
   # 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.
@@ -130,7 +130,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': 'c796cbc3a6e6c45f95d9dd7bf8769f7407719dcf',
+  'catapult_revision': 'a12fb2d1ad961877f3fc1ca4b72965394270419d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -634,7 +634,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '05591bbeae6592fd924caec8e728a4ea86cbb8c9',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '22a77a1b1d9cd6e55af14c895b33b86be4ec53c7', # commit position 20628
+    Var('webrtc_git') + '/src.git' + '@' + '87ed4487e40dad8c0c5d415b95f3c40c5b4d2db4', # commit position 20628
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/browser/android_protocol_handler.cc b/android_webview/browser/android_protocol_handler.cc
index 6882635..08e8cdac 100644
--- a/android_webview/browser/android_protocol_handler.cc
+++ b/android_webview/browser/android_protocol_handler.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/android_protocol_handler.h"
 
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/input_stream.h"
@@ -13,7 +14,6 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/android/jni_weak_ref.h"
-#include "base/memory/ptr_util.h"
 #include "content/public/common/url_constants.h"
 #include "jni/AndroidProtocolHandler_jni.h"
 #include "net/base/io_buffer.h"
@@ -41,7 +41,7 @@
 
 void MarkRequestAsFailed(net::URLRequest* request) {
   request->SetUserData(kPreviouslyFailedKey,
-                       base::MakeUnique<base::SupportsUserData::Data>());
+                       std::make_unique<base::SupportsUserData::Data>());
 }
 
 bool HasRequestPreviouslyFailed(net::URLRequest* request) {
@@ -120,7 +120,7 @@
     DLOG(ERROR) << "Unable to open input stream for Android URL";
     return std::unique_ptr<InputStream>();
   }
-  return base::MakeUnique<InputStream>(stream);
+  return std::make_unique<InputStream>(stream);
 }
 
 void AndroidStreamReaderURLRequestJobDelegateImpl::OnInputStreamOpenFailed(
@@ -222,7 +222,7 @@
 // static
 std::unique_ptr<net::URLRequestInterceptor>
 CreateContentSchemeRequestInterceptor() {
-  return base::MakeUnique<ContentSchemeRequestInterceptor>();
+  return std::make_unique<ContentSchemeRequestInterceptor>();
 }
 
 // static
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index baa76ec..34a4952 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/aw_browser_context.h"
 
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/aw_browser_policy_connector.h"
@@ -111,7 +112,7 @@
           {base::MayBlock(), base::TaskPriority::BACKGROUND});
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
-  return base::MakeUnique<AwSafeBrowsingWhitelistManager>(
+  return std::make_unique<AwSafeBrowsingWhitelistManager>(
       background_task_runner, io_task_runner);
 }
 
@@ -194,7 +195,7 @@
   safe_browsing_db_manager_ =
       new safe_browsing::RemoteSafeBrowsingDatabaseManager();
   safe_browsing_trigger_manager_ =
-      base::MakeUnique<safe_browsing::TriggerManager>(
+      std::make_unique<safe_browsing::TriggerManager>(
           safe_browsing_ui_manager_.get());
   safe_browsing_whitelist_manager_ = CreateSafeBrowsingWhitelistManager();
 
@@ -282,7 +283,7 @@
 AwBrowserContext::GetDownloadManagerDelegate() {
   if (!GetUserData(kDownloadManagerDelegateKey)) {
     SetUserData(kDownloadManagerDelegateKey,
-                base::MakeUnique<AwDownloadManagerDelegate>());
+                std::make_unique<AwDownloadManagerDelegate>());
   }
   return static_cast<AwDownloadManagerDelegate*>(
       GetUserData(kDownloadManagerDelegateKey));
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc
index cf389b8..fa72178d 100644
--- a/android_webview/browser/aw_browser_main_parts.cc
+++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -4,6 +4,8 @@
 
 #include "android_webview/browser/aw_browser_main_parts.h"
 
+#include <memory>
+
 #include "android_webview/browser/aw_browser_context.h"
 #include "android_webview/browser/aw_browser_terminator.h"
 #include "android_webview/browser/aw_content_browser_client.h"
@@ -106,7 +108,7 @@
           switches::kWebViewSandboxedRenderer)) {
     // Create the renderers crash manager on the UI thread.
     breakpad::CrashDumpObserver::GetInstance()->RegisterClient(
-        base::MakeUnique<AwBrowserTerminator>(crash_dir));
+        std::make_unique<AwBrowserTerminator>(crash_dir));
   }
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/android_webview/browser/aw_browser_policy_connector.cc b/android_webview/browser/aw_browser_policy_connector.cc
index bcd497bc..c7ffd4f 100644
--- a/android_webview/browser/aw_browser_policy_connector.cc
+++ b/android_webview/browser/aw_browser_policy_connector.cc
@@ -4,9 +4,10 @@
 
 #include "android_webview/browser/aw_browser_policy_connector.h"
 
+#include <memory>
+
 #include "android_webview/browser/aw_browser_context.h"
 #include "base/bind.h"
-#include "base/memory/ptr_util.h"
 #include "components/policy/core/browser/android/android_combined_policy_provider.h"
 #include "components/policy/core/browser/configuration_policy_handler_list.h"
 #include "components/policy/core/browser/url_blacklist_policy_handler.h"
@@ -37,16 +38,16 @@
           base::Bind(&GetChromePolicyDetails)));
 
   // URL Filtering
-  handlers->AddHandler(base::MakeUnique<policy::SimplePolicyHandler>(
+  handlers->AddHandler(std::make_unique<policy::SimplePolicyHandler>(
       policy::key::kURLWhitelist, policy::policy_prefs::kUrlWhitelist,
       base::Value::Type::LIST));
-  handlers->AddHandler(base::MakeUnique<policy::URLBlacklistPolicyHandler>());
+  handlers->AddHandler(std::make_unique<policy::URLBlacklistPolicyHandler>());
 
   // HTTP Negotiate authentication
-  handlers->AddHandler(base::MakeUnique<policy::SimplePolicyHandler>(
+  handlers->AddHandler(std::make_unique<policy::SimplePolicyHandler>(
       policy::key::kAuthServerWhitelist, prefs::kAuthServerWhitelist,
       base::Value::Type::STRING));
-  handlers->AddHandler(base::MakeUnique<policy::SimplePolicyHandler>(
+  handlers->AddHandler(std::make_unique<policy::SimplePolicyHandler>(
       policy::key::kAuthAndroidNegotiateAccountType,
       prefs::kAuthAndroidNegotiateAccountType, base::Value::Type::STRING));
 
@@ -63,7 +64,7 @@
 AwBrowserPolicyConnector::AwBrowserPolicyConnector()
    : BrowserPolicyConnectorBase(base::Bind(&BuildHandlerList)) {
   SetPlatformPolicyProvider(
-      base::MakeUnique<policy::android::AndroidCombinedPolicyProvider>(
+      std::make_unique<policy::android::AndroidCombinedPolicyProvider>(
           GetSchemaRegistry()));
   InitPolicyProviders();
 }
diff --git a/android_webview/browser/aw_browser_terminator.cc b/android_webview/browser/aw_browser_terminator.cc
index 3473be0..8a0d1c3 100644
--- a/android_webview/browser/aw_browser_terminator.cc
+++ b/android_webview/browser/aw_browser_terminator.cc
@@ -5,6 +5,7 @@
 #include "android_webview/browser/aw_browser_terminator.h"
 
 #include <unistd.h>
+#include <memory>
 
 #include "android_webview/browser/aw_render_process_gone_delegate.h"
 #include "android_webview/common/aw_descriptors.h"
@@ -110,8 +111,8 @@
   base::AutoLock auto_lock(process_host_id_to_pipe_lock_);
   DCHECK(!ContainsKey(process_host_id_to_pipe_, process_host_id));
 
-  auto local_pipe = base::MakeUnique<base::SyncSocket>();
-  auto child_pipe = base::MakeUnique<base::SyncSocket>();
+  auto local_pipe = std::make_unique<base::SyncSocket>();
+  auto child_pipe = std::make_unique<base::SyncSocket>();
   if (base::SyncSocket::CreatePair(local_pipe.get(), child_pipe.get())) {
     process_host_id_to_pipe_[process_host_id] = std::move(local_pipe);
     mappings->Transfer(kAndroidWebViewCrashSignalDescriptor,
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index f1f8e58..15f4d3a 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -5,6 +5,7 @@
 #include "android_webview/browser/aw_contents.h"
 
 #include <limits>
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/aw_autofill_client.h"
@@ -47,7 +48,6 @@
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
-#include "base/memory/ptr_util.h"
 #include "base/pickle.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
@@ -229,7 +229,7 @@
   icon_helper_.reset(new IconHelper(web_contents_.get()));
   icon_helper_->SetListener(this);
   web_contents_->SetUserData(android_webview::kAwContentsUserDataKey,
-                             base::MakeUnique<AwContentsUserData>(this));
+                             std::make_unique<AwContentsUserData>(this));
   browser_view_renderer_.RegisterWithWebContents(web_contents_.get());
 
   CompositorID compositor_id;
@@ -283,11 +283,11 @@
   AwContentsIoThreadClient::Associate(web_contents_.get(), io_thread_client);
 
   InterceptNavigationDelegate::Associate(
-      web_contents_.get(), base::MakeUnique<InterceptNavigationDelegate>(
+      web_contents_.get(), std::make_unique<InterceptNavigationDelegate>(
                                env, intercept_navigation_delegate));
 
   if (!autofill_provider.is_null()) {
-    autofill_provider_ = base::MakeUnique<autofill::AutofillProviderAndroid>(
+    autofill_provider_ = std::make_unique<autofill::AutofillProviderAndroid>(
         autofill_provider, web_contents_.get());
   }
 
diff --git a/android_webview/browser/aw_contents_client_bridge.cc b/android_webview/browser/aw_contents_client_bridge.cc
index 0824fd90..8c9d15f 100644
--- a/android_webview/browser/aw_contents_client_bridge.cc
+++ b/android_webview/browser/aw_contents_client_bridge.cc
@@ -13,7 +13,6 @@
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
 #include "content/public/browser/browser_thread.h"
@@ -77,7 +76,7 @@
 void AwContentsClientBridge::Associate(WebContents* web_contents,
                                        AwContentsClientBridge* handler) {
   web_contents->SetUserData(kAwContentsClientBridge,
-                            base::MakeUnique<UserData>(handler));
+                            std::make_unique<UserData>(handler));
 }
 
 // static
@@ -148,7 +147,7 @@
   // We need to add the callback before making the call to java side,
   // as it may do a synchronous callback prior to returning.
   int request_id = pending_cert_error_callbacks_.Add(
-      base::MakeUnique<CertErrorCallback>(callback));
+      std::make_unique<CertErrorCallback>(callback));
   *cancel_request = !Java_AwContentsClientBridge_allowCertificateError(
       env, obj, cert_error, jcert, jurl, request_id);
   // if the request is cancelled, then cancel the stored callback
@@ -297,7 +296,7 @@
   }
 
   int callback_id = pending_js_dialog_callbacks_.Add(
-      base::MakeUnique<content::JavaScriptDialogManager::DialogClosedCallback>(
+      std::make_unique<content::JavaScriptDialogManager::DialogClosedCallback>(
           std::move(callback)));
   ScopedJavaLocalRef<jstring> jurl(
       ConvertUTF8ToJavaString(env, origin_url.spec()));
@@ -346,7 +345,7 @@
       l10n_util::GetStringUTF16(IDS_BEFOREUNLOAD_MESSAGEBOX_MESSAGE);
 
   int callback_id = pending_js_dialog_callbacks_.Add(
-      base::MakeUnique<content::JavaScriptDialogManager::DialogClosedCallback>(
+      std::make_unique<content::JavaScriptDialogManager::DialogClosedCallback>(
           std::move(callback)));
   ScopedJavaLocalRef<jstring> jurl(
       ConvertUTF8ToJavaString(env, origin_url.spec()));
@@ -455,7 +454,7 @@
     const safe_browsing::SBThreatType& threat_type,
     const SafeBrowsingActionCallback& callback) {
   int request_id = safe_browsing_callbacks_.Add(
-      base::MakeUnique<SafeBrowsingActionCallback>(callback));
+      std::make_unique<SafeBrowsingActionCallback>(callback));
 
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
diff --git a/android_webview/browser/aw_contents_client_bridge_unittest.cc b/android_webview/browser/aw_contents_client_bridge_unittest.cc
index 97c5f8b..c24d1a7 100644
--- a/android_webview/browser/aw_contents_client_bridge_unittest.cc
+++ b/android_webview/browser/aw_contents_client_bridge_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/android/scoped_java_ref.h"
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "content/public/browser/client_certificate_delegate.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -116,7 +115,7 @@
   cert_request_info_->cert_key_types.push_back(type);
   bridge_->SelectClientCertificate(
       cert_request_info_.get(),
-      base::MakeUnique<TestClientCertificateDelegate>(this));
+      std::make_unique<TestClientCertificateDelegate>(this));
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, cert_selected_callbacks_);
   ScopedJavaLocalRef<jobjectArray> key_types =
diff --git a/android_webview/browser/aw_field_trial_creator.cc b/android_webview/browser/aw_field_trial_creator.cc
index 8949dc8..fa8020e 100644
--- a/android_webview/browser/aw_field_trial_creator.cc
+++ b/android_webview/browser/aw_field_trial_creator.cc
@@ -4,6 +4,8 @@
 
 #include "android_webview/browser/aw_field_trial_creator.h"
 
+#include <memory>
+
 #include "android_webview/browser/aw_metrics_service_client.h"
 #include "base/base_switches.h"
 #include "base/feature_list.h"
@@ -46,7 +48,7 @@
 }  // anonymous namespace
 
 AwFieldTrialCreator::AwFieldTrialCreator()
-    : aw_field_trials_(base::MakeUnique<AwFieldTrials>()) {}
+    : aw_field_trials_(std::make_unique<AwFieldTrials>()) {}
 
 AwFieldTrialCreator::~AwFieldTrialCreator() {}
 
@@ -66,7 +68,7 @@
                                     std::string());
   pref_registry->RegisterListPref(
       variations::prefs::kVariationsPermanentConsistencyCountry,
-      base::MakeUnique<base::ListValue>());
+      std::make_unique<base::ListValue>());
 
   pref_service_factory_.set_user_prefs(
       base::MakeRefCounted<InMemoryPrefStore>());
@@ -79,7 +81,7 @@
   DCHECK(!field_trial_list_);
   // Set the FieldTrialList singleton.
   field_trial_list_ =
-      base::MakeUnique<base::FieldTrialList>(CreateLowEntropyProvider());
+      std::make_unique<base::FieldTrialList>(CreateLowEntropyProvider());
 
   std::unique_ptr<PrefService> local_state = CreateLocalState();
 
@@ -87,9 +89,9 @@
     return;
 
   variations::UIStringOverrider ui_string_overrider;
-  client_ = base::MakeUnique<AwVariationsServiceClient>();
+  client_ = std::make_unique<AwVariationsServiceClient>();
   variations_field_trial_creator_ =
-      base::MakeUnique<variations::VariationsFieldTrialCreator>(
+      std::make_unique<variations::VariationsFieldTrialCreator>(
           local_state.get(), client_.get(), ui_string_overrider);
 
   variations_field_trial_creator_->OverrideVariationsPlatform(
@@ -104,7 +106,7 @@
   variations_field_trial_creator_->SetupFieldTrials(
       cc::switches::kEnableGpuBenchmarking, switches::kEnableFeatures,
       switches::kDisableFeatures, unforceable_field_trials,
-      CreateLowEntropyProvider(), base::MakeUnique<base::FeatureList>(),
+      CreateLowEntropyProvider(), std::make_unique<base::FeatureList>(),
       &variation_ids, aw_field_trials_.get());
 }
 
diff --git a/android_webview/browser/aw_permission_manager.cc b/android_webview/browser/aw_permission_manager.cc
index c012414..e9dca2e 100644
--- a/android_webview/browser/aw_permission_manager.cc
+++ b/android_webview/browser/aw_permission_manager.cc
@@ -12,7 +12,6 @@
 #include "base/callback.h"
 #include "base/containers/hash_tables.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "content/public/browser/permission_type.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -256,7 +255,7 @@
 
   const GURL& embedding_origin = LastCommittedOrigin(render_frame_host);
 
-  auto pending_request = base::MakeUnique<PendingRequest>(
+  auto pending_request = std::make_unique<PendingRequest>(
       permissions, requesting_origin, embedding_origin,
       GetRenderProcessID(render_frame_host),
       GetRenderFrameID(render_frame_host), callback);
diff --git a/android_webview/browser/aw_permission_manager_unittest.cc b/android_webview/browser/aw_permission_manager_unittest.cc
index 4f069b9..2407a8f 100644
--- a/android_webview/browser/aw_permission_manager_unittest.cc
+++ b/android_webview/browser/aw_permission_manager_unittest.cc
@@ -10,13 +10,11 @@
 #include "android_webview/browser/aw_browser_permission_request_delegate.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/memory/ptr_util.h"
 #include "content/public/browser/permission_manager.h"
 #include "content/public/browser/permission_type.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using base::MakeUnique;
 using blink::mojom::PermissionStatus;
 using content::PermissionType;
 
@@ -46,7 +44,7 @@
       callback.Run(grant);
       return;
     }
-    response_.push_back(MakeUnique<Response>(origin, type, grant));
+    response_.push_back(std::make_unique<Response>(origin, type, grant));
   }
 
   // AwBrowserPermissionRequestDelegate:
@@ -89,7 +87,7 @@
       callback.Run(grant);
       return;
     }
-    request_.push_back(MakeUnique<Request>(origin, type, callback));
+    request_.push_back(std::make_unique<Request>(origin, type, callback));
   }
 
   void CancelPermission(const GURL& origin, PermissionType type) {
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.cc b/android_webview/browser/aw_safe_browsing_blocking_page.cc
index 559c69c..da19f09 100644
--- a/android_webview/browser/aw_safe_browsing_blocking_page.cc
+++ b/android_webview/browser/aw_safe_browsing_blocking_page.cc
@@ -4,6 +4,8 @@
 
 #include "android_webview/browser/aw_safe_browsing_blocking_page.h"
 
+#include <memory>
+
 #include "android_webview/browser/aw_browser_context.h"
 #include "android_webview/browser/aw_safe_browsing_ui_manager.h"
 #include "android_webview/browser/net/aw_url_request_context_getter.h"
@@ -46,7 +48,7 @@
                             ErrorUiType::COUNT);
   if (errorUiType == ErrorUiType::QUIET_SMALL ||
       errorUiType == ErrorUiType::QUIET_GIANT) {
-    set_sb_error_ui(base::MakeUnique<SafeBrowsingQuietErrorUI>(
+    set_sb_error_ui(std::make_unique<SafeBrowsingQuietErrorUI>(
         unsafe_resources[0].url, main_frame_url,
         GetInterstitialReason(unsafe_resources), display_options,
         ui_manager->app_locale(), base::Time::NowFromSystemTime(), controller(),
diff --git a/android_webview/browser/aw_safe_browsing_whitelist_manager.cc b/android_webview/browser/aw_safe_browsing_whitelist_manager.cc
index 26601fb..873eea2 100644
--- a/android_webview/browser/aw_safe_browsing_whitelist_manager.cc
+++ b/android_webview/browser/aw_safe_browsing_whitelist_manager.cc
@@ -5,6 +5,7 @@
 #include "android_webview/browser/aw_safe_browsing_whitelist_manager.h"
 
 #include <map>
+#include <memory>
 
 #include "base/bind.h"
 #include "base/logging.h"
@@ -68,7 +69,7 @@
     std::string component = hostcomp->as_string();
     auto child_node = node->children.find(component);
     if (child_node == node->children.end()) {
-      std::unique_ptr<TrieNode> temp = base::MakeUnique<TrieNode>();
+      std::unique_ptr<TrieNode> temp = std::make_unique<TrieNode>();
       TrieNode* current = temp.get();
       node->children.emplace(component, std::move(temp));
       node = current;
@@ -183,7 +184,7 @@
     : background_task_runner_(background_task_runner),
       io_task_runner_(io_task_runner),
       ui_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      whitelist_(base::MakeUnique<TrieNode>()) {}
+      whitelist_(std::make_unique<TrieNode>()) {}
 
 AwSafeBrowsingWhitelistManager::~AwSafeBrowsingWhitelistManager() {}
 
@@ -199,7 +200,7 @@
     const base::Callback<void(bool)>& callback) {
   DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
-  std::unique_ptr<TrieNode> whitelist(base::MakeUnique<TrieNode>());
+  std::unique_ptr<TrieNode> whitelist(std::make_unique<TrieNode>());
   bool success = AddRules(rules, whitelist.get());
   DCHECK(!whitelist->is_terminal);
   DCHECK(!whitelist->match_prefix);
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc
index 6d86537..3055338 100644
--- a/android_webview/browser/aw_settings.cc
+++ b/android_webview/browser/aw_settings.cc
@@ -4,6 +4,8 @@
 
 #include "android_webview/browser/aw_settings.h"
 
+#include <memory>
+
 #include "android_webview/browser/aw_content_browser_client.h"
 #include "android_webview/browser/aw_contents.h"
 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
@@ -11,7 +13,6 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/supports_user_data.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
@@ -83,7 +84,7 @@
       javascript_can_open_windows_automatically_(false),
       aw_settings_(env, obj) {
   web_contents->SetUserData(kAwSettingsUserDataKey,
-                            base::MakeUnique<AwSettingsUserData>(this));
+                            std::make_unique<AwSettingsUserData>(this));
 }
 
 AwSettings::~AwSettings() {
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 75b88755..afb8e78 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/browser_view_renderer.h"
 
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/browser_view_renderer_client.h"
@@ -12,7 +13,6 @@
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/supports_user_data.h"
@@ -137,7 +137,7 @@
     content::WebContents* web_contents) {
   web_contents->SetUserData(
       kBrowserViewRendererUserDataKey,
-      base::MakeUnique<BrowserViewRendererUserData>(this));
+      std::make_unique<BrowserViewRendererUserData>(this));
 }
 
 void BrowserViewRenderer::TrimMemory() {
@@ -252,7 +252,7 @@
   }
 
   allow_async_draw_ = true;
-  std::unique_ptr<ChildFrame> child_frame = base::MakeUnique<ChildFrame>(
+  std::unique_ptr<ChildFrame> child_frame = std::make_unique<ChildFrame>(
       std::move(future), frame.layer_tree_frame_sink_id, std::move(frame.frame),
       compositor_id_, viewport_rect_for_tile_priority.IsEmpty(),
       transform_for_tile_priority, offscreen_pre_raster_,
diff --git a/android_webview/browser/browser_view_renderer_unittest.cc b/android_webview/browser/browser_view_renderer_unittest.cc
index 0b373600..3e67083 100644
--- a/android_webview/browser/browser_view_renderer_unittest.cc
+++ b/android_webview/browser/browser_view_renderer_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <map>
+#include <memory>
 #include <queue>
 #include <utility>
 
@@ -12,7 +13,6 @@
 #include "android_webview/browser/render_thread_manager.h"
 #include "android_webview/browser/test/rendering_test.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/viz/common/quads/compositor_frame.h"
@@ -500,7 +500,7 @@
         // Switch to new RTM.
         std::unique_ptr<FakeFunctor> functor(new FakeFunctor);
         functor->Init(window_.get(),
-                      base::MakeUnique<RenderThreadManager>(
+                      std::make_unique<RenderThreadManager>(
                           functor.get(), base::ThreadTaskRunnerHandle::Get()));
         browser_view_renderer_->SetCurrentCompositorFrameConsumer(
             functor->GetCompositorFrameConsumer());
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index 164015542..632a84b4 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/hardware_renderer.h"
 
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/aw_gl_surface.h"
@@ -12,7 +13,6 @@
 #include "android_webview/browser/render_thread_manager.h"
 #include "android_webview/browser/surfaces_instance.h"
 #include "android_webview/public/browser/draw_gl.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/surfaces/local_surface_id_allocator.h"
@@ -29,7 +29,7 @@
       surfaces_(SurfacesInstance::GetOrCreateInstance()),
       frame_sink_id_(surfaces_->AllocateFrameSinkId()),
       local_surface_id_allocator_(
-          base::MakeUnique<viz::LocalSurfaceIdAllocator>()),
+          std::make_unique<viz::LocalSurfaceIdAllocator>()),
       last_committed_layer_tree_frame_sink_id_(0u),
       last_submitted_layer_tree_frame_sink_id_(0u) {
   DCHECK(last_egl_context_);
diff --git a/android_webview/browser/java_browser_view_renderer_helper.cc b/android_webview/browser/java_browser_view_renderer_helper.cc
index 91992694..6b1ea5c75 100644
--- a/android_webview/browser/java_browser_view_renderer_helper.cc
+++ b/android_webview/browser/java_browser_view_renderer_helper.cc
@@ -5,10 +5,10 @@
 #include "android_webview/browser/java_browser_view_renderer_helper.h"
 
 #include <android/bitmap.h>
+#include <memory>
 
 #include "android_webview/public/browser/draw_sw.h"
 #include "base/android/scoped_java_ref.h"
-#include "base/memory/ptr_util.h"
 #include "base/trace_event/trace_event.h"
 #include "jni/JavaBrowserViewRendererHelper_jni.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -121,7 +121,7 @@
       SkImageInfo::MakeN32Premul(bitmap_info.width, bitmap_info.height);
   bitmap_.reset(new SkBitmap);
   bitmap_->installPixels(info, pixels, bitmap_info.stride);
-  canvas_ = base::MakeUnique<SkCanvas>(*bitmap_);
+  canvas_ = std::make_unique<SkCanvas>(*bitmap_);
 }
 
 AuxiliaryCanvasHolder::~AuxiliaryCanvasHolder() {
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job.cc b/android_webview/browser/net/android_stream_reader_url_request_job.cc
index 267f5dab..0fb895f 100644
--- a/android_webview/browser/net/android_stream_reader_url_request_job.cc
+++ b/android_webview/browser/net/android_stream_reader_url_request_job.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/net/android_stream_reader_url_request_job.h"
 
+#include <memory>
 #include <string>
 #include <utility>
 
@@ -14,7 +15,6 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/lazy_instance.h"
-#include "base/memory/ptr_util.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task_scheduler/post_task.h"
@@ -157,7 +157,7 @@
 
 std::unique_ptr<InputStreamReader>
 AndroidStreamReaderURLRequestJob::CreateStreamReader(InputStream* stream) {
-  return base::MakeUnique<InputStreamReader>(stream);
+  return std::make_unique<InputStreamReader>(stream);
 }
 
 void AndroidStreamReaderURLRequestJob::OnInputStreamOpened(
diff --git a/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc b/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc
index fcdd00a..d77dd7c 100644
--- a/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc
+++ b/android_webview/browser/net/android_stream_reader_url_request_job_unittest.cc
@@ -11,7 +11,6 @@
 #include "android_webview/browser/net/aw_url_request_job_factory.h"
 #include "android_webview/browser/net/input_stream_reader.h"
 #include "base/format_macros.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
@@ -80,7 +79,7 @@
 
   std::unique_ptr<InputStream> OpenInputStream(JNIEnv* env,
                                                const GURL& url) override {
-    return base::MakeUnique<NotImplInputStream>();
+    return std::make_unique<NotImplInputStream>();
   }
 
   void OnInputStreamOpenFailed(net::URLRequest* request,
@@ -205,7 +204,7 @@
 
   void SetUpTestJob(std::unique_ptr<InputStreamReader> stream_reader) {
     SetUpTestJob(std::move(stream_reader),
-                 base::MakeUnique<StreamReaderDelegate>());
+                 std::make_unique<StreamReaderDelegate>());
   }
 
   void SetUpTestJob(std::unique_ptr<InputStreamReader> stream_reader,
@@ -258,7 +257,7 @@
 }
 
 TEST_F(AndroidStreamReaderURLRequestJobTest, ReadWithNullStream) {
-  SetUpTestJob(nullptr, base::MakeUnique<NullStreamReaderDelegate>());
+  SetUpTestJob(nullptr, std::make_unique<NullStreamReaderDelegate>());
   req_->Start();
 
   // The TestDelegate will quit the message loop on request completion.
@@ -274,7 +273,7 @@
 }
 
 TEST_F(AndroidStreamReaderURLRequestJobTest, ModifyHeadersAndStatus) {
-  SetUpTestJob(nullptr, base::MakeUnique<HeaderAlteringStreamReaderDelegate>());
+  SetUpTestJob(nullptr, std::make_unique<HeaderAlteringStreamReaderDelegate>());
   req_->Start();
 
   // The TestDelegate will quit the message loop on request completion.
diff --git a/android_webview/browser/net/aw_request_interceptor.cc b/android_webview/browser/net/aw_request_interceptor.cc
index 6db70fd..ebe8b2c2 100644
--- a/android_webview/browser/net/aw_request_interceptor.cc
+++ b/android_webview/browser/net/aw_request_interceptor.cc
@@ -4,13 +4,13 @@
 
 #include "android_webview/browser/net/aw_request_interceptor.h"
 
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/aw_contents_io_thread_client.h"
 #include "android_webview/browser/input_stream.h"
 #include "android_webview/browser/net/android_stream_reader_url_request_job.h"
 #include "android_webview/browser/net/aw_web_resource_response.h"
-#include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/supports_user_data.h"
@@ -103,7 +103,7 @@
       std::unique_ptr<AwWebResourceResponse> response) {
     if (response) {
       callback_.Run(
-          base::MakeUnique<StreamReaderJobDelegateImpl>(std::move(response)));
+          std::make_unique<StreamReaderJobDelegateImpl>(std::move(response)));
     } else {
       callback_.Run(nullptr);
     }
@@ -174,10 +174,10 @@
                                          referrer.spec(), true);
   }
   request->SetUserData(kRequestAlreadyHasJobDataKey,
-                       base::MakeUnique<base::SupportsUserData::Data>());
+                       std::make_unique<base::SupportsUserData::Data>());
   return new AndroidStreamReaderURLRequestJob(
       request, network_delegate,
-      base::MakeUnique<ShouldInterceptRequestAdaptor>(
+      std::make_unique<ShouldInterceptRequestAdaptor>(
           std::move(io_thread_client)),
       true);
 }
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index 4acf8a24f..6ae4478 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/net/aw_url_request_context_getter.h"
 
+#include <memory>
 #include <utility>
 #include <vector>
 
@@ -22,7 +23,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
-#include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/sys_info.h"
@@ -123,13 +123,13 @@
   // AwContentBrowserClient::IsHandledURL.
   bool set_protocol = aw_job_factory->SetProtocolHandler(
       url::kFileScheme,
-      base::MakeUnique<net::FileProtocolHandler>(
+      std::make_unique<net::FileProtocolHandler>(
           base::CreateTaskRunnerWithTraits(
               {base::MayBlock(), base::TaskPriority::BACKGROUND,
                base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
   DCHECK(set_protocol);
   set_protocol = aw_job_factory->SetProtocolHandler(
-      url::kDataScheme, base::MakeUnique<net::DataProtocolHandler>());
+      url::kDataScheme, std::make_unique<net::DataProtocolHandler>());
   DCHECK(set_protocol);
   set_protocol = aw_job_factory->SetProtocolHandler(
       url::kBlobScheme,
@@ -159,7 +159,7 @@
   // This logical dependency is also the reason why the Content
   // URLRequestInterceptor has to be added as an interceptor rather than as a
   // ProtocolHandler.
-  request_interceptors.push_back(base::MakeUnique<AwRequestInterceptor>());
+  request_interceptors.push_back(std::make_unique<AwRequestInterceptor>());
 
   // The chain of responsibility will execute the handlers in reverse to the
   // order in which the elements of the chain are created.
@@ -223,7 +223,7 @@
     std::unique_ptr<base::DictionaryValue> constants_dict =
         net::GetNetConstants();
     // Add a dictionary with client information
-    auto dict = base::MakeUnique<base::DictionaryValue>();
+    auto dict = std::make_unique<base::DictionaryValue>();
 
     dict->SetString("name", version_info::GetProductName());
     dict->SetString("version", version_info::GetVersionNumber());
@@ -260,7 +260,7 @@
   AwBrowserContext* browser_context = AwBrowserContext::GetDefault();
   DCHECK(browser_context);
 
-  builder.set_network_delegate(base::MakeUnique<AwNetworkDelegate>());
+  builder.set_network_delegate(std::make_unique<AwNetworkDelegate>());
 #if !BUILDFLAG(DISABLE_FTP_SUPPORT)
   builder.set_ftp_enabled(false);  // Android WebView does not support ftp yet.
 #endif
@@ -293,7 +293,7 @@
         std::move(proxy_config_service_), net_log_.get()));
   }
   builder.set_net_log(net_log_.get());
-  builder.SetCookieAndChannelIdStores(base::MakeUnique<AwCookieStoreWrapper>(),
+  builder.SetCookieAndChannelIdStores(std::make_unique<AwCookieStoreWrapper>(),
                                       std::move(channel_id_service));
 
   net::URLRequestContextBuilder::HttpCacheParams cache_params;
diff --git a/android_webview/browser/net/aw_web_resource_response.cc b/android_webview/browser/net/aw_web_resource_response.cc
index 4fc646e..f45174a 100644
--- a/android_webview/browser/net/aw_web_resource_response.cc
+++ b/android_webview/browser/net/aw_web_resource_response.cc
@@ -4,11 +4,12 @@
 
 #include "android_webview/browser/net/aw_web_resource_response.h"
 
+#include <memory>
+
 #include "android_webview/browser/input_stream.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
-#include "base/memory/ptr_util.h"
 #include "jni/AwWebResourceResponse_jni.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request.h"
@@ -31,7 +32,7 @@
       Java_AwWebResourceResponse_getData(env, java_object_);
   if (jstream.is_null())
     return std::unique_ptr<InputStream>();
-  return base::MakeUnique<InputStream>(jstream);
+  return std::make_unique<InputStream>(jstream);
 }
 
 bool AwWebResourceResponse::GetMimeType(JNIEnv* env,
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
index b671964ca..d82e350 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -292,7 +292,7 @@
       content::ResourceRequestInfo::ForRequest(request);
 
   std::unique_ptr<IoThreadClientThrottle> ioThreadThrottle =
-      base::MakeUnique<IoThreadClientThrottle>(request_info->GetChildID(),
+      std::make_unique<IoThreadClientThrottle>(request_info->GetChildID(),
                                                request_info->GetRenderFrameID(),
                                                request);
 
@@ -322,7 +322,7 @@
   if (!is_main_frame)
     InterceptNavigationDelegate::UpdateUserGestureCarryoverInfo(request);
   throttles->push_back(
-      base::MakeUnique<web_restrictions::WebRestrictionsResourceThrottle>(
+      std::make_unique<web_restrictions::WebRestrictionsResourceThrottle>(
           AwBrowserContext::GetDefault()->GetWebRestrictionProvider(),
           request->url(), is_main_frame));
 }
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc
index 11ebec2..4e2dfa00 100644
--- a/android_webview/browser/surfaces_instance.cc
+++ b/android_webview/browser/surfaces_instance.cc
@@ -5,13 +5,13 @@
 #include "android_webview/browser/surfaces_instance.h"
 
 #include <algorithm>
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/aw_gl_surface.h"
 #include "android_webview/browser/aw_render_thread_context_provider.h"
 #include "android_webview/browser/deferred_gpu_command_service.h"
 #include "android_webview/browser/parent_output_surface.h"
-#include "base/memory/ptr_util.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
@@ -69,10 +69,10 @@
           base::WrapRefCounted(new AwGLSurface),
           DeferredGpuCommandService::GetInstance())));
   output_surface_ = output_surface_holder.get();
-  auto scheduler = base::MakeUnique<viz::DisplayScheduler>(
+  auto scheduler = std::make_unique<viz::DisplayScheduler>(
       begin_frame_source_.get(), nullptr /* current_task_runner */,
       output_surface_holder->capabilities().max_frames_pending);
-  display_ = base::MakeUnique<viz::Display>(
+  display_ = std::make_unique<viz::Display>(
       nullptr /* shared_bitmap_manager */,
       nullptr /* gpu_memory_buffer_manager */, settings, frame_sink_id_,
       std::move(output_surface_holder), std::move(scheduler),
diff --git a/android_webview/browser/test/rendering_test.cc b/android_webview/browser/test/rendering_test.cc
index 4fb908f7..26aa0ec 100644
--- a/android_webview/browser/test/rendering_test.cc
+++ b/android_webview/browser/test/rendering_test.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/test/rendering_test.h"
 
+#include <memory>
 #include <utility>
 
 #include "android_webview/browser/browser_view_renderer.h"
@@ -12,7 +13,6 @@
 #include "android_webview/common/aw_switches.h"
 #include "base/command_line.h"
 #include "base/location.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/viz/common/quads/compositor_frame.h"
@@ -75,7 +75,7 @@
       new FakeWindow(browser_view_renderer_.get(), this, gfx::Rect(100, 100)));
   functor_.reset(new FakeFunctor);
   functor_->Init(window.get(),
-                 base::MakeUnique<RenderThreadManager>(
+                 std::make_unique<RenderThreadManager>(
                      functor_.get(), base::ThreadTaskRunnerHandle::Get()));
   browser_view_renderer_->SetCurrentCompositorFrameConsumer(
       functor_->GetCompositorFrameConsumer());
@@ -118,7 +118,7 @@
 }
 
 std::unique_ptr<viz::CompositorFrame> RenderingTest::ConstructEmptyFrame() {
-  auto compositor_frame = base::MakeUnique<viz::CompositorFrame>(
+  auto compositor_frame = std::make_unique<viz::CompositorFrame>(
       viz::test::MakeEmptyCompositorFrame());
   std::unique_ptr<viz::RenderPass> root_pass(viz::RenderPass::Create());
   gfx::Rect viewport(browser_view_renderer_->size());
diff --git a/android_webview/browser/tracing/aw_tracing_delegate.cc b/android_webview/browser/tracing/aw_tracing_delegate.cc
index 2376330..6b4cdeb 100644
--- a/android_webview/browser/tracing/aw_tracing_delegate.cc
+++ b/android_webview/browser/tracing/aw_tracing_delegate.cc
@@ -4,8 +4,9 @@
 
 #include "android_webview/browser/tracing/aw_tracing_delegate.h"
 
+#include <memory>
+
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
 #include "base/values.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/trace_uploader.h"
@@ -23,7 +24,7 @@
 
 std::unique_ptr<base::DictionaryValue>
 AwTracingDelegate::GenerateMetadataDict() {
-  auto metadata_dict = base::MakeUnique<base::DictionaryValue>();
+  auto metadata_dict = std::make_unique<base::DictionaryValue>();
   metadata_dict->SetString("revision", version_info::GetLastChange());
   return metadata_dict;
 }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
index 44e2da97..21490116 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -59,6 +59,7 @@
 import org.chromium.android_webview.AwSettings;
 import org.chromium.android_webview.ResourcesContextWrapperFactory;
 import org.chromium.android_webview.renderer_priority.RendererPriority;
+import org.chromium.base.BuildInfo;
 import org.chromium.base.ThreadUtils;
 import org.chromium.components.autofill.AutofillProvider;
 import org.chromium.content.browser.SmartClipProvider;
@@ -193,6 +194,11 @@
             mWebSettings.getAwSettings().setZeroLayoutHeightDisablesViewportQuirk(true);
         }
 
+        if (BuildInfo.targetsAtLeastP()) {
+            mWebSettings.getAwSettings().setCSSHexAlphaColorEnabled(true);
+            mWebSettings.getAwSettings().setScrollTopLeftInteropEnabled(true);
+        }
+
         if (mShouldDisableThreadChecking) disableThreadChecking();
 
         mFactory.addTask(new Runnable() {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
index fb7caaab..73f9384 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -2866,6 +2866,40 @@
         }
     }
 
+    private void testScrollTopLeftInteropState(boolean state) throws Throwable {
+        final TestAwContentsClient client = new TestAwContentsClient();
+        final AwTestContainerView view =
+                mActivityTestRule.createAwTestContainerViewOnMainSync(client);
+        final AwContents awContents = view.getAwContents();
+        CallbackHelper onPageFinishedHelper = client.getOnPageFinishedHelper();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(
+                () -> awContents.getSettings().setScrollTopLeftInteropEnabled(state));
+        mActivityTestRule.enableJavaScriptOnUiThread(awContents);
+        final String page = "<!doctype html>"
+                + "<script>"
+                + "window.onload = function() {"
+                + "  document.title = document.scrollingElement === document.documentElement;"
+                + "};"
+                + "</script>";
+        mActivityTestRule.loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
+        String actualTitle = mActivityTestRule.getTitleOnUiThread(awContents);
+        Assert.assertEquals(state ? "true" : "false", actualTitle);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView", "Preferences"})
+    public void testScrollTopLeftInteropEnabled() throws Throwable {
+        testScrollTopLeftInteropState(true);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView", "Preferences"})
+    public void testScrollTopLeftInteropDisabled() throws Throwable {
+        testScrollTopLeftInteropState(false);
+    }
+
     @Test
     @SmallTest
     @Feature({"AndroidWebView", "Preferences"})
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index d4f94127..f14b2a4 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/renderer/aw_content_renderer_client.h"
 
+#include <memory>
 #include <vector>
 
 #include "android_webview/common/aw_switches.h"
@@ -19,7 +20,6 @@
 #include "android_webview/renderer/print_render_frame_observer.h"
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
-#include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
@@ -85,17 +85,17 @@
 
   visited_link_slave_.reset(new visitedlink::VisitedLinkSlave);
 
-  auto registry = base::MakeUnique<service_manager::BinderRegistry>();
+  auto registry = std::make_unique<service_manager::BinderRegistry>();
   registry->AddInterface(visited_link_slave_->GetBindCallback(),
                          base::ThreadTaskRunnerHandle::Get());
   content::ChildThread::Get()
       ->GetServiceManagerConnection()
-      ->AddConnectionFilter(base::MakeUnique<content::SimpleConnectionFilter>(
+      ->AddConnectionFilter(std::make_unique<content::SimpleConnectionFilter>(
           std::move(registry)));
 
 #if BUILDFLAG(ENABLE_SPELLCHECK)
   if (!spellcheck_) {
-    spellcheck_ = base::MakeUnique<SpellCheck>(this);
+    spellcheck_ = std::make_unique<SpellCheck>(this);
     thread->AddObserver(spellcheck_.get());
   }
 #endif
@@ -168,7 +168,7 @@
   new AwContentSettingsClient(render_frame);
   new PrintRenderFrameObserver(render_frame);
   new printing::PrintRenderFrameHelper(
-      render_frame, base::MakeUnique<AwPrintRenderFrameHelperDelegate>());
+      render_frame, std::make_unique<AwPrintRenderFrameHelperDelegate>());
   new AwRenderFrameExt(render_frame);
 
   // TODO(jam): when the frame tree moves into content and parent() works at
@@ -301,7 +301,7 @@
 AwContentRendererClient::CreateWebSocketHandshakeThrottle() {
   if (!UsingSafeBrowsingMojoService())
     return nullptr;
-  return base::MakeUnique<safe_browsing::WebSocketSBHandshakeThrottle>(
+  return std::make_unique<safe_browsing::WebSocketSBHandshakeThrottle>(
       safe_browsing_.get());
 }
 
@@ -315,7 +315,7 @@
     content::RenderFrame* render_frame =
         content::RenderFrame::FromWebFrame(frame);
     throttles->push_back(
-        base::MakeUnique<safe_browsing::RendererURLLoaderThrottle>(
+        std::make_unique<safe_browsing::RendererURLLoaderThrottle>(
             safe_browsing_.get(), render_frame->GetRoutingID()));
   }
 
diff --git a/android_webview/renderer/aw_render_frame_ext.cc b/android_webview/renderer/aw_render_frame_ext.cc
index 6680b9a..b837abd 100644
--- a/android_webview/renderer/aw_render_frame_ext.cc
+++ b/android_webview/renderer/aw_render_frame_ext.cc
@@ -4,6 +4,8 @@
 
 #include "android_webview/renderer/aw_render_frame_ext.h"
 
+#include <memory>
+
 #include "android_webview/common/aw_hit_test_data.h"
 #include "android_webview/common/render_view_messages.h"
 #include "base/strings/utf_string_conversions.h"
@@ -140,7 +142,7 @@
 
 AwRenderFrameExt::AwRenderFrameExt(content::RenderFrame* render_frame)
     : content::RenderFrameObserver(render_frame) {
-  registry_ = base::MakeUnique<service_manager::BinderRegistry>();
+  registry_ = std::make_unique<service_manager::BinderRegistry>();
 
   // TODO(sgurun) do not create a password autofill agent (change
   // autofill agent to store a weakptr).
diff --git a/base/version_unittest.cc b/base/version_unittest.cc
index 4ca784f..285ca9c 100644
--- a/base/version_unittest.cc
+++ b/base/version_unittest.cc
@@ -91,24 +91,31 @@
     const char* rhs;
     int expected;
   } cases[] = {
-    {"1.0", "1.0", 0},
-    {"1.0", "0.0", 1},
-    {"1.0", "2.0", -1},
-    {"1.0", "1.1", -1},
-    {"1.1", "1.0", 1},
-    {"1.0", "1.0.1", -1},
-    {"1.1", "1.0.1", 1},
-    {"1.1", "1.0.1", 1},
-    {"1.0.0", "1.0", 0},
-    {"1.0.3", "1.0.20", -1},
-    {"11.0.10", "15.007.20011", -1},
-    {"11.0.10", "15.5.28.130162", -1},
+      {"1.0", "1.0", 0},
+      {"1.0", "0.0", 1},
+      {"1.0", "2.0", -1},
+      {"1.0", "1.1", -1},
+      {"1.1", "1.0", 1},
+      {"1.0", "1.0.1", -1},
+      {"1.1", "1.0.1", 1},
+      {"1.1", "1.0.1", 1},
+      {"1.0.0", "1.0", 0},
+      {"1.0.3", "1.0.20", -1},
+      {"11.0.10", "15.007.20011", -1},
+      {"11.0.10", "15.5.28.130162", -1},
+      {"15.5.28.130162", "15.5.28.130162", 0},
   };
   for (size_t i = 0; i < arraysize(cases); ++i) {
     base::Version lhs(cases[i].lhs);
     base::Version rhs(cases[i].rhs);
     EXPECT_EQ(lhs.CompareTo(rhs), cases[i].expected) <<
         cases[i].lhs << " ? " << cases[i].rhs;
+    // CompareToWildcardString() should have same behavior as CompareTo() when
+    // no wildcards are present.
+    EXPECT_EQ(lhs.CompareToWildcardString(cases[i].rhs), cases[i].expected)
+        << cases[i].lhs << " ? " << cases[i].rhs;
+    EXPECT_EQ(rhs.CompareToWildcardString(cases[i].lhs), -cases[i].expected)
+        << cases[i].lhs << " ? " << cases[i].rhs;
 
     // Test comparison operators
     switch (cases[i].expected) {
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index 12eb04b..932c48d1 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -114,9 +114,6 @@
   if (command_line->HasSwitch(switches::kMus)) {
     params.create_discardable_memory = true;
     params.env_mode = aura::Env::Mode::MUS;
-    // TODO(786453): Remove when mus no longer needs to host viz.
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kMus, switches::kMusHostVizValue);
   }
   if (service_manager::ServiceManagerIsRemote() ||
       command_line->HasSwitch(switches::kMash)) {
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index f59c90e..1f11c19 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2562,8 +2562,8 @@
       "resource_coordinator/lifecycle_unit.h",
       "resource_coordinator/lifecycle_unit_source_observer.h",
       "resource_coordinator/tab_lifecycle_observer.h",
-      "resource_coordinator/tab_lifecycle_unit.cc",
-      "resource_coordinator/tab_lifecycle_unit.h",
+      "resource_coordinator/tab_lifecycle_unit_external.cc",
+      "resource_coordinator/tab_lifecycle_unit_external.h",
       "resource_coordinator/tab_manager.cc",
       "resource_coordinator/tab_manager.h",
       "resource_coordinator/tab_manager_delegate_chromeos.cc",
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit.cc b/chrome/browser/resource_coordinator/lifecycle_unit.cc
index c38b0b9..eee11d68 100644
--- a/chrome/browser/resource_coordinator/lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/lifecycle_unit.cc
@@ -19,4 +19,13 @@
   return last_focused_time > other.last_focused_time;
 }
 
+LifecycleUnit::LifecycleUnit() = default;
+LifecycleUnit::~LifecycleUnit() = default;
+
+uint32_t LifecycleUnit::GetID() const {
+  return id_;
+}
+
+uint32_t LifecycleUnit::next_id_ = 0;
+
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit.h b/chrome/browser/resource_coordinator/lifecycle_unit.h
index 8431a6e..887888fc 100644
--- a/chrome/browser/resource_coordinator/lifecycle_unit.h
+++ b/chrome/browser/resource_coordinator/lifecycle_unit.h
@@ -5,9 +5,11 @@
 #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_LIFECYCLE_UNIT_H_
 #define CHROME_BROWSER_RESOURCE_COORDINATOR_LIFECYCLE_UNIT_H_
 
+#include <stdint.h>
 #include <string>
 
 #include "base/containers/flat_set.h"
+#include "base/macros.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "chrome/browser/resource_coordinator/discard_reason.h"
@@ -41,7 +43,11 @@
     base::TimeTicks last_focused_time;
   };
 
-  virtual ~LifecycleUnit() = default;
+  LifecycleUnit();
+  virtual ~LifecycleUnit();
+
+  // Returns a unique id representing this LifecycleUnit.
+  uint32_t GetID() const;
 
   // Returns a title describing this LifecycleUnit, or an empty string if no
   // title is available.
@@ -84,6 +90,14 @@
   // in the same process(es) than if we discard individual LifecycleUnits.
   // https://crbug.com/775644
   virtual bool Discard(DiscardReason discard_reason) = 0;
+
+ private:
+  static uint32_t next_id_;
+
+  // A unique id representing this LifecycleUnit.
+  const uint32_t id_ = ++next_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(LifecycleUnit);
 };
 
 using LifecycleUnitSet = base::flat_set<LifecycleUnit*>;
diff --git a/chrome/browser/resource_coordinator/lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/lifecycle_unit_unittest.cc
index 69aaad4..16a0945 100644
--- a/chrome/browser/resource_coordinator/lifecycle_unit_unittest.cc
+++ b/chrome/browser/resource_coordinator/lifecycle_unit_unittest.cc
@@ -4,11 +4,33 @@
 
 #include "chrome/browser/resource_coordinator/lifecycle_unit.h"
 
+#include "base/macros.h"
 #include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace resource_coordinator {
 
+namespace {
+
+class DummyLifecycleUnit : public LifecycleUnit {
+ public:
+  DummyLifecycleUnit() = default;
+
+  // LifecycleUnit:
+  base::string16 GetTitle() const override { return base::string16(); }
+  std::string GetIconURL() const override { return std::string(); }
+  SortKey GetSortKey() const override { return SortKey(); }
+  State GetState() const override { return State::LOADED; }
+  int GetEstimatedMemoryFreedOnDiscardKB() const override { return 0; }
+  bool CanDiscard(DiscardReason reason) const override { return false; }
+  bool Discard(DiscardReason discard_reason) override { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DummyLifecycleUnit);
+};
+
+}  // namespace
+
 TEST(LifecycleUnitTest, SortKeyComparison) {
   constexpr base::TimeTicks kBaseTime;
   LifecycleUnit::SortKey a(kBaseTime);
@@ -40,4 +62,20 @@
   EXPECT_FALSE(c > c);
 }
 
+// Verify that GetID() returns different ids for different LifecycleUnits, but
+// always the same id for the same LifecycleUnit.
+TEST(LifecycleUnitTest, GetID) {
+  DummyLifecycleUnit a;
+  DummyLifecycleUnit b;
+  DummyLifecycleUnit c;
+
+  EXPECT_NE(a.GetID(), b.GetID());
+  EXPECT_NE(a.GetID(), c.GetID());
+  EXPECT_NE(b.GetID(), c.GetID());
+
+  EXPECT_EQ(a.GetID(), a.GetID());
+  EXPECT_EQ(b.GetID(), b.GetID());
+  EXPECT_EQ(c.GetID(), c.GetID());
+}
+
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
deleted file mode 100644
index 569848b..0000000
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h"
-
-#include "base/macros.h"
-#include "content/public/browser/web_contents_user_data.h"
-
-namespace resource_coordinator {
-
-namespace {
-
-class TabLifecycleUnitHolder
-    : public content::WebContentsUserData<TabLifecycleUnitHolder> {
- public:
-  explicit TabLifecycleUnitHolder(content::WebContents*) {}
-  TabLifecycleUnit* tab_lifecycle_unit() const { return tab_lifecycle_unit_; }
-  void set_tab_lifecycle_unit(TabLifecycleUnit* tab_lifecycle_unit) {
-    tab_lifecycle_unit_ = tab_lifecycle_unit;
-  }
-
- private:
-  TabLifecycleUnit* tab_lifecycle_unit_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(TabLifecycleUnitHolder);
-};
-
-}  // namespace
-
-// static
-TabLifecycleUnit* TabLifecycleUnit::FromWebContents(
-    content::WebContents* web_contents) {
-  TabLifecycleUnitHolder* holder =
-      TabLifecycleUnitHolder::FromWebContents(web_contents);
-  return holder ? holder->tab_lifecycle_unit() : nullptr;
-}
-
-// static
-void TabLifecycleUnit::SetForWebContents(content::WebContents* web_contents,
-                                         TabLifecycleUnit* tab_lifecycle_unit) {
-  TabLifecycleUnitHolder::CreateForWebContents(web_contents);
-  TabLifecycleUnitHolder::FromWebContents(web_contents)
-      ->set_tab_lifecycle_unit(tab_lifecycle_unit);
-}
-
-}  // namespace resource_coordinator
-
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(resource_coordinator::TabLifecycleUnitHolder);
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
deleted file mode 100644
index 77012d7..0000000
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_H_
-#define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_H_
-
-#include "chrome/browser/resource_coordinator/lifecycle_unit.h"
-
-namespace content {
-class RenderProcessHost;
-class WebContents;
-}  // namespace content
-
-namespace resource_coordinator {
-
-// Represents a tab.
-class TabLifecycleUnit : public LifecycleUnit {
- public:
-  // Returns the TabLifecycleUnit associated with |web_contents|, or nullptr if
-  // the WebContents is not associated with a tab.
-  static TabLifecycleUnit* FromWebContents(content::WebContents* web_contents);
-
-  // Returns the WebContents associated with this tab.
-  virtual content::WebContents* GetWebContents() const = 0;
-
-  // Returns the RenderProcessHost associated with this tab.
-  virtual content::RenderProcessHost* GetRenderProcessHost() const = 0;
-
-  // Returns true if the tab is playing audio, has played audio recently, is
-  // accessing the microphone, is accessing the camera or is being mirrored.
-  virtual bool IsMediaTab() const = 0;
-
-  // Returns true if this tab can be automatically discarded.
-  virtual bool IsAutoDiscardable() const = 0;
-
-  // Allows/disallows this tab to be automatically discarded.
-  virtual void SetAutoDiscardable(bool auto_discardable) = 0;
-
- protected:
-  // Sets the TabLifecycleUnit associated with |web_contents|.
-  static void SetForWebContents(content::WebContents* web_contents,
-                                TabLifecycleUnit* tab_lifecycle_unit);
-};
-
-}  // namespace resource_coordinator
-
-#endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_H_
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_external.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_external.cc
new file mode 100644
index 0000000..37f5447
--- /dev/null
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_external.cc
@@ -0,0 +1,16 @@
+// 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 "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h"
+
+namespace resource_coordinator {
+
+// static
+TabLifecycleUnitExternal* TabLifecycleUnitExternal::FromWebContents(
+    content::WebContents* web_contents) {
+  // TODO(fdoray): Implement this. https://crbug.com/775644
+  return nullptr;
+}
+
+}  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h
new file mode 100644
index 0000000..7a7144a
--- /dev/null
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h
@@ -0,0 +1,43 @@
+// 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 CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_EXTERNAL_H_
+#define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_EXTERNAL_H_
+
+namespace content {
+class WebContents;
+}  // namespace content
+
+namespace resource_coordinator {
+
+// Interface to control the lifecycle of a tab exposed outside of
+// chrome/browser/resource_coordinator/.
+class TabLifecycleUnitExternal {
+ public:
+  // Returns the TabLifecycleUnitExternal associated with |web_contents|, or
+  // nullptr if the WebContents is not associated with a tab.
+  static TabLifecycleUnitExternal* FromWebContents(
+      content::WebContents* web_contents);
+
+  virtual ~TabLifecycleUnitExternal() = default;
+
+  // Returns the WebContents associated with this tab.
+  virtual content::WebContents* GetWebContents() const = 0;
+
+  // Returns true if this tab can be automatically discarded.
+  virtual bool IsAutoDiscardable() const = 0;
+
+  // Allows/disallows this tab to be automatically discarded.
+  virtual void SetAutoDiscardable(bool auto_discardable) = 0;
+
+  // Discards the tab.
+  virtual void DiscardTab() = 0;
+
+  // Returns true if the tab is discarded.
+  virtual bool IsDiscarded() const = 0;
+};
+
+}  // namespace resource_coordinator
+
+#endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_EXTERNAL_H_
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
deleted file mode 100644
index 9281959..0000000
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/resource_coordinator/tab_lifecycle_unit.h"
-
-#include "base/macros.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace resource_coordinator {
-
-namespace {
-
-class DummyTabLifecycleUnit : public TabLifecycleUnit {
- public:
-  explicit DummyTabLifecycleUnit(content::WebContents* contents)
-      : contents_(contents) {
-    TabLifecycleUnit::SetForWebContents(contents_, this);
-  }
-
-  ~DummyTabLifecycleUnit() override {
-    TabLifecycleUnit::SetForWebContents(contents_, nullptr);
-  }
-
-  // TabLifecycleUnit:
-  content::WebContents* GetWebContents() const override { return nullptr; }
-  content::RenderProcessHost* GetRenderProcessHost() const override {
-    return nullptr;
-  }
-  bool IsMediaTab() const override { return false; }
-  bool IsAutoDiscardable() const override { return false; }
-  void SetAutoDiscardable(bool) override {}
-
-  // LifecycleUnit:
-  base::string16 GetTitle() const override { return base::string16(); }
-  std::string GetIconURL() const override { return std::string(); }
-  SortKey GetSortKey() const override { return SortKey(); }
-  State GetState() const override { return State::LOADED; }
-  int GetEstimatedMemoryFreedOnDiscardKB() const override { return 0; }
-  bool CanDiscard(DiscardReason) const override { return false; }
-  bool Discard(DiscardReason) override { return false; }
-
- private:
-  content::WebContents* const contents_;
-
-  DISALLOW_COPY_AND_ASSIGN(DummyTabLifecycleUnit);
-};
-
-}  // namespace
-
-using TabLifecycleUnitTest = ChromeRenderViewHostTestHarness;
-
-TEST_F(TabLifecycleUnitTest, FromWebContentsNullByDefault) {
-  EXPECT_FALSE(TabLifecycleUnit::FromWebContents(web_contents()));
-}
-
-TEST_F(TabLifecycleUnitTest, SetForWebContents) {
-  {
-    DummyTabLifecycleUnit tab_lifecycle_unit(web_contents());
-    EXPECT_EQ(&tab_lifecycle_unit,
-              TabLifecycleUnit::FromWebContents(web_contents()));
-  }
-  EXPECT_FALSE(TabLifecycleUnit::FromWebContents(web_contents()));
-  {
-    DummyTabLifecycleUnit tab_lifecycle_unit(web_contents());
-    EXPECT_EQ(&tab_lifecycle_unit,
-              TabLifecycleUnit::FromWebContents(web_contents()));
-  }
-  EXPECT_FALSE(TabLifecycleUnit::FromWebContents(web_contents()));
-}
-
-}  // namespace resource_coordinator
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc
index 626090c..14386af 100644
--- a/chrome/browser/search/search.cc
+++ b/chrome/browser/search/search.cc
@@ -276,8 +276,14 @@
   if (!contents)
     return false;
 
-  return NavEntryIsInstantNTP(contents,
-                              contents->GetController().GetVisibleEntry());
+  if (contents->ShowingInterstitialPage())
+    return false;
+
+  const content::NavigationEntry* entry =
+      contents->GetController().GetLastCommittedEntry();
+  if (!entry)
+    entry = contents->GetController().GetVisibleEntry();
+  return NavEntryIsInstantNTP(contents, entry);
 }
 
 bool NavEntryIsInstantNTP(const content::WebContents* contents,
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h
index 27a3245..04ed373 100644
--- a/chrome/browser/search/search.h
+++ b/chrome/browser/search/search.h
@@ -36,8 +36,9 @@
 // to an NTP, but aren't an NTP themselves (such as the NTP's service worker).
 bool IsNTPURL(const GURL& url, Profile* profile);
 
-// Returns true if the visible entry of |contents| is a New Tab page rendered
-// in an Instant process.
+// Returns true if the active navigation entry of |contents| is a New Tab page
+// rendered in an Instant process. This is the last committed entry if it
+// exists, and otherwise the visible entry.
 bool IsInstantNTP(const content::WebContents* contents);
 
 // Same as IsInstantNTP but uses |nav_entry| to determine the URL for the page
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc
index 93ca30c5..89aea28 100644
--- a/chrome/browser/search/search_unittest.cc
+++ b/chrome/browser/search/search_unittest.cc
@@ -275,8 +275,7 @@
 
 TEST_F(SearchTest, InstantNTPExtendedEnabled) {
   AddTab(browser(), GURL("chrome://blank"));
-  for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
-    const SearchTestCase& test = kInstantNTPTestCases[i];
+  for (const SearchTestCase& test : kInstantNTPTestCases) {
     NavigateAndCommitActiveTab(GURL(test.url));
     const content::WebContents* contents =
         browser()->tab_strip_model()->GetWebContentsAt(0);
@@ -287,8 +286,7 @@
 
 TEST_F(SearchTest, InstantNTPCustomNavigationEntry) {
   AddTab(browser(), GURL("chrome://blank"));
-  for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
-    const SearchTestCase& test = kInstantNTPTestCases[i];
+  for (const SearchTestCase& test : kInstantNTPTestCases) {
     NavigateAndCommitActiveTab(GURL(test.url));
     content::WebContents* contents =
         browser()->tab_strip_model()->GetWebContentsAt(0);
@@ -300,12 +298,14 @@
                                          false,
                                          std::string(),
                                          contents->GetBrowserContext()));
-    // The active entry is chrome://blank and not an NTP.
-    EXPECT_FALSE(IsInstantNTP(contents));
+    // The visible entry is now chrome://blank, but this is still an NTP.
+    EXPECT_FALSE(NavEntryIsInstantNTP(contents, controller.GetVisibleEntry()));
     EXPECT_EQ(test.expected_result,
               NavEntryIsInstantNTP(contents,
                                    controller.GetLastCommittedEntry()))
         << test.url << " " << test.comment;
+    EXPECT_EQ(test.expected_result, IsInstantNTP(contents))
+        << test.url << " " << test.comment;
   }
 }
 
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc
index ba51b96..2bcdc81 100644
--- a/chrome/browser/ui/search/local_ntp_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -5,14 +5,20 @@
 #include <memory>
 #include <string>
 
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/i18n/base_i18n_switches.h"
+#include "base/memory/weak_ptr.h"
 #include "base/metrics/statistics_recorder.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/instant_service.h"
+#include "chrome/browser/search/instant_service_factory.h"
+#include "chrome/browser/search/instant_service_observer.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -20,19 +26,32 @@
 #include "chrome/browser/ui/search/local_ntp_test_utils.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/common/search/instant_types.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/interstitial_page.h"
+#include "content/public/browser/interstitial_page_delegate.h"
 #include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/download_test_observer.h"
 #include "content/public/test/test_navigation_observer.h"
-#include "testing/gmock/include/gmock/gmock.h"
+#include "content/public/test/test_navigation_throttle_inserter.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/platform/web_feature.mojom.h"
 #include "url/gurl.h"
 
+namespace {
+
+// In a non-signed-in, fresh profile with no history, there should be two
+// default TopSites tiles (see history::PrepopulatedPage).
+const int kDefaultMostVisitedItemCount = 2;
+
 class LocalNTPTest : public InProcessBrowserTest {
  public:
   LocalNTPTest() {}
@@ -215,6 +234,136 @@
   }
 }
 
+class TestMostVisitedObserver : public InstantServiceObserver {
+ public:
+  explicit TestMostVisitedObserver(InstantService* service)
+      : service_(service), expected_count_(0) {
+    service_->AddObserver(this);
+  }
+
+  ~TestMostVisitedObserver() override { service_->RemoveObserver(this); }
+
+  void WaitForNumberOfItems(size_t count) {
+    DCHECK(!quit_closure_);
+
+    expected_count_ = count;
+
+    if (items_.size() == count) {
+      return;
+    }
+
+    base::RunLoop run_loop;
+    quit_closure_ = run_loop.QuitClosure();
+    run_loop.Run();
+  }
+
+ private:
+  void ThemeInfoChanged(const ThemeBackgroundInfo&) override {}
+
+  void MostVisitedItemsChanged(
+      const std::vector<InstantMostVisitedItem>& items) override {
+    items_ = items;
+
+    if (quit_closure_ && items_.size() == expected_count_) {
+      std::move(quit_closure_).Run();
+      quit_closure_.Reset();
+    }
+  }
+
+  InstantService* const service_;
+
+  std::vector<InstantMostVisitedItem> items_;
+
+  size_t expected_count_;
+  base::OnceClosure quit_closure_;
+};
+
+IN_PROC_BROWSER_TEST_F(LocalNTPTest, EmbeddedSearchAPIEndToEnd) {
+  content::WebContents* active_tab =
+      local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
+
+  TestMostVisitedObserver observer(
+      InstantServiceFactory::GetForProfile(browser()->profile()));
+
+  // Navigating to an NTP should trigger an update of the MV items.
+  NavigateToNTPAndWaitUntilLoaded();
+  observer.WaitForNumberOfItems(kDefaultMostVisitedItemCount);
+
+  // Make sure the same number of items is available in JS.
+  int most_visited_count = -1;
+  ASSERT_TRUE(instant_test_utils::GetIntFromJS(
+      active_tab, "window.chrome.embeddedSearch.newTabPage.mostVisited.length",
+      &most_visited_count));
+  ASSERT_EQ(kDefaultMostVisitedItemCount, most_visited_count);
+
+  // Get the ID of one item.
+  int most_visited_rid = -1;
+  ASSERT_TRUE(instant_test_utils::GetIntFromJS(
+      active_tab, "window.chrome.embeddedSearch.newTabPage.mostVisited[0].rid",
+      &most_visited_rid));
+
+  // Delete that item. The deletion should arrive on the native side.
+  ASSERT_TRUE(content::ExecuteScript(
+      active_tab,
+      base::StringPrintf(
+          "window.chrome.embeddedSearch.newTabPage.deleteMostVisitedItem(%d)",
+          most_visited_rid)));
+  observer.WaitForNumberOfItems(kDefaultMostVisitedItemCount - 1);
+}
+
+// Regression test for crbug.com/592273.
+IN_PROC_BROWSER_TEST_F(LocalNTPTest, EmbeddedSearchAPIAfterDownload) {
+  // Set up a test server, so we have some URL to download.
+  net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+  test_server.ServeFilesFromSourceDirectory("chrome/test/data");
+  ASSERT_TRUE(test_server.Start());
+  const GURL download_url = test_server.GetURL("/download-test1.lib");
+
+  content::WebContents* active_tab =
+      local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
+
+  TestMostVisitedObserver observer(
+      InstantServiceFactory::GetForProfile(browser()->profile()));
+
+  // Navigating to an NTP should trigger an update of the MV items.
+  NavigateToNTPAndWaitUntilLoaded();
+  observer.WaitForNumberOfItems(kDefaultMostVisitedItemCount);
+
+  // Download some file.
+  content::DownloadTestObserverTerminal download_observer(
+      content::BrowserContext::GetDownloadManager(browser()->profile()), 1,
+      content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_ACCEPT);
+  ui_test_utils::NavigateToURL(browser(), download_url);
+  download_observer.WaitForFinished();
+
+  // This should have changed the visible URL, but not the last committed one.
+  ASSERT_EQ(download_url, active_tab->GetVisibleURL());
+  ASSERT_EQ(GURL(chrome::kChromeUINewTabURL),
+            active_tab->GetLastCommittedURL());
+
+  // Make sure the same number of items is available in JS.
+  int most_visited_count = -1;
+  ASSERT_TRUE(instant_test_utils::GetIntFromJS(
+      active_tab, "window.chrome.embeddedSearch.newTabPage.mostVisited.length",
+      &most_visited_count));
+  ASSERT_EQ(kDefaultMostVisitedItemCount, most_visited_count);
+
+  // Get the ID of one item.
+  int most_visited_rid = -1;
+  ASSERT_TRUE(instant_test_utils::GetIntFromJS(
+      active_tab, "window.chrome.embeddedSearch.newTabPage.mostVisited[0].rid",
+      &most_visited_rid));
+
+  // Since the current page is still an NTP, it should be possible to delete MV
+  // items (as well as anything else that the embeddedSearch API allows).
+  ASSERT_TRUE(content::ExecuteScript(
+      active_tab,
+      base::StringPrintf(
+          "window.chrome.embeddedSearch.newTabPage.deleteMostVisitedItem(%d)",
+          most_visited_rid)));
+  observer.WaitForNumberOfItems(kDefaultMostVisitedItemCount - 1);
+}
+
 IN_PROC_BROWSER_TEST_F(LocalNTPTest, NTPRespectsBrowserLanguageSetting) {
   // If the platform cannot load the French locale (GetApplicationLocale() is
   // platform specific, and has been observed to fail on a small number of
@@ -432,8 +581,6 @@
   EXPECT_EQ("rtl", dir);
 }
 
-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) {
@@ -445,8 +592,6 @@
   return nullptr;
 }
 
-}  // namespace
-
 IN_PROC_BROWSER_TEST_F(LocalNTPTest, LoadsIframe) {
   content::WebContents* active_tab =
       local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
@@ -482,3 +627,100 @@
   EXPECT_EQ(total_thumbs, succeeded_imgs);
   EXPECT_EQ(0, failed_imgs);
 }
+
+// A minimal implementation of an interstitial page.
+class TestInterstitialPageDelegate : public content::InterstitialPageDelegate {
+ public:
+  static void Show(content::WebContents* web_contents, const GURL& url) {
+    // The InterstitialPage takes ownership of this object, and will delete it
+    // when it gets destroyed itself.
+    new TestInterstitialPageDelegate(web_contents, url);
+  }
+
+  ~TestInterstitialPageDelegate() override {}
+
+ private:
+  TestInterstitialPageDelegate(content::WebContents* web_contents,
+                               const GURL& url) {
+    // |page| takes ownership of |this|.
+    content::InterstitialPage* page =
+        content::InterstitialPage::Create(web_contents, true, url, this);
+    page->Show();
+  }
+
+  std::string GetHTMLContents() override { return "<html></html>"; }
+
+  DISALLOW_COPY_AND_ASSIGN(TestInterstitialPageDelegate);
+};
+
+// A navigation throttle that will create an interstitial for all pages except
+// chrome-search:// ones (i.e. the local NTP).
+class TestNavigationThrottle : public content::NavigationThrottle {
+ public:
+  explicit TestNavigationThrottle(content::NavigationHandle* handle)
+      : content::NavigationThrottle(handle), weak_ptr_factory_(this) {}
+
+  static std::unique_ptr<NavigationThrottle> Create(
+      content::NavigationHandle* handle) {
+    return std::make_unique<TestNavigationThrottle>(handle);
+  }
+
+ private:
+  ThrottleCheckResult WillStartRequest() override {
+    const GURL& url = navigation_handle()->GetURL();
+    if (url.SchemeIs(chrome::kChromeSearchScheme)) {
+      return NavigationThrottle::PROCEED;
+    }
+
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindRepeating(&TestNavigationThrottle::ShowInterstitial,
+                            weak_ptr_factory_.GetWeakPtr()));
+    return NavigationThrottle::DEFER;
+  }
+
+  const char* GetNameForLogging() override { return "TestNavigationThrottle"; }
+
+  void ShowInterstitial() {
+    TestInterstitialPageDelegate::Show(navigation_handle()->GetWebContents(),
+                                       navigation_handle()->GetURL());
+  }
+
+  base::WeakPtrFactory<TestNavigationThrottle> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestNavigationThrottle);
+};
+
+IN_PROC_BROWSER_TEST_F(LocalNTPTest, InterstitialsAreNotNTPs) {
+  // Set up a test server, so we have some non-NTP URL to navigate to.
+  net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+  test_server.ServeFilesFromSourceDirectory("chrome/test/data");
+  ASSERT_TRUE(test_server.Start());
+
+  content::WebContents* active_tab =
+      local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
+
+  content::TestNavigationThrottleInserter throttle_inserter(
+      active_tab, base::BindRepeating(&TestNavigationThrottle::Create));
+
+  NavigateToNTPAndWaitUntilLoaded();
+  ASSERT_TRUE(search::IsInstantNTP(active_tab));
+
+  // Navigate to some non-NTP URL, which will result in an interstitial.
+  const GURL blocked_url = test_server.GetURL("/simple.html");
+  ui_test_utils::NavigateToURL(browser(), blocked_url);
+  content::WaitForInterstitialAttach(active_tab);
+  ASSERT_TRUE(active_tab->ShowingInterstitialPage());
+  ASSERT_EQ(blocked_url, active_tab->GetVisibleURL());
+  // The interstitial is not an NTP (even though the committed URL may still
+  // point to an NTP, see crbug.com/448486).
+  EXPECT_FALSE(search::IsInstantNTP(active_tab));
+
+  // Go back to the NTP.
+  chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
+  content::WaitForInterstitialDetach(active_tab);
+  // Now the page should be an NTP again.
+  EXPECT_TRUE(search::IsInstantNTP(active_tab));
+}
+
+}  // namespace
diff --git a/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc b/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc
index 5469833f..bb84aca 100644
--- a/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc
+++ b/chrome/browser/ui/search/search_ipc_router_policy_unittest.cc
@@ -4,14 +4,12 @@
 
 #include "chrome/browser/ui/search/search_ipc_router.h"
 
-#include "build/build_config.h"
-#include "base/command_line.h"
 #include "chrome/browser/ui/search/search_ipc_router_policy_impl.h"
 #include "chrome/browser/ui/search/search_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
+#include "content/public/browser/page_navigator.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
@@ -30,7 +28,7 @@
   SearchIPCRouter::Policy* GetSearchIPCRouterPolicy() {
     SearchTabHelper* search_tab_helper =
         SearchTabHelper::FromWebContents(web_contents());
-    EXPECT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
+    EXPECT_NE(nullptr, search_tab_helper);
     return search_tab_helper->ipc_router_for_testing().policy_for_testing();
   }
 
@@ -46,6 +44,28 @@
   EXPECT_TRUE(GetSearchIPCRouterPolicy()->ShouldProcessFocusOmnibox(true));
 }
 
+// Regression test for crbug.com/592273.
+TEST_F(SearchIPCRouterPolicyTest, ProcessFocusOmniboxAfterDownload) {
+  // Open an NTP.
+  NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl));
+  ASSERT_TRUE(GetSearchIPCRouterPolicy()->ShouldProcessFocusOmnibox(true));
+
+  // Simulate a download by opening a URL without committing it.
+  browser()->OpenURL(content::OpenURLParams(
+      GURL("http://foo/download.zip"), content::Referrer(),
+      WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
+
+  // Now the visible URL corresponds to the download, but the last committed URL
+  // is still the NTP.
+  const content::WebContents* tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_EQ(GURL("http://foo/download.zip"), tab->GetVisibleURL());
+  ASSERT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), tab->GetLastCommittedURL());
+
+  // In this state, we should still accept IPC messages.
+  EXPECT_TRUE(GetSearchIPCRouterPolicy()->ShouldProcessFocusOmnibox(true));
+}
+
 TEST_F(SearchIPCRouterPolicyTest, DoNotProcessFocusOmnibox) {
   // Process message only if the underlying page is an InstantNTP.
   NavigateAndCommitActiveTab(GURL("chrome-search://foo/bar"));
diff --git a/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc b/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc
index bc688ba..7f48628 100644
--- a/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc
+++ b/chrome/browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc
@@ -203,9 +203,7 @@
 
 // Tests that when focus is in the omnibox and the user types a url and
 // presses enter, no focus events are sent on the old document.
-// TODO(dmazzoni): enable this test.  http://crbug.com/421116
-IN_PROC_BROWSER_TEST_F(NavigationAccessibilityTest,
-                       DISABLED_TestNavigateToNewUrl) {
+IN_PROC_BROWSER_TEST_F(NavigationAccessibilityTest, TestNavigateToNewUrl) {
   content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
 
   ui_test_utils::NavigateToURL(browser(),
diff --git a/chrome/installer/zucchini/binary_data_histogram.cc b/chrome/installer/zucchini/binary_data_histogram.cc
index 3fa283a..08d7c23 100644
--- a/chrome/installer/zucchini/binary_data_histogram.cc
+++ b/chrome/installer/zucchini/binary_data_histogram.cc
@@ -4,14 +4,59 @@
 
 #include "chrome/installer/zucchini/binary_data_histogram.h"
 
+#include <algorithm>
 #include <cmath>
 #include <limits>
 
+#include "base/format_macros.h"
 #include "base/logging.h"
-#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
 
 namespace zucchini {
 
+/******** OutlierDetector ********/
+
+OutlierDetector::OutlierDetector() = default;
+
+OutlierDetector::~OutlierDetector() = default;
+
+// For BinaryDataHistogram, |sample| is typically in interval [0, 1].
+void OutlierDetector::Add(double sample) {
+  ++n_;
+  sum_ += sample;
+  sum_of_squares_ += sample * sample;
+}
+
+void OutlierDetector::Prepare() {
+  if (n_ > 0) {
+    mean_ = sum_ / n_;
+    standard_deviation_ = ::sqrt((sum_of_squares_ - sum_ * mean_) /
+                                 std::max(static_cast<size_t>(1), n_ - 1));
+  }
+}
+
+std::string OutlierDetector::RenderStats() {
+  return base::StringPrintf("Mean = %.5f, StdDev = %.5f over %" PRIuS
+                            " samples",
+                            mean_, standard_deviation_, n_);
+}
+
+// Constants are chosen for BinaryDataHistogram, where |sample| is typically in
+// [0, 1].
+int OutlierDetector::DecideOutlier(double sample) {
+  // Lower bound to avoid divide-by-zero and penalizing tight clusters.
+  constexpr double kMinTolerance = 0.1;
+  // Number of standard deviations away from mean for value to become outlier.
+  constexpr double kSigmaBound = 1.9;
+  if (n_ <= 1)
+    return 0;
+  double tolerance = std::max(kMinTolerance, standard_deviation_);
+  double num_sigma = (sample - mean_) / tolerance;
+  return num_sigma > kSigmaBound ? 1 : num_sigma < -kSigmaBound ? -1 : 0;
+}
+
+/******** BinaryDataHistogram ********/
+
 BinaryDataHistogram::BinaryDataHistogram() = default;
 
 BinaryDataHistogram::~BinaryDataHistogram() = default;
@@ -24,7 +69,7 @@
   DCHECK_LE(region.size(),
             static_cast<size_t>(std::numeric_limits<int32_t>::max()));
 
-  histogram_ = base::MakeUnique<int32_t[]>(kNumBins);
+  histogram_ = std::make_unique<int32_t[]>(kNumBins);
   size_ = region.size();
   // Number of 2-byte intervals fully contained in |region|.
   size_t bound = size_ - sizeof(uint16_t) + 1;
diff --git a/chrome/installer/zucchini/binary_data_histogram.h b/chrome/installer/zucchini/binary_data_histogram.h
index fcf7a45..1fac068f 100644
--- a/chrome/installer/zucchini/binary_data_histogram.h
+++ b/chrome/installer/zucchini/binary_data_histogram.h
@@ -9,12 +9,48 @@
 #include <stdint.h>
 
 #include <memory>
+#include <string>
 
 #include "base/macros.h"
 #include "chrome/installer/zucchini/buffer_view.h"
 
 namespace zucchini {
 
+// A class to detect outliers in a list of doubles using Chauvenet's criterion:
+// Compute mean and standard deviation of observations, then determine whether
+// a query value lies beyond a fixed number of standard deviations (sigmas) from
+// the mean. The purpose of this test is to reduce the chance of false-positive
+// ensemble matches.
+class OutlierDetector {
+ public:
+  OutlierDetector();
+  ~OutlierDetector();
+
+  // Incorporates |sample| into mean and standard deviation.
+  void Add(double sample);
+
+  // Prepares basic statistics for DecideOutlier() calls. Should be called after
+  // all samples have been added.
+  void Prepare();
+
+  // Renders current statistics as strings for logging.
+  std::string RenderStats();
+
+  // Heuristically decides whether |sample| is an outlier. Returns 1 if |sample|
+  // is "too high", 0 if |sample| is "normal", and -1 if |sample| is "too low".
+  // Must be called after Prepare().
+  int DecideOutlier(double sample);
+
+ private:
+  size_t n_ = 0;
+  double sum_ = 0;
+  double sum_of_squares_ = 0;
+  double mean_ = 0;
+  double standard_deviation_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(OutlierDetector);
+};
+
 // A class to compute similarity score between binary data. The heuristic here
 // preprocesses input data to a size-65536 histogram, counting the frequency of
 // consecutive 2-byte sequences. Therefore data with lengths < 2 are considered
diff --git a/chrome/installer/zucchini/binary_data_histogram_unittest.cc b/chrome/installer/zucchini/binary_data_histogram_unittest.cc
index f6cf89e..f7aa44c 100644
--- a/chrome/installer/zucchini/binary_data_histogram_unittest.cc
+++ b/chrome/installer/zucchini/binary_data_histogram_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <memory>
 #include <vector>
 
 #include "chrome/installer/zucchini/buffer_view.h"
@@ -13,6 +14,65 @@
 
 namespace zucchini {
 
+TEST(OutlierDetectorTest, Basic) {
+  auto make_detector = [](const std::vector<double>& values) {
+    auto detector = std::make_unique<OutlierDetector>();
+    for (double v : values)
+      detector->Add(v);
+    detector->Prepare();
+    return detector;
+  };
+
+  std::unique_ptr<OutlierDetector> detector;
+  // No data: Should at least not cause error.
+  detector = make_detector({});
+  EXPECT_EQ(0, detector->DecideOutlier(0.0));
+  // Single point: Trivially inert.
+  detector = make_detector({0.5});
+  EXPECT_EQ(0, detector->DecideOutlier(0.1));
+  EXPECT_EQ(0, detector->DecideOutlier(0.5));
+  EXPECT_EQ(0, detector->DecideOutlier(0.9));
+  // Two identical points: StdDev is 0, so falls back to built-in tolerance.
+  detector = make_detector({0.5, 0.5});
+  EXPECT_EQ(-1, detector->DecideOutlier(0.3));
+  EXPECT_EQ(0, detector->DecideOutlier(0.499));
+  EXPECT_EQ(0, detector->DecideOutlier(0.5));
+  EXPECT_EQ(0, detector->DecideOutlier(0.501));
+  EXPECT_EQ(1, detector->DecideOutlier(0.7));
+  // Two separate points: Outliner test is pretty lax.
+  detector = make_detector({0.4, 0.6});
+  EXPECT_EQ(-1, detector->DecideOutlier(0.2));
+  EXPECT_EQ(0, detector->DecideOutlier(0.3));
+  EXPECT_EQ(0, detector->DecideOutlier(0.5));
+  EXPECT_EQ(0, detector->DecideOutlier(0.7));
+  EXPECT_EQ(1, detector->DecideOutlier(0.8));
+  // Sharpen distribution by clustering toward norm: Now test is stricter.
+  detector = make_detector({0.4, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52, 0.6});
+  EXPECT_EQ(-1, detector->DecideOutlier(0.3));
+  EXPECT_EQ(0, detector->DecideOutlier(0.4));
+  EXPECT_EQ(0, detector->DecideOutlier(0.5));
+  EXPECT_EQ(0, detector->DecideOutlier(0.6));
+  EXPECT_EQ(1, detector->DecideOutlier(0.7));
+  // Shift numbers around: Mean is 0.3, and data order scrambled.
+  detector = make_detector({0.28, 0.2, 0.31, 0.4, 0.29, 0.32, 0.27, 0.30});
+  EXPECT_EQ(-1, detector->DecideOutlier(0.0));
+  EXPECT_EQ(-1, detector->DecideOutlier(0.1));
+  EXPECT_EQ(0, detector->DecideOutlier(0.2));
+  EXPECT_EQ(0, detector->DecideOutlier(0.3));
+  EXPECT_EQ(0, detector->DecideOutlier(0.4));
+  EXPECT_EQ(1, detector->DecideOutlier(0.5));
+  EXPECT_EQ(1, detector->DecideOutlier(1.0));
+  // Typical usage: Potential outlier would be part of original input data!
+  detector = make_detector({0.3, 0.29, 0.31, 0.0, 0.3, 0.32, 0.3, 0.29, 0.6});
+  EXPECT_EQ(-1, detector->DecideOutlier(0.0));
+  EXPECT_EQ(0, detector->DecideOutlier(0.28));
+  EXPECT_EQ(0, detector->DecideOutlier(0.29));
+  EXPECT_EQ(0, detector->DecideOutlier(0.3));
+  EXPECT_EQ(0, detector->DecideOutlier(0.31));
+  EXPECT_EQ(0, detector->DecideOutlier(0.32));
+  EXPECT_EQ(1, detector->DecideOutlier(0.6));
+}
+
 TEST(BinaryDataHistogramTest, Basic) {
   constexpr double kUninitScore = -1;
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 68b17f7..8a66ffa 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2746,7 +2746,6 @@
       "../browser/page_load_metrics/observers/session_restore_page_load_metrics_observer_unittest.cc",
       "../browser/resource_coordinator/background_tab_navigation_throttle_unittest.cc",
       "../browser/resource_coordinator/lifecycle_unit_unittest.cc",
-      "../browser/resource_coordinator/tab_lifecycle_unit_unittest.cc",
       "../browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc",
       "../browser/resource_coordinator/tab_manager_stats_collector_unittest.cc",
       "../browser/resource_coordinator/tab_manager_unittest.cc",
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index f3963ef0..09333e8 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -631,13 +631,40 @@
 #if defined(USE_OZONE)
   // Ozone needs to send the primary DRM device to GPU process as early as
   // possible to ensure the latter always has a valid device. crbug.com/608839
-  ui::OzonePlatform::GetInstance()
-      ->GetGpuPlatformSupportHost()
-      ->OnGpuProcessLaunched(
-          host_id_, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
-          base::ThreadTaskRunnerHandle::Get(),
-          base::Bind(&SendGpuProcessMessage, weak_ptr_factory_.GetWeakPtr()));
-#endif
+  // When running with mus, the OzonePlatform may not have been created yet. So
+  // defer the callback until OzonePlatform instance is created.
+  auto send_callback = base::BindRepeating(&SendGpuProcessMessage,
+                                           weak_ptr_factory_.GetWeakPtr());
+  // Create the callback that should run on the current thread (i.e. IO thread).
+  auto io_callback = base::BindOnce(
+      [](int host_id,
+         const base::RepeatingCallback<void(IPC::Message*)>& send_callback,
+         ui::OzonePlatform* platform) {
+        DCHECK_CURRENTLY_ON(BrowserThread::IO);
+        platform->GetGpuPlatformSupportHost()->OnGpuProcessLaunched(
+            host_id, BrowserThread::GetTaskRunnerForThread(BrowserThread::UI),
+            BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
+            send_callback);
+      },
+      host_id_, send_callback);
+  // The callback registered in ozone can be called in any thread. So use an
+  // intermediary callback that bounces to the IO thread if needed, before
+  // running the callback.
+  auto bounce_callback = base::BindOnce(
+      [](base::TaskRunner* task_runner,
+         base::OnceCallback<void(ui::OzonePlatform*)> callback,
+         ui::OzonePlatform* platform) {
+        if (task_runner->RunsTasksInCurrentSequence()) {
+          std::move(callback).Run(platform);
+        } else {
+          task_runner->PostTask(FROM_HERE,
+                                base::BindOnce(std::move(callback), platform));
+        }
+      },
+      base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+      base::Passed(&io_callback));
+  ui::OzonePlatform::RegisterStartupCallback(std::move(bounce_callback));
+#endif  // defined(USE_OZONE)
 
   return true;
 }
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
index 7a8c3149..3c4ec78 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -23,6 +23,7 @@
 #include "content/test/test_content_browser_client.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "ui/base/ui_base_switches_util.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace content {
@@ -155,8 +156,9 @@
 // Tests that while in mus, the child frame receives an updated FrameSinkId
 // representing the frame sink used by the RenderFrameProxy.
 IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameTest, ChildFrameSinkId) {
-  // Only in mus do we expect a RenderFrameProxy to provide the FrameSinkId.
-  if (!IsUsingMus())
+  // Only when mus hosts viz do we expect a RenderFrameProxy to provide the
+  // FrameSinkId.
+  if (!switches::IsMusHostingViz())
     return;
 
   GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
diff --git a/content/test/content_test_launcher.cc b/content/test/content_test_launcher.cc
index ed97d02..5aa3919 100644
--- a/content/test/content_test_launcher.cc
+++ b/content/test/content_test_launcher.cc
@@ -52,12 +52,6 @@
  public:
   ContentBrowserTestSuite(int argc, char** argv)
       : ContentTestSuiteBase(argc, argv) {
-#if BUILDFLAG(ENABLE_MUS)
-    // TODO(786453): This should be removed once mus can run without viz.
-    auto* cmd = base::CommandLine::ForCurrentProcess();
-    if (cmd->HasSwitch(switches::kMus))
-      cmd->AppendSwitchASCII(switches::kMus, switches::kMusHostVizValue);
-#endif
   }
   ~ContentBrowserTestSuite() override {}
 
diff --git a/content/test/data/accessibility/aria/aria-autocomplete-expected-android.txt b/content/test/data/accessibility/aria/aria-autocomplete-expected-android.txt
index 5bb07bd9..c64c530f 100644
--- a/content/test/data/accessibility/aria/aria-autocomplete-expected-android.txt
+++ b/content/test/data/accessibility/aria/aria-autocomplete-expected-android.txt
@@ -3,4 +3,5 @@
 ++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='autocomplete=inline' input_type=1 text_change_added_count=19
 ++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='autocomplete=list' input_type=1 text_change_added_count=17
 ++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='autocomplete=both' input_type=1 text_change_added_count=17
-++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='autocomplete=none' input_type=1 text_change_added_count=17
\ No newline at end of file
+++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='autocomplete=none' input_type=1 text_change_added_count=17
+++++android.widget.EditText clickable editable_text focusable has_non_empty_value name='No role with autocomplete=inline' input_type=1 text_change_added_count=32
diff --git a/content/test/data/accessibility/aria/aria-autocomplete-expected-blink.txt b/content/test/data/accessibility/aria/aria-autocomplete-expected-blink.txt
index 3a3f4320..d08611b 100644
--- a/content/test/data/accessibility/aria/aria-autocomplete-expected-blink.txt
+++ b/content/test/data/accessibility/aria/aria-autocomplete-expected-blink.txt
@@ -15,4 +15,8 @@
 ++++textFieldWithComboBox haspopup
 ++++++genericContainer
 ++++++++staticText name='autocomplete=none'
-++++++++++inlineTextBox name='autocomplete=none'
\ No newline at end of file
+++++++++++inlineTextBox name='autocomplete=none'
+++++textField autoComplete='inline'
+++++++genericContainer
+++++++++staticText name='No role with autocomplete=inline'
+++++++++++inlineTextBox name='No role with autocomplete=inline'
diff --git a/content/test/data/accessibility/aria/aria-autocomplete-expected-win.txt b/content/test/data/accessibility/aria/aria-autocomplete-expected-win.txt
index d53bb47..27f603f 100644
--- a/content/test/data/accessibility/aria/aria-autocomplete-expected-win.txt
+++ b/content/test/data/accessibility/aria/aria-autocomplete-expected-win.txt
@@ -3,4 +3,5 @@
 ++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP IA2_STATE_SUPPORTS_AUTOCOMPLETION autocomplete:inline
 ++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP IA2_STATE_SUPPORTS_AUTOCOMPLETION autocomplete:list
 ++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP IA2_STATE_SUPPORTS_AUTOCOMPLETION autocomplete:both
-++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP
\ No newline at end of file
+++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP
+++++ROLE_SYSTEM_TEXT FOCUSABLE IA2_STATE_SUPPORTS_AUTOCOMPLETION autocomplete:inline
diff --git a/content/test/data/accessibility/aria/aria-autocomplete.html b/content/test/data/accessibility/aria/aria-autocomplete.html
index 9205720..f01dbe91 100644
--- a/content/test/data/accessibility/aria/aria-autocomplete.html
+++ b/content/test/data/accessibility/aria/aria-autocomplete.html
@@ -8,5 +8,8 @@
   <input role="combobox" aria-autocomplete="list" value="autocomplete=list">
   <input role="combobox"aria-autocomplete="both" value="autocomplete=both">
   <input role="combobox" aria-autocomplete="none" value="autocomplete=none">
+
+  <!-- Input elements of type text should map to an ARIA role of textbox. -->
+  <input type="text" aria-autocomplete="inline" value="No role with autocomplete=inline">
 </body>
 </html>
diff --git a/gin/object_template_builder.cc b/gin/object_template_builder.cc
index c905efee..53ff01ba 100644
--- a/gin/object_template_builder.cc
+++ b/gin/object_template_builder.cc
@@ -49,7 +49,7 @@
   return PerIsolateData::From(isolate)->GetIndexedPropertyInterceptor(base);
 }
 
-void NamedPropertyGetter(v8::Local<v8::String> property,
+void NamedPropertyGetter(v8::Local<v8::Name> property,
                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   v8::Isolate* isolate = info.GetIsolate();
   NamedPropertyInterceptor* interceptor =
@@ -61,7 +61,7 @@
   info.GetReturnValue().Set(interceptor->GetNamedProperty(isolate, name));
 }
 
-void NamedPropertySetter(v8::Local<v8::String> property,
+void NamedPropertySetter(v8::Local<v8::Name> property,
                          v8::Local<v8::Value> value,
                          const v8::PropertyCallbackInfo<v8::Value>& info) {
   v8::Isolate* isolate = info.GetIsolate();
@@ -75,7 +75,7 @@
     info.GetReturnValue().Set(value);
 }
 
-void NamedPropertyQuery(v8::Local<v8::String> property,
+void NamedPropertyQuery(v8::Local<v8::Name> property,
                         const v8::PropertyCallbackInfo<v8::Integer>& info) {
   v8::Isolate* isolate = info.GetIsolate();
   NamedPropertyInterceptor* interceptor =
@@ -151,11 +151,10 @@
 ObjectTemplateBuilder::~ObjectTemplateBuilder() = default;
 
 ObjectTemplateBuilder& ObjectTemplateBuilder::AddNamedPropertyInterceptor() {
-  template_->SetNamedPropertyHandler(&NamedPropertyGetter,
-                                     &NamedPropertySetter,
-                                     &NamedPropertyQuery,
-                                     NULL,
-                                     &NamedPropertyEnumerator);
+  template_->SetHandler(v8::NamedPropertyHandlerConfiguration(
+      &NamedPropertyGetter, &NamedPropertySetter, &NamedPropertyQuery, nullptr,
+      &NamedPropertyEnumerator, v8::Local<v8::Value>(),
+      v8::PropertyHandlerFlags::kOnlyInterceptStrings));
   return *this;
 }
 
diff --git a/ios/chrome/browser/signin/profile_oauth2_token_service_ios_provider_impl.mm b/ios/chrome/browser/signin/profile_oauth2_token_service_ios_provider_impl.mm
index bcef1cd2..11ebbda 100644
--- a/ios/chrome/browser/signin/profile_oauth2_token_service_ios_provider_impl.mm
+++ b/ios/chrome/browser/signin/profile_oauth2_token_service_ios_provider_impl.mm
@@ -25,7 +25,7 @@
   ProfileOAuth2TokenServiceIOSProvider::AccountInfo account_info;
   if (identity) {
     account_info.gaia = base::SysNSStringToUTF8([identity gaiaID]);
-    account_info.email = GetCanonicalizedEmailForIdentity(identity);
+    account_info.email = base::SysNSStringToUTF8([identity userEmail]);
   }
   return account_info;
 }
diff --git a/ios/chrome/browser/tabs/legacy_tab_helper.mm b/ios/chrome/browser/tabs/legacy_tab_helper.mm
index 6e0ffe17..bd13c3c2 100644
--- a/ios/chrome/browser/tabs/legacy_tab_helper.mm
+++ b/ios/chrome/browser/tabs/legacy_tab_helper.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/tabs/legacy_tab_helper.h"
 
 #import "ios/chrome/browser/tabs/tab.h"
-#import "ios/chrome/browser/tabs/tab_private.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/tabs/tab_model_closing_web_state_observer.mm b/ios/chrome/browser/tabs/tab_model_closing_web_state_observer.mm
index 25314326..6575ddf2 100644
--- a/ios/chrome/browser/tabs/tab_model_closing_web_state_observer.mm
+++ b/ios/chrome/browser/tabs/tab_model_closing_web_state_observer.mm
@@ -12,7 +12,6 @@
 #import "ios/chrome/browser/tabs/legacy_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
-#import "ios/chrome/browser/tabs/tab_private.h"
 #import "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 391b6876..04f67b3 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -1224,6 +1224,9 @@
   self.contentArea.autoresizingMask = initialViewAutoresizing;
   self.typingShield = [[UIButton alloc] initWithFrame:initialViewsRect];
   self.typingShield.autoresizingMask = initialViewAutoresizing;
+  self.typingShield.accessibilityIdentifier = @"Typing Shield";
+  self.typingShield.accessibilityLabel = l10n_util::GetNSString(IDS_CANCEL);
+
   [self.typingShield addTarget:self
                         action:@selector(shieldWasTapped:)
               forControlEvents:UIControlEventTouchUpInside];
@@ -2044,11 +2047,10 @@
 
   // Attach the typing shield to the content area but have it hidden.
   [_typingShield setFrame:[_contentArea frame]];
-  if (initialLayout)
+  if (initialLayout) {
     [[self view] insertSubview:_typingShield aboveSubview:_contentArea];
-  [_typingShield setHidden:YES];
-  _typingShield.accessibilityIdentifier = @"Typing Shield";
-  _typingShield.accessibilityLabel = l10n_util::GetNSString(IDS_CANCEL);
+    [_typingShield setHidden:YES];
+  }
 }
 
 - (void)displayTab:(Tab*)tab isNewSelection:(BOOL)newSelection {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
index f179e649..f461176 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -257,9 +257,11 @@
 
 - (void)viewWillAppear:(BOOL)animated {
   [super viewWillAppear:animated];
-  // Reload data to ensure the Most Visited tiles are correctly positionned, in
-  // particular during a rotation while a ViewController is presented in front
-  // of the NTP.
+  // Reload data to ensure the Most Visited tiles and fakeOmnibox are correctly
+  // positionned, in particular during a rotation while a ViewController is
+  // presented in front of the NTP.
+  [self.headerSynchronizer
+      updateFakeOmniboxOnNewWidth:self.collectionView.bounds.size.width];
   [self.collectionView.collectionViewLayout invalidateLayout];
 }
 
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
index 9ff52c3c..24547a08 100644
--- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -700,6 +700,12 @@
   clippingFrame.origin.y =
       [_webToolbar frame].size.height - clippingFrame.size.height;
   [_clippingView setFrame:clippingFrame];
+
+  // Omnibox background height also must be manually resized.
+  if ([_locationBarView.textField isFirstResponder]) {
+    CGRect omniboxFrame = CGRectInset([_clippingView bounds], -2, -2);
+    [_omniboxBackground setFrame:omniboxFrame];
+  }
 }
 
 - (void)setUpButton:(UIButton*)button
@@ -1189,6 +1195,14 @@
     [_webToolbar setAutoresizesSubviews:NO];
     CGRect expandedFrame =
         RectShiftedDownAndResizedForStatusBar(self.contentView.bounds);
+    // Using -RectShiftedDownAndResizedForStatusBar can sometimes be wrong in
+    // an autolayout world, such as if the view is rotated with the app
+    // backgrounded. It's safer to use -SafeAreaInsetsForView.
+    if (IsSafeAreaCompatibleToolbarEnabled()) {
+      UIEdgeInsets safeAreaInsets = SafeAreaInsetsForView(self.contentView);
+      expandedFrame =
+          UIEdgeInsetsInsetRect(self.contentView.bounds, safeAreaInsets);
+    }
     [_webToolbar
         setFrame:growOmnibox ? expandedFrame : [self specificControlsArea]];
     [_webToolbar setAutoresizesSubviews:YES];
@@ -2048,6 +2062,15 @@
 - (void)layoutCancelButton {
   CGFloat height = CGRectGetHeight([self specificControlsArea]) -
                    kCancelButtonTopMargin - kCancelButtonBottomMargin;
+  // Using -specificControlsArea can sometimes be wrong in
+  // an autolayout world, such as if the view is rotated with the app
+  // backgrounded. It's safer to use -SafeAreaInsetsForView.
+  if (IsSafeAreaCompatibleToolbarEnabled()) {
+    UIEdgeInsets safeAreaInsets = SafeAreaInsetsForView(self.contentView);
+    height = CGRectGetHeight(UIEdgeInsetsInsetRect(self.contentView.bounds,
+                                                   safeAreaInsets)) -
+             kCancelButtonTopMargin - kCancelButtonBottomMargin;
+  }
   LayoutRect cancelButtonLayout;
   cancelButtonLayout.position.leading =
       CGRectGetWidth([_webToolbar bounds]) - height;
diff --git a/ios/third_party/material_internationalization_ios/BUILD.gn b/ios/third_party/material_internationalization_ios/BUILD.gn
index 30058798..9e52ad5 100644
--- a/ios/third_party/material_internationalization_ios/BUILD.gn
+++ b/ios/third_party/material_internationalization_ios/BUILD.gn
@@ -45,14 +45,3 @@
     "//build/config/gcc:symbol_visibility_default",
   ]
 }
-
-# TODO(crbug.com/785248): remove those targets when downstream has been fixed
-# to no longer use it but instead depend on :material_internationalization_ios.
-group("material_internationalization_ios+link") {
-  public_deps = [
-    ":material_internationalization_ios",
-  ]
-}
-
-group("material_internationalization_ios:bundle") {
-}
diff --git a/net/BUILD.gn b/net/BUILD.gn
index cda37cb..8ff3e0b 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1833,8 +1833,6 @@
         "reporting/reporting_network_change_observer.h",
         "reporting/reporting_observer.cc",
         "reporting/reporting_observer.h",
-        "reporting/reporting_persister.cc",
-        "reporting/reporting_persister.h",
         "reporting/reporting_policy.cc",
         "reporting/reporting_policy.h",
         "reporting/reporting_report.cc",
@@ -5372,7 +5370,6 @@
       "reporting/reporting_garbage_collector_unittest.cc",
       "reporting/reporting_header_parser_unittest.cc",
       "reporting/reporting_network_change_observer_unittest.cc",
-      "reporting/reporting_persister_unittest.cc",
       "reporting/reporting_service_unittest.cc",
       "reporting/reporting_test_util.cc",
       "reporting/reporting_test_util.h",
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
index b5155ba3..2e01942 100644
--- a/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
+++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java
@@ -129,6 +129,15 @@
     }
 
     /**
+     * Returns {@code true} if NetworkCallback failed to register, indicating that network-specific
+     * callbacks will not be issued.
+     */
+    @CalledByNative
+    public boolean registerNetworkCallbackFailed() {
+        return mAutoDetector == null ? false : mAutoDetector.registerNetworkCallbackFailed();
+    }
+
+    /**
      * Returns the singleton instance.
      */
     public static NetworkChangeNotifier getInstance() {
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
index 42543c93..4666c9e 100644
--- a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
+++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
@@ -647,8 +647,9 @@
     private ConnectivityManagerDelegate mConnectivityManagerDelegate;
     private WifiManagerDelegate mWifiManagerDelegate;
     // mNetworkCallback and mNetworkRequest are only non-null in Android L and above.
-    private final MyNetworkCallback mNetworkCallback;
-    private final NetworkRequest mNetworkRequest;
+    // mNetworkCallback will be null if ConnectivityManager.registerNetworkCallback() ever fails.
+    private MyNetworkCallback mNetworkCallback;
+    private NetworkRequest mNetworkRequest;
     private boolean mRegistered;
     private NetworkState mNetworkState;
     // When a BroadcastReceiver is registered for a sticky broadcast that has been sent out at
@@ -665,6 +666,9 @@
     // been updated to the current device state, so no signals are necessary. This is simply an
     // optimization to avoid useless work.
     private boolean mShouldSignalObserver;
+    // Indicates if ConnectivityManager.registerNetworkRequest() ever failed. When true, no
+    // network-specific callbacks (e.g. Observer.onNetwork*() ) will be issued.
+    private boolean mRegisterNetworkCallbackFailed;
 
     /**
      * Observer interface by which observer is notified of network changes.
@@ -817,8 +821,19 @@
 
         if (mNetworkCallback != null) {
             mNetworkCallback.initializeVpnInPlace();
-            mConnectivityManagerDelegate.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
-            if (mShouldSignalObserver) {
+            try {
+                mConnectivityManagerDelegate.registerNetworkCallback(
+                        mNetworkRequest, mNetworkCallback);
+            } catch (IllegalArgumentException e) {
+                mRegisterNetworkCallbackFailed = true;
+                // If Android thinks this app has used up all available NetworkRequests, don't
+                // bother trying to register any more callbacks as Android will still think
+                // all available NetworkRequests are used up and fail again needlessly.
+                // Also don't bother unregistering as this call didn't actually register.
+                // See crbug.com/791025 for more info.
+                mNetworkCallback = null;
+            }
+            if (!mRegisterNetworkCallbackFailed && mShouldSignalObserver) {
                 // registerNetworkCallback() will rematch the NetworkRequest
                 // against active networks, so a cached list of active networks
                 // will be repopulated immediatly after this. However we need to
@@ -925,6 +940,14 @@
     }
 
     /**
+     * Returns {@code true} if NetworkCallback failed to register, indicating that network-specific
+     * callbacks will not be issued.
+     */
+    public boolean registerNetworkCallbackFailed() {
+        return mRegisterNetworkCallbackFailed;
+    }
+
+    /**
      * Returns the connection type for the given ConnectivityManager type and subtype.
      */
     @ConnectionType
diff --git a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierNoNativeTest.java b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierNoNativeTest.java
index 9ec284a..ad30b9d 100644
--- a/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierNoNativeTest.java
+++ b/net/android/javatests/src/org/chromium/net/NetworkChangeNotifierNoNativeTest.java
@@ -4,20 +4,36 @@
 
 package org.chromium.net;
 
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.os.Build;
 import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
 
+import org.junit.After;
+import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.MinAndroidSdkLevel;
 
 /**
  * Tests for org.chromium.net.NetworkChangeNotifier without native code. This class specifically
  * does not have a setUp() method that loads native libraries.
  */
 @RunWith(BaseJUnit4ClassRunner.class)
+@SuppressLint("NewApi")
 public class NetworkChangeNotifierNoNativeTest {
+    @After
+    public void tearDown() {
+        // Destroy NetworkChangeNotifierAutoDetect
+        NetworkChangeNotifier.setAutoDetectConnectivityState(false);
+    }
+
     /**
      * Verify NetworkChangeNotifier can initialize without calling into native code. This test
      * will crash if any native calls are made during NetworkChangeNotifier initialization.
@@ -29,4 +45,43 @@
         NetworkChangeNotifier.init();
         NetworkChangeNotifier.registerToReceiveNotificationsAlways();
     }
+
+    /**
+     * Verify NetworkChangeNotifier.registerNetworkCallbackFailed() and
+     * NetworkChangeNotifier.isProcessBoundToNetwork() return false under normal circumstances.
+     */
+    @Test
+    @MediumTest
+    public void testDefaultState() {
+        Looper.prepare();
+        NetworkChangeNotifier ncn = NetworkChangeNotifier.init();
+        Assert.assertFalse(ncn.registerNetworkCallbackFailed());
+        Assert.assertFalse(ncn.isProcessBoundToNetwork());
+        NetworkChangeNotifier.registerToReceiveNotificationsAlways();
+        Assert.assertFalse(ncn.registerNetworkCallbackFailed());
+        Assert.assertFalse(ncn.isProcessBoundToNetwork());
+    }
+
+    /**
+     * Verify NetworkChangeNotifier.registerNetworkCallbackFailed() catches exception properly.
+     */
+    @Test
+    @MediumTest
+    @MinAndroidSdkLevel(Build.VERSION_CODES.N)
+    public void testRegisterNetworkCallbackFail() {
+        ConnectivityManager connectivityManager =
+                (ConnectivityManager) InstrumentationRegistry.getTargetContext().getSystemService(
+                        Context.CONNECTIVITY_SERVICE);
+        Looper.prepare();
+        NetworkChangeNotifier ncn = NetworkChangeNotifier.init();
+        Assert.assertFalse(ncn.registerNetworkCallbackFailed());
+
+        // Use up all NetworkRequests
+        for (int i = 0; i < 99; i++) {
+            connectivityManager.registerDefaultNetworkCallback(new NetworkCallback());
+        }
+
+        NetworkChangeNotifier.registerToReceiveNotificationsAlways();
+        Assert.assertTrue(ncn.registerNetworkCallbackFailed());
+    }
 }
\ No newline at end of file
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc
index 44adae8..577e270 100644
--- a/net/android/network_change_notifier_android.cc
+++ b/net/android/network_change_notifier_android.cc
@@ -183,7 +183,8 @@
   return force_network_handles_supported_for_testing_ ||
          (base::android::BuildInfo::GetInstance()->sdk_int() >=
               base::android::SDK_VERSION_LOLLIPOP &&
-          !delegate_->IsProcessBoundToNetwork());
+          !delegate_->IsProcessBoundToNetwork() &&
+          !delegate_->RegisterNetworkCallbackFailed());
 }
 
 void NetworkChangeNotifierAndroid::GetCurrentConnectedNetworks(
diff --git a/net/android/network_change_notifier_delegate_android.cc b/net/android/network_change_notifier_delegate_android.cc
index 3df5cc4c..b4ce7ac 100644
--- a/net/android/network_change_notifier_delegate_android.cc
+++ b/net/android/network_change_notifier_delegate_android.cc
@@ -64,9 +64,14 @@
 }
 
 NetworkChangeNotifierDelegateAndroid::NetworkChangeNotifierDelegateAndroid()
-    : observers_(new base::ObserverListThreadSafe<Observer>()) {
+    : observers_(new base::ObserverListThreadSafe<Observer>()),
+      java_network_change_notifier_(Java_NetworkChangeNotifier_init(
+          base::android::AttachCurrentThread())),
+      register_network_callback_failed_(
+          Java_NetworkChangeNotifier_registerNetworkCallbackFailed(
+              base::android::AttachCurrentThread(),
+              java_network_change_notifier_)) {
   JNIEnv* env = base::android::AttachCurrentThread();
-  java_network_change_notifier_.Reset(Java_NetworkChangeNotifier_init(env));
   Java_NetworkChangeNotifier_addNativeObserver(
       env, java_network_change_notifier_, reinterpret_cast<intptr_t>(this));
   SetCurrentConnectionType(
diff --git a/net/android/network_change_notifier_delegate_android.h b/net/android/network_change_notifier_delegate_android.h
index b9db748..d102f63 100644
--- a/net/android/network_change_notifier_delegate_android.h
+++ b/net/android/network_change_notifier_delegate_android.h
@@ -46,6 +46,14 @@
                                        ConnectionType connection_type) = 0;
   };
 
+  // Initializes native (C++) side of NetworkChangeNotifierAndroid that
+  // communicates with Java NetworkChangeNotifier class. The Java
+  // NetworkChangeNotifier must have been previously initialized with calls
+  // like this:
+  //   // Creates global singleton Java NetworkChangeNotifier class instance.
+  //   NetworkChangeNotifier.init();
+  //   // Creates Java NetworkChangeNotifierAutoDetect class instance.
+  //   NetworkChangeNotifier.registerToReceiveNotificationsAlways();
   NetworkChangeNotifierDelegateAndroid();
   ~NetworkChangeNotifierDelegateAndroid();
 
@@ -116,6 +124,12 @@
   // Is the current process bound to a specific network?
   bool IsProcessBoundToNetwork();
 
+  // Returns true if NetworkCallback failed to register, indicating that
+  // network-specific callbacks will not be issued.
+  bool RegisterNetworkCallbackFailed() const {
+    return register_network_callback_failed_;
+  }
+
  private:
   friend class BaseNetworkChangeNotifierAndroidTest;
 
@@ -146,7 +160,11 @@
 
   base::ThreadChecker thread_checker_;
   scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_;
-  base::android::ScopedJavaGlobalRef<jobject> java_network_change_notifier_;
+  const base::android::ScopedJavaGlobalRef<jobject>
+      java_network_change_notifier_;
+  // True if NetworkCallback failed to register, indicating that
+  // network-specific callbacks will not be issued.
+  const bool register_network_callback_failed_;
 
   mutable base::Lock connection_lock_;  // Protects the state below.
   ConnectionType connection_type_;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 8b1a2a4..d90620f 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -929,7 +929,7 @@
   // that.
   if (CanUseExistingSpdySession()) {
     existing_spdy_session_ =
-        session_->spdy_session_pool()->push_promise_index()->Find(
+        session_->spdy_session_pool()->push_promise_index()->FindSession(
             spdy_session_key_, origin_url_);
     if (!existing_spdy_session_) {
       existing_spdy_session_ =
@@ -1206,7 +1206,7 @@
   // time Job checked above.
   if (!existing_spdy_session_) {
     existing_spdy_session_ =
-        session_->spdy_session_pool()->push_promise_index()->Find(
+        session_->spdy_session_pool()->push_promise_index()->FindSession(
             spdy_session_key_, origin_url_);
     // It is also possible that an HTTP/2 connection has been established since
     // last time Job checked above.
diff --git a/net/reporting/reporting_cache.cc b/net/reporting/reporting_cache.cc
index 822f14f..4c06ede 100644
--- a/net/reporting/reporting_cache.cc
+++ b/net/reporting/reporting_cache.cc
@@ -167,38 +167,6 @@
     context_->NotifyCacheUpdated();
   }
 
-  void GetClients(
-      std::vector<const ReportingClient*>* clients_out) const override {
-    clients_out->clear();
-    for (const auto& it : clients_)
-      for (const auto& endpoint_and_client : it.second)
-        clients_out->push_back(endpoint_and_client.second.get());
-  }
-
-  void GetClientsForOriginAndGroup(
-      const url::Origin& origin,
-      const std::string& group,
-      std::vector<const ReportingClient*>* clients_out) const override {
-    clients_out->clear();
-
-    const auto it = clients_.find(origin);
-    if (it != clients_.end()) {
-      for (const auto& endpoint_and_client : it->second) {
-        if (endpoint_and_client.second->group == group)
-          clients_out->push_back(endpoint_and_client.second.get());
-      }
-    }
-
-    // If no clients were found, try successive superdomain suffixes until a
-    // client with includeSubdomains is found or there are no more domain
-    // components left.
-    std::string domain = origin.host();
-    while (clients_out->empty() && !domain.empty()) {
-      GetWildcardClientsForDomainAndGroup(domain, group, clients_out);
-      domain = GetSuperdomain(domain);
-    }
-  }
-
   void SetClient(const url::Origin& origin,
                  const GURL& endpoint,
                  ReportingClient::Subdomains subdomains,
@@ -242,6 +210,51 @@
     client_last_used_[client] = tick_clock()->NowTicks();
   }
 
+  void GetClients(
+      std::vector<const ReportingClient*>* clients_out) const override {
+    clients_out->clear();
+    for (const auto& it : clients_)
+      for (const auto& endpoint_and_client : it.second)
+        clients_out->push_back(endpoint_and_client.second.get());
+  }
+
+  void GetClientsForOriginAndGroup(
+      const url::Origin& origin,
+      const std::string& group,
+      std::vector<const ReportingClient*>* clients_out) const override {
+    clients_out->clear();
+
+    const auto it = clients_.find(origin);
+    if (it != clients_.end()) {
+      for (const auto& endpoint_and_client : it->second) {
+        if (endpoint_and_client.second->group == group)
+          clients_out->push_back(endpoint_and_client.second.get());
+      }
+    }
+
+    // If no clients were found, try successive superdomain suffixes until a
+    // client with includeSubdomains is found or there are no more domain
+    // components left.
+    std::string domain = origin.host();
+    while (clients_out->empty() && !domain.empty()) {
+      GetWildcardClientsForDomainAndGroup(domain, group, clients_out);
+      domain = GetSuperdomain(domain);
+    }
+  }
+
+  // TODO(juliatuttle): Unittests.
+  void GetEndpointsForOrigin(const url::Origin& origin,
+                             std::vector<GURL>* endpoints_out) const override {
+    endpoints_out->clear();
+
+    const auto it = clients_.find(origin);
+    if (it == clients_.end())
+      return;
+
+    for (const auto& endpoint_and_client : it->second)
+      endpoints_out->push_back(endpoint_and_client.first);
+  }
+
   void RemoveClients(
       const std::vector<const ReportingClient*>& clients_to_remove) override {
     for (const ReportingClient* client : clients_to_remove)
@@ -295,36 +308,6 @@
   }
 
  private:
-  ReportingContext* context_;
-
-  // Owns all reports, keyed by const raw pointer for easier lookup.
-  std::unordered_map<const ReportingReport*, std::unique_ptr<ReportingReport>>
-      reports_;
-
-  // Reports that have been marked pending (in use elsewhere and should not be
-  // deleted until no longer pending).
-  std::unordered_set<const ReportingReport*> pending_reports_;
-
-  // Reports that have been marked doomed (would have been deleted, but were
-  // pending when the deletion was requested).
-  std::unordered_set<const ReportingReport*> doomed_reports_;
-
-  // Owns all clients, keyed by origin, then endpoint URL.
-  // (These would be unordered_map, but neither url::Origin nor GURL has a hash
-  // function implemented.)
-  std::map<url::Origin, std::map<GURL, std::unique_ptr<ReportingClient>>>
-      clients_;
-
-  // References but does not own all clients with includeSubdomains set, keyed
-  // by domain name.
-  std::unordered_map<std::string, std::unordered_set<const ReportingClient*>>
-      wildcard_clients_;
-
-  // The time that each client has last been used.
-  std::unordered_map<const ReportingClient*, base::TimeTicks> client_last_used_;
-
-  base::TickClock* tick_clock() { return context_->tick_clock(); }
-
   void RemoveReportInternal(const ReportingReport* report) {
     reports_[report]->RecordOutcome(tick_clock()->NowTicks());
     size_t erased = reports_.erase(report);
@@ -454,6 +437,36 @@
     else
       return earliest_used;
   }
+
+  base::TickClock* tick_clock() { return context_->tick_clock(); }
+
+  ReportingContext* context_;
+
+  // Owns all reports, keyed by const raw pointer for easier lookup.
+  std::unordered_map<const ReportingReport*, std::unique_ptr<ReportingReport>>
+      reports_;
+
+  // Reports that have been marked pending (in use elsewhere and should not be
+  // deleted until no longer pending).
+  std::unordered_set<const ReportingReport*> pending_reports_;
+
+  // Reports that have been marked doomed (would have been deleted, but were
+  // pending when the deletion was requested).
+  std::unordered_set<const ReportingReport*> doomed_reports_;
+
+  // Owns all clients, keyed by origin, then endpoint URL.
+  // (These would be unordered_map, but neither url::Origin nor GURL has a hash
+  // function implemented.)
+  std::map<url::Origin, std::map<GURL, std::unique_ptr<ReportingClient>>>
+      clients_;
+
+  // References but does not own all clients with includeSubdomains set, keyed
+  // by domain name.
+  std::unordered_map<std::string, std::unordered_set<const ReportingClient*>>
+      wildcard_clients_;
+
+  // The time that each client has last been used.
+  std::unordered_map<const ReportingClient*, base::TimeTicks> client_last_used_;
 };
 
 }  // namespace
diff --git a/net/reporting/reporting_cache.h b/net/reporting/reporting_cache.h
index 2cd4bb7..fbe11da 100644
--- a/net/reporting/reporting_cache.h
+++ b/net/reporting/reporting_cache.h
@@ -126,6 +126,13 @@
       const std::string& group,
       std::vector<const ReportingClient*>* clients_out) const = 0;
 
+  // Gets all of the endpoints in the cache configured for a particular origin.
+  // Does not pay attention to wildcard hosts; only returns endpoints configured
+  // by |origin| itself.
+  virtual void GetEndpointsForOrigin(
+      const url::Origin& origin,
+      std::vector<GURL>* endpoints_out) const = 0;
+
   // Removes a set of clients.
   //
   // May invalidate ReportingClient pointers returned by |GetClients| or
diff --git a/net/reporting/reporting_context.cc b/net/reporting/reporting_context.cc
index 8def197..6aa69733 100644
--- a/net/reporting/reporting_context.cc
+++ b/net/reporting/reporting_context.cc
@@ -20,7 +20,6 @@
 #include "net/reporting/reporting_garbage_collector.h"
 #include "net/reporting/reporting_network_change_observer.h"
 #include "net/reporting/reporting_observer.h"
-#include "net/reporting/reporting_persister.h"
 #include "net/reporting/reporting_policy.h"
 #include "net/reporting/reporting_uploader.h"
 
@@ -80,7 +79,6 @@
       cache_(ReportingCache::Create(this)),
       endpoint_manager_(ReportingEndpointManager::Create(this)),
       delivery_agent_(ReportingDeliveryAgent::Create(this)),
-      persister_(ReportingPersister::Create(this)),
       garbage_collector_(ReportingGarbageCollector::Create(this)),
       network_change_observer_(ReportingNetworkChangeObserver::Create(this)) {}
 
diff --git a/net/reporting/reporting_context.h b/net/reporting/reporting_context.h
index 139ca02..4f44334 100644
--- a/net/reporting/reporting_context.h
+++ b/net/reporting/reporting_context.h
@@ -27,7 +27,6 @@
 class ReportingGarbageCollector;
 class ReportingNetworkChangeObserver;
 class ReportingObserver;
-class ReportingPersister;
 class ReportingUploader;
 class URLRequestContext;
 
@@ -57,8 +56,6 @@
     return garbage_collector_.get();
   }
 
-  ReportingPersister* persister() { return persister_.get(); }
-
   void AddObserver(ReportingObserver* observer);
   void RemoveObserver(ReportingObserver* observer);
 
@@ -91,9 +88,6 @@
   // |cache_|, and |endpoint_manager_|.
   std::unique_ptr<ReportingDeliveryAgent> delivery_agent_;
 
-  // |persister_| must come after |clock_|, |tick_clock_|, and |cache_|.
-  std::unique_ptr<ReportingPersister> persister_;
-
   // |garbage_collector_| must come after |tick_clock_| and |cache_|.
   std::unique_ptr<ReportingGarbageCollector> garbage_collector_;
 
diff --git a/net/reporting/reporting_header_parser.cc b/net/reporting/reporting_header_parser.cc
index e5db601..9e1b7533 100644
--- a/net/reporting/reporting_header_parser.cc
+++ b/net/reporting/reporting_header_parser.cc
@@ -52,6 +52,12 @@
   MAX
 };
 
+bool EndpointParsedSuccessfully(HeaderEndpointOutcome outcome) {
+  return outcome == HeaderEndpointOutcome::REMOVED ||
+         outcome == HeaderEndpointOutcome::SET_REJECTED_BY_DELEGATE ||
+         outcome == HeaderEndpointOutcome::SET;
+}
+
 void RecordHeaderEndpointOutcome(HeaderEndpointOutcome outcome) {
   UMA_HISTOGRAM_ENUMERATION("Reporting.HeaderEndpointOutcome", outcome,
                             HeaderEndpointOutcome::MAX);
@@ -63,11 +69,21 @@
 const char kGroupDefaultValue[] = "default";
 const char kMaxAgeKey[] = "max-age";
 
+// Processes a single endpoint tuple received in a Report-To header.
+//
+// |origin| is the origin that sent the Report-To header.
+//
+// |value| is the parsed JSON value of the endpoint tuple.
+//
+// |*endpoint_out| will contain the endpoint URL parsed out of the tuple.
 HeaderEndpointOutcome ProcessEndpoint(ReportingDelegate* delegate,
                                       ReportingCache* cache,
                                       base::TimeTicks now,
-                                      const GURL& url,
-                                      const base::Value& value) {
+                                      const url::Origin& origin,
+                                      const base::Value& value,
+                                      GURL* endpoint_url_out) {
+  *endpoint_url_out = GURL();
+
   const base::DictionaryValue* dict = nullptr;
   if (!value.GetAsDictionary(&dict))
     return HeaderEndpointOutcome::DISCARDED_NOT_DICTIONARY;
@@ -105,13 +121,13 @@
     subdomains = ReportingClient::Subdomains::INCLUDE;
   }
 
+  *endpoint_url_out = endpoint_url;
+
   if (ttl_sec == 0) {
-    cache->RemoveClientForOriginAndEndpoint(url::Origin::Create(url),
-                                            endpoint_url);
+    cache->RemoveClientForOriginAndEndpoint(origin, endpoint_url);
     return HeaderEndpointOutcome::REMOVED;
   }
 
-  url::Origin origin = url::Origin::Create(url);
   if (!delegate->CanSetClient(origin, endpoint_url))
     return HeaderEndpointOutcome::SET_REJECTED_BY_DELEGATE;
 
@@ -150,19 +166,37 @@
     return;
   }
 
-  const base::ListValue* list = nullptr;
-  bool is_list = value->GetAsList(&list);
+  const base::ListValue* endpoint_list = nullptr;
+  bool is_list = value->GetAsList(&endpoint_list);
   DCHECK(is_list);
 
   ReportingDelegate* delegate = context->delegate();
   ReportingCache* cache = context->cache();
+
+  url::Origin origin = url::Origin::Create(url);
+
+  std::vector<GURL> old_endpoints;
+  cache->GetEndpointsForOrigin(origin, &old_endpoints);
+
+  std::set<GURL> new_endpoints;
+
   base::TimeTicks now = context->tick_clock()->NowTicks();
-  for (size_t i = 0; i < list->GetSize(); i++) {
+  for (size_t i = 0; i < endpoint_list->GetSize(); i++) {
     const base::Value* endpoint = nullptr;
-    bool got_endpoint = list->Get(i, &endpoint);
+    bool got_endpoint = endpoint_list->Get(i, &endpoint);
     DCHECK(got_endpoint);
-    RecordHeaderEndpointOutcome(
-        ProcessEndpoint(delegate, cache, now, url, *endpoint));
+    GURL endpoint_url;
+    HeaderEndpointOutcome outcome =
+        ProcessEndpoint(delegate, cache, now, origin, *endpoint, &endpoint_url);
+    if (EndpointParsedSuccessfully(outcome))
+      new_endpoints.insert(endpoint_url);
+    RecordHeaderEndpointOutcome(outcome);
+  }
+
+  // Remove any endpoints that weren't specified in the current header(s).
+  for (const GURL& old_endpoint : old_endpoints) {
+    if (new_endpoints.count(old_endpoint) == 0u)
+      cache->RemoveClientForOriginAndEndpoint(origin, old_endpoint);
   }
 }
 
diff --git a/net/reporting/reporting_header_parser_unittest.cc b/net/reporting/reporting_header_parser_unittest.cc
index 7d8710a..8fe3f4f 100644
--- a/net/reporting/reporting_header_parser_unittest.cc
+++ b/net/reporting/reporting_header_parser_unittest.cc
@@ -104,5 +104,22 @@
   EXPECT_EQ(nullptr, FindClientInCache(cache(), kOrigin_, kEndpoint_));
 }
 
+TEST_F(ReportingHeaderParserTest, RemoveOld) {
+  static const GURL kDifferentEndpoint_ = GURL("https://endpoint2/");
+
+  ReportingHeaderParser::ParseHeader(
+      context(), kUrl_,
+      "{\"url\":\"" + kEndpoint_.spec() + "\",\"max-age\":86400}");
+
+  EXPECT_TRUE(FindClientInCache(cache(), kOrigin_, kEndpoint_));
+
+  ReportingHeaderParser::ParseHeader(
+      context(), kUrl_,
+      "{\"url\":\"" + kDifferentEndpoint_.spec() + "\",\"max-age\":86400}");
+
+  EXPECT_FALSE(FindClientInCache(cache(), kOrigin_, kEndpoint_));
+  EXPECT_TRUE(FindClientInCache(cache(), kOrigin_, kDifferentEndpoint_));
+}
+
 }  // namespace
 }  // namespace net
diff --git a/net/reporting/reporting_persister.cc b/net/reporting/reporting_persister.cc
deleted file mode 100644
index c4f0e71..0000000
--- a/net/reporting/reporting_persister.cc
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/reporting/reporting_persister.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/strings/string_number_conversions.h"
-#include "base/time/clock.h"
-#include "base/time/tick_clock.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "base/values.h"
-#include "net/reporting/reporting_cache.h"
-#include "net/reporting/reporting_client.h"
-#include "net/reporting/reporting_context.h"
-#include "net/reporting/reporting_observer.h"
-#include "net/reporting/reporting_policy.h"
-#include "net/reporting/reporting_report.h"
-
-namespace net {
-namespace {
-
-std::unique_ptr<base::Value> SerializeOrigin(const url::Origin& origin) {
-  auto serialized = std::make_unique<base::DictionaryValue>();
-
-  serialized->SetString("scheme", origin.scheme());
-  serialized->SetString("host", origin.host());
-  serialized->SetInteger("port", origin.port());
-  serialized->SetString("suborigin", origin.suborigin());
-
-  return std::move(serialized);
-}
-
-bool DeserializeOrigin(const base::DictionaryValue& serialized,
-                       url::Origin* origin_out) {
-  std::string scheme;
-  if (!serialized.GetString("scheme", &scheme))
-    return false;
-
-  std::string host;
-  if (!serialized.GetString("host", &host))
-    return false;
-
-  int port_int;
-  if (!serialized.GetInteger("port", &port_int))
-    return false;
-  uint16_t port = static_cast<uint16_t>(port_int);
-  if (port_int != port)
-    return false;
-
-  std::string suborigin;
-  if (!serialized.GetString("suborigin", &suborigin))
-    return false;
-
-  *origin_out = url::Origin::CreateFromNormalizedTupleWithSuborigin(
-      scheme, host, port, suborigin);
-  return true;
-}
-
-class ReportingPersisterImpl : public ReportingPersister {
- public:
-  ReportingPersisterImpl(ReportingContext* context) : context_(context) {}
-
-  // ReportingPersister implementation:
-
-  ~ReportingPersisterImpl() override = default;
-
- private:
-  std::string SerializeTicks(base::TimeTicks time_ticks) {
-    base::Time time = time_ticks - tick_clock()->NowTicks() + clock()->Now();
-    return base::Int64ToString(time.ToInternalValue());
-  }
-
-  bool DeserializeTicks(const std::string& serialized,
-                        base::TimeTicks* time_ticks_out) {
-    int64_t internal;
-    if (!base::StringToInt64(serialized, &internal))
-      return false;
-
-    base::Time time = base::Time::FromInternalValue(internal);
-    *time_ticks_out = time - clock()->Now() + tick_clock()->NowTicks();
-    return true;
-  }
-
-  std::unique_ptr<base::Value> SerializeReport(const ReportingReport& report) {
-    auto serialized = std::make_unique<base::DictionaryValue>();
-
-    serialized->SetString("url", report.url.spec());
-    serialized->SetString("group", report.group);
-    serialized->SetString("type", report.type);
-    serialized->Set("body", report.body->CreateDeepCopy());
-    serialized->SetString("queued", SerializeTicks(report.queued));
-    serialized->SetInteger("attempts", report.attempts);
-
-    return std::move(serialized);
-  }
-
-  bool DeserializeReport(const base::DictionaryValue& report) {
-    std::string url_string;
-    if (!report.GetString("url", &url_string))
-      return false;
-    GURL url(url_string);
-    if (!url.is_valid())
-      return false;
-
-    std::string group;
-    if (!report.GetString("group", &group))
-      return false;
-
-    std::string type;
-    if (!report.GetString("type", &type))
-      return false;
-
-    const base::Value* body_original;
-    if (!report.Get("body", &body_original))
-      return false;
-    std::unique_ptr<base::Value> body = body_original->CreateDeepCopy();
-
-    std::string queued_string;
-    if (!report.GetString("queued", &queued_string))
-      return false;
-    base::TimeTicks queued;
-    if (!DeserializeTicks(queued_string, &queued))
-      return false;
-
-    int attempts;
-    if (!report.GetInteger("attempts", &attempts))
-      return false;
-    if (attempts < 0)
-      return false;
-
-    cache()->AddReport(url, group, type, std::move(body), queued, attempts);
-    return true;
-  }
-
-  std::unique_ptr<base::Value> SerializeReports() {
-    std::vector<const ReportingReport*> reports;
-    cache()->GetReports(&reports);
-
-    auto serialized = std::make_unique<base::ListValue>();
-    for (const ReportingReport* report : reports)
-      serialized->Append(SerializeReport(*report));
-
-    return std::move(serialized);
-  }
-
-  bool DeserializeReports(const base::ListValue& reports) {
-    for (size_t i = 0; i < reports.GetSize(); ++i) {
-      const base::DictionaryValue* report;
-      if (!reports.GetDictionary(i, &report))
-        return false;
-      if (!DeserializeReport(*report))
-        return false;
-    }
-
-    return true;
-  }
-
-  std::unique_ptr<base::Value> SerializeClient(const ReportingClient& client) {
-    auto serialized = std::make_unique<base::DictionaryValue>();
-
-    serialized->Set("origin", SerializeOrigin(client.origin));
-    serialized->SetString("endpoint", client.endpoint.spec());
-    serialized->SetBoolean(
-        "subdomains",
-        client.subdomains == ReportingClient::Subdomains::INCLUDE);
-    serialized->SetString("group", client.group);
-    serialized->SetString("expires", SerializeTicks(client.expires));
-
-    return std::move(serialized);
-  }
-
-  bool DeserializeClient(const base::DictionaryValue& client) {
-    const base::DictionaryValue* origin_value;
-    if (!client.GetDictionary("origin", &origin_value))
-      return false;
-    url::Origin origin;
-    if (!DeserializeOrigin(*origin_value, &origin))
-      return false;
-
-    std::string endpoint_string;
-    if (!client.GetString("endpoint", &endpoint_string))
-      return false;
-    GURL endpoint(endpoint_string);
-    if (!endpoint.is_valid())
-      return false;
-
-    bool subdomains_bool;
-    if (!client.GetBoolean("subdomains", &subdomains_bool))
-      return false;
-    ReportingClient::Subdomains subdomains =
-        subdomains_bool ? ReportingClient::Subdomains::INCLUDE
-                        : ReportingClient::Subdomains::EXCLUDE;
-
-    std::string group;
-    if (!client.GetString("group", &group))
-      return false;
-
-    std::string expires_string;
-    if (!client.GetString("expires", &expires_string))
-      return false;
-    base::TimeTicks expires;
-    if (!DeserializeTicks(expires_string, &expires))
-      return false;
-
-    cache()->SetClient(origin, endpoint, subdomains, group, expires);
-    return true;
-  }
-
-  std::unique_ptr<base::Value> SerializeClients() {
-    std::vector<const ReportingClient*> clients;
-    cache()->GetClients(&clients);
-
-    auto serialized = std::make_unique<base::ListValue>();
-    for (const ReportingClient* client : clients)
-      serialized->Append(SerializeClient(*client));
-
-    return std::move(serialized);
-  }
-
-  bool DeserializeClients(const base::ListValue& clients) {
-    for (size_t i = 0; i < clients.GetSize(); ++i) {
-      const base::DictionaryValue* client;
-      if (!clients.GetDictionary(i, &client))
-        return false;
-      if (!DeserializeClient(*client))
-        return false;
-    }
-
-    return true;
-  }
-
-  static const int kSupportedVersion = 1;
-
-  std::unique_ptr<base::Value> Serialize() {
-    auto serialized = std::make_unique<base::DictionaryValue>();
-
-    serialized->SetInteger("reporting_serialized_cache_version",
-                           kSupportedVersion);
-
-    bool persist_reports = policy().persist_reports_across_restarts;
-    serialized->SetBoolean("includes_reports", persist_reports);
-    if (persist_reports)
-      serialized->Set("reports", SerializeReports());
-
-    bool persist_clients = policy().persist_clients_across_restarts;
-    serialized->SetBoolean("includes_clients", persist_clients);
-    if (persist_clients)
-      serialized->Set("clients", SerializeClients());
-
-    return std::move(serialized);
-  }
-
-  bool Deserialize(const base::Value& serialized_value) {
-    std::vector<const ReportingReport*> reports;
-    cache()->GetReports(&reports);
-    DCHECK(reports.empty());
-
-    std::vector<const ReportingClient*> clients;
-    cache()->GetClients(&clients);
-    DCHECK(clients.empty());
-
-    int version;
-
-    const base::DictionaryValue* serialized;
-    if (!serialized_value.GetAsDictionary(&serialized))
-      return false;
-
-    if (!serialized->GetInteger("reporting_serialized_cache_version", &version))
-      return false;
-    if (version != kSupportedVersion)
-      return false;
-
-    bool includes_reports;
-    bool includes_clients;
-    if (!serialized->GetBoolean("includes_reports", &includes_reports) ||
-        !serialized->GetBoolean("includes_clients", &includes_clients)) {
-      return false;
-    }
-
-    if (includes_reports) {
-      const base::ListValue* reports;
-      if (!serialized->GetList("reports", &reports))
-        return false;
-      if (!DeserializeReports(*reports))
-        return false;
-    }
-
-    if (includes_clients) {
-      const base::ListValue* clients;
-      if (!serialized->GetList("clients", &clients))
-        return false;
-      if (!DeserializeClients(*clients))
-        return false;
-    }
-
-    return true;
-  }
-
-  const ReportingPolicy& policy() { return context_->policy(); }
-  base::Clock* clock() { return context_->clock(); }
-  base::TickClock* tick_clock() { return context_->tick_clock(); }
-  ReportingCache* cache() { return context_->cache(); }
-
-  ReportingContext* context_;
-};
-
-}  // namespace
-
-// static
-std::unique_ptr<ReportingPersister> ReportingPersister::Create(
-    ReportingContext* context) {
-  return std::make_unique<ReportingPersisterImpl>(context);
-}
-
-ReportingPersister::~ReportingPersister() = default;
-
-}  // namespace net
diff --git a/net/reporting/reporting_persister.h b/net/reporting/reporting_persister.h
deleted file mode 100644
index 40414f0..0000000
--- a/net/reporting/reporting_persister.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_REPORTING_REPORTING_PERSISTER_H_
-#define NET_REPORTING_REPORTING_PERSISTER_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-class ReportingContext;
-
-// Will persist the state of the Reporting system to (reasonably) stable
-// storage using an as-yet-unwritten persistence mechanism within //net.
-class NET_EXPORT ReportingPersister {
- public:
-  // Creates a ReportingPersister. |context| must outlive the persister.
-  static std::unique_ptr<ReportingPersister> Create(ReportingContext* context);
-
-  virtual ~ReportingPersister();
-};
-
-}  // namespace net
-
-#endif  // NET_REPORTING_REPORTING_PERSISTER_H_
diff --git a/net/reporting/reporting_persister_unittest.cc b/net/reporting/reporting_persister_unittest.cc
deleted file mode 100644
index 547c7208..0000000
--- a/net/reporting/reporting_persister_unittest.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/reporting/reporting_persister.h"
-
-#include "base/json/json_writer.h"
-#include "base/test/simple_test_clock.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/time/time.h"
-#include "base/timer/mock_timer.h"
-#include "base/values.h"
-#include "net/base/test_completion_callback.h"
-#include "net/reporting/reporting_cache.h"
-#include "net/reporting/reporting_client.h"
-#include "net/reporting/reporting_policy.h"
-#include "net/reporting/reporting_report.h"
-#include "net/reporting/reporting_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-namespace {
-
-class ReportingPersisterTest : public ReportingTestBase {
- protected:
-  const GURL kUrl_ = GURL("https://origin/path");
-  const url::Origin kOrigin_ = url::Origin::Create(kUrl_);
-  const GURL kEndpoint_ = GURL("https://endpoint/");
-  const std::string kGroup_ = "group";
-  const std::string kType_ = "default";
-};
-
-// Disabled because the Persister has no persistence layer to use yet.
-TEST_F(ReportingPersisterTest, DISABLED_Test) {
-  ReportingPolicy policy;
-  policy.persist_reports_across_restarts = true;
-  policy.persist_clients_across_restarts = true;
-  // Make sure reports don't expire on our simulated restart.
-  policy.max_report_age = base::TimeDelta::FromDays(30);
-  UsePolicy(policy);
-
-  static const int kAttempts = 3;
-
-  base::DictionaryValue body;
-  body.SetString("key", "value");
-
-  cache()->AddReport(kUrl_, kGroup_, kType_, body.CreateDeepCopy(),
-                     tick_clock()->NowTicks(), kAttempts);
-  cache()->SetClient(kOrigin_, kEndpoint_, ReportingClient::Subdomains::EXCLUDE,
-                     kGroup_,
-                     tick_clock()->NowTicks() + base::TimeDelta::FromDays(1));
-
-  // TODO: Actually save data, once it's possible.
-
-  SimulateRestart(/* delta= */ base::TimeDelta::FromHours(1),
-                  /* delta_ticks= */ base::TimeDelta::FromHours(-3));
-
-  // TODO: Actually load data, once it's possible.
-
-  std::vector<const ReportingReport*> reports;
-  cache()->GetReports(&reports);
-  ASSERT_EQ(1u, reports.size());
-  EXPECT_EQ(kUrl_, reports[0]->url);
-  EXPECT_EQ(kGroup_, reports[0]->group);
-  EXPECT_EQ(kType_, reports[0]->type);
-  EXPECT_EQ(body, *reports[0]->body);
-  EXPECT_EQ(tick_clock()->NowTicks() - base::TimeDelta::FromHours(1),
-            reports[0]->queued);
-  EXPECT_EQ(kAttempts, reports[0]->attempts);
-
-  const ReportingClient* client =
-      FindClientInCache(cache(), kOrigin_, kEndpoint_);
-  ASSERT_TRUE(client);
-  EXPECT_EQ(ReportingClient::Subdomains::EXCLUDE, client->subdomains);
-  EXPECT_EQ(kGroup_, client->group);
-  EXPECT_EQ(tick_clock()->NowTicks() + base::TimeDelta::FromDays(1) -
-                base::TimeDelta::FromHours(1),
-            client->expires);
-}
-
-// TODO(juliatuttle): Test asynchronous behavior.
-
-}  // namespace
-}  // namespace net
diff --git a/net/reporting/reporting_service.cc b/net/reporting/reporting_service.cc
index 935fd6d..91385b1 100644
--- a/net/reporting/reporting_service.cc
+++ b/net/reporting/reporting_service.cc
@@ -16,7 +16,6 @@
 #include "net/reporting/reporting_context.h"
 #include "net/reporting/reporting_delegate.h"
 #include "net/reporting/reporting_header_parser.h"
-#include "net/reporting/reporting_persister.h"
 #include "url/gurl.h"
 
 namespace net {
diff --git a/net/reporting/reporting_test_util.cc b/net/reporting/reporting_test_util.cc
index 8c98b8f..67e8c869 100644
--- a/net/reporting/reporting_test_util.cc
+++ b/net/reporting/reporting_test_util.cc
@@ -20,7 +20,6 @@
 #include "net/reporting/reporting_delegate.h"
 #include "net/reporting/reporting_delivery_agent.h"
 #include "net/reporting/reporting_garbage_collector.h"
-#include "net/reporting/reporting_persister.h"
 #include "net/reporting/reporting_policy.h"
 #include "net/reporting/reporting_uploader.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/net/reporting/reporting_test_util.h b/net/reporting/reporting_test_util.h
index 488284e..dfb1c4c6 100644
--- a/net/reporting/reporting_test_util.h
+++ b/net/reporting/reporting_test_util.h
@@ -123,8 +123,8 @@
   }
 
  private:
-  // Owned by the Persister and GarbageCollector, respectively, but referenced
-  // here to preserve type:
+  // Owned by the DeliveryAgent and GarbageCollector, respectively, but
+  // referenced here to preserve type:
 
   base::MockTimer* delivery_timer_;
   base::MockTimer* garbage_collection_timer_;
@@ -172,8 +172,6 @@
     return context_->garbage_collector();
   }
 
-  ReportingPersister* persister() { return context_->persister(); }
-
   base::TimeTicks yesterday();
   base::TimeTicks now();
   base::TimeTicks tomorrow();
diff --git a/net/spdy/chromium/http2_push_promise_index.cc b/net/spdy/chromium/http2_push_promise_index.cc
index bcd65e3d..3dfce23f 100644
--- a/net/spdy/chromium/http2_push_promise_index.cc
+++ b/net/spdy/chromium/http2_push_promise_index.cc
@@ -14,7 +14,7 @@
   DCHECK(unclaimed_pushed_streams_.empty());
 }
 
-base::WeakPtr<SpdySession> Http2PushPromiseIndex::Find(
+base::WeakPtr<SpdySession> Http2PushPromiseIndex::FindSession(
     const SpdySessionKey& key,
     const GURL& url) const {
   DCHECK(!url.is_empty());
diff --git a/net/spdy/chromium/http2_push_promise_index.h b/net/spdy/chromium/http2_push_promise_index.h
index cbc3441..9e4b8cb 100644
--- a/net/spdy/chromium/http2_push_promise_index.h
+++ b/net/spdy/chromium/http2_push_promise_index.h
@@ -57,8 +57,8 @@
   // Returns a session with |key| that has an unclaimed push stream for |url| if
   // such exists.  Makes no guarantee on which one it returns if there are
   // multiple.  Returns nullptr if no such session exists.
-  base::WeakPtr<SpdySession> Find(const SpdySessionKey& key,
-                                  const GURL& url) const;
+  base::WeakPtr<SpdySession> FindSession(const SpdySessionKey& key,
+                                         const GURL& url) const;
 
   // (Un)registers a Delegate with an unclaimed pushed stream for |url|.
   // Caller must make sure |delegate| stays valid by unregistering the exact
diff --git a/net/spdy/chromium/http2_push_promise_index_test.cc b/net/spdy/chromium/http2_push_promise_index_test.cc
index 2bc9c7e..5ae837c 100644
--- a/net/spdy/chromium/http2_push_promise_index_test.cc
+++ b/net/spdy/chromium/http2_push_promise_index_test.cc
@@ -44,8 +44,8 @@
 };
 
 TEST_F(Http2PushPromiseIndexTest, Empty) {
-  EXPECT_FALSE(index_.Find(key1_, url1_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_FALSE(index_.FindSession(key1_, url1_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 }
 
 TEST_F(Http2PushPromiseIndexTest, FindMultipleSessionsWithDifferentUrl) {
@@ -70,28 +70,28 @@
   // Read hanging socket data.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_FALSE(index_.Find(key1_, url1_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_FALSE(index_.FindSession(key1_, url1_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   index_.RegisterUnclaimedPushedStream(url1_, spdy_session1.get());
 
-  EXPECT_EQ(spdy_session1.get(), index_.Find(key1_, url1_).get());
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_EQ(spdy_session1.get(), index_.FindSession(key1_, url1_).get());
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   index_.RegisterUnclaimedPushedStream(url2_, spdy_session2.get());
 
-  EXPECT_EQ(spdy_session1.get(), index_.Find(key1_, url1_).get());
-  EXPECT_EQ(spdy_session2.get(), index_.Find(key2_, url2_).get());
+  EXPECT_EQ(spdy_session1.get(), index_.FindSession(key1_, url1_).get());
+  EXPECT_EQ(spdy_session2.get(), index_.FindSession(key2_, url2_).get());
 
   index_.UnregisterUnclaimedPushedStream(url1_, spdy_session1.get());
 
-  EXPECT_FALSE(index_.Find(key1_, url1_));
-  EXPECT_EQ(spdy_session2.get(), index_.Find(key2_, url2_).get());
+  EXPECT_FALSE(index_.FindSession(key1_, url1_));
+  EXPECT_EQ(spdy_session2.get(), index_.FindSession(key2_, url2_).get());
 
   index_.UnregisterUnclaimedPushedStream(url2_, spdy_session2.get());
 
-  EXPECT_FALSE(index_.Find(key1_, url1_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_FALSE(index_.FindSession(key1_, url1_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   // SpdySession weak pointers must still be valid,
   // otherwise comparisons above are not meaningful.
@@ -126,45 +126,45 @@
   // Read hanging socket data.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_FALSE(index_.Find(key1_, url1_));
-  EXPECT_FALSE(index_.Find(key2_, url1_));
-  EXPECT_FALSE(index_.Find(key1_, url2_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_FALSE(index_.FindSession(key1_, url1_));
+  EXPECT_FALSE(index_.FindSession(key2_, url1_));
+  EXPECT_FALSE(index_.FindSession(key1_, url2_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   index_.RegisterUnclaimedPushedStream(url1_, spdy_session1.get());
 
-  // Note that Find() only uses its SpdySessionKey argument to verify proxy and
-  // privacy mode.  Cross-origin pooling is supported, therefore HostPortPair of
-  // SpdySessionKey does not matter.
-  EXPECT_EQ(spdy_session1.get(), index_.Find(key1_, url1_).get());
-  EXPECT_EQ(spdy_session1.get(), index_.Find(key2_, url1_).get());
-  EXPECT_FALSE(index_.Find(key1_, url2_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  // Note that FindSession() only uses its SpdySessionKey argument to verify
+  // proxy and privacy mode.  Cross-origin pooling is supported, therefore
+  // HostPortPair of SpdySessionKey does not matter.
+  EXPECT_EQ(spdy_session1.get(), index_.FindSession(key1_, url1_).get());
+  EXPECT_EQ(spdy_session1.get(), index_.FindSession(key2_, url1_).get());
+  EXPECT_FALSE(index_.FindSession(key1_, url2_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   index_.RegisterUnclaimedPushedStream(url1_, spdy_session2.get());
 
-  // Find() makes no guarantee about which SpdySession it returns if there are
-  // multiple for the same URL.
-  SpdySession* result = index_.Find(key1_, url1_).get();
+  // FindSession() makes no guarantee about which SpdySession it returns if
+  // there are multiple for the same URL.
+  SpdySession* result = index_.FindSession(key1_, url1_).get();
   EXPECT_TRUE(result == spdy_session1.get() || result == spdy_session2.get());
-  result = index_.Find(key2_, url1_).get();
+  result = index_.FindSession(key2_, url1_).get();
   EXPECT_TRUE(result == spdy_session1.get() || result == spdy_session2.get());
-  EXPECT_FALSE(index_.Find(key1_, url2_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_FALSE(index_.FindSession(key1_, url2_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   index_.UnregisterUnclaimedPushedStream(url1_, spdy_session1.get());
 
-  EXPECT_EQ(spdy_session2.get(), index_.Find(key1_, url1_).get());
-  EXPECT_EQ(spdy_session2.get(), index_.Find(key2_, url1_).get());
-  EXPECT_FALSE(index_.Find(key1_, url2_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_EQ(spdy_session2.get(), index_.FindSession(key1_, url1_).get());
+  EXPECT_EQ(spdy_session2.get(), index_.FindSession(key2_, url1_).get());
+  EXPECT_FALSE(index_.FindSession(key1_, url2_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   index_.UnregisterUnclaimedPushedStream(url1_, spdy_session2.get());
 
-  EXPECT_FALSE(index_.Find(key1_, url1_));
-  EXPECT_FALSE(index_.Find(key2_, url1_));
-  EXPECT_FALSE(index_.Find(key1_, url2_));
-  EXPECT_FALSE(index_.Find(key2_, url2_));
+  EXPECT_FALSE(index_.FindSession(key1_, url1_));
+  EXPECT_FALSE(index_.FindSession(key2_, url1_));
+  EXPECT_FALSE(index_.FindSession(key1_, url2_));
+  EXPECT_FALSE(index_.FindSession(key2_, url2_));
 
   // SpdySession weak pointers must still be valid,
   // otherwise comparisons above are not meaningful.
diff --git a/net/spdy/chromium/spdy_network_transaction_unittest.cc b/net/spdy/chromium/spdy_network_transaction_unittest.cc
index 108151f..14541b6 100644
--- a/net/spdy/chromium/spdy_network_transaction_unittest.cc
+++ b/net/spdy/chromium/spdy_network_transaction_unittest.cc
@@ -4973,9 +4973,10 @@
       spdy_session_pool->FindAvailableSession(
           key, /* enable_ip_based_pooling = */ true, log_);
 
-  EXPECT_EQ(1u, spdy_session->unclaimed_pushed_streams_.size());
   EXPECT_EQ(1u,
-            spdy_session->unclaimed_pushed_streams_.count(GURL(url_to_push)));
+            spdy_session->unclaimed_pushed_streams_.CountStreamsForSession());
+  EXPECT_TRUE(
+      spdy_session->has_unclaimed_pushed_stream_for_url(GURL(url_to_push)));
 
   HttpNetworkTransaction trans1(DEFAULT_PRIORITY, helper.session());
   HttpRequestInfo push_request;
@@ -4986,7 +4987,8 @@
   rv = callback1.GetResult(rv);
   EXPECT_THAT(rv, IsOk());
 
-  EXPECT_TRUE(spdy_session->unclaimed_pushed_streams_.empty());
+  EXPECT_EQ(0u,
+            spdy_session->unclaimed_pushed_streams_.CountStreamsForSession());
 
   HttpResponseInfo response = *trans0->GetResponseInfo();
   EXPECT_TRUE(response.headers);
@@ -5113,7 +5115,8 @@
       spdy_session_pool->FindAvailableSession(
           key0, /* enable_ip_based_pooling = */ true, log_);
 
-  EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
+  EXPECT_EQ(0u,
+            spdy_session0->unclaimed_pushed_streams_.CountStreamsForSession());
 
   HostPortPair host_port_pair1("docs.example.org", 443);
   SpdySessionKey key1(host_port_pair1, ProxyServer::Direct(),
@@ -5122,9 +5125,10 @@
       spdy_session_pool->FindAvailableSession(
           key1, /* enable_ip_based_pooling = */ true, log_);
 
-  EXPECT_EQ(1u, spdy_session1->unclaimed_pushed_streams_.size());
   EXPECT_EQ(1u,
-            spdy_session1->unclaimed_pushed_streams_.count(GURL(url_to_push)));
+            spdy_session1->unclaimed_pushed_streams_.CountStreamsForSession());
+  EXPECT_TRUE(
+      spdy_session1->has_unclaimed_pushed_stream_for_url(GURL(url_to_push)));
 
   // Request |url_to_push|, which should be served from the pushed resource.
   HttpNetworkTransaction trans2(DEFAULT_PRIORITY, helper.session());
@@ -5136,8 +5140,10 @@
   rv = callback2.GetResult(rv);
   EXPECT_THAT(rv, IsOk());
 
-  EXPECT_TRUE(spdy_session0->unclaimed_pushed_streams_.empty());
-  EXPECT_TRUE(spdy_session1->unclaimed_pushed_streams_.empty());
+  EXPECT_EQ(0u,
+            spdy_session0->unclaimed_pushed_streams_.CountStreamsForSession());
+  EXPECT_EQ(0u,
+            spdy_session1->unclaimed_pushed_streams_.CountStreamsForSession());
 
   HttpResponseInfo response0 = *trans0->GetResponseInfo();
   EXPECT_TRUE(response0.headers);
diff --git a/net/spdy/chromium/spdy_session.cc b/net/spdy/chromium/spdy_session.cc
index f0eac8d..8eb9757 100644
--- a/net/spdy/chromium/spdy_session.cc
+++ b/net/spdy/chromium/spdy_session.cc
@@ -857,12 +857,10 @@
 }
 
 void SpdySession::CancelPush(const GURL& url) {
-  UnclaimedPushedStreamContainer::const_iterator unclaimed_it =
-      unclaimed_pushed_streams_.find(url);
-  if (unclaimed_it == unclaimed_pushed_streams_.end())
+  const SpdyStreamId stream_id = unclaimed_pushed_streams_.FindStream(url);
+  if (stream_id == kNoPushedStreamFound)
     return;
 
-  const SpdyStreamId stream_id = unclaimed_it->second;
   DCHECK(active_streams_.find(stream_id) != active_streams_.end());
   ResetStream(stream_id, ERROR_CODE_CANCEL, "Cancelled push stream.");
 }
@@ -1254,7 +1252,7 @@
   dict->SetInteger("active_streams", active_streams_.size());
 
   dict->SetInteger("unclaimed_pushed_streams",
-                   unclaimed_pushed_streams_.size());
+                   unclaimed_pushed_streams_.CountStreamsForSession());
 
   dict->SetString(
       "negotiated_protocol",
@@ -1290,12 +1288,11 @@
 }
 
 size_t SpdySession::num_unclaimed_pushed_streams() const {
-  return unclaimed_pushed_streams_.size();
+  return unclaimed_pushed_streams_.CountStreamsForSession();
 }
 
-size_t SpdySession::count_unclaimed_pushed_streams_for_url(
-    const GURL& url) const {
-  return unclaimed_pushed_streams_.count(url);
+bool SpdySession::has_unclaimed_pushed_stream_for_url(const GURL& url) const {
+  return unclaimed_pushed_streams_.FindStream(url) != kNoPushedStreamFound;
 }
 
 int SpdySession::GetPeerAddress(IPEndPoint* address) const {
@@ -1359,15 +1356,14 @@
 }
 
 void SpdySession::OnPushedStreamClaimed(const GURL& url) {
-  UnclaimedPushedStreamContainer::const_iterator unclaimed_it =
-      unclaimed_pushed_streams_.find(url);
+  SpdyStreamId stream_id = unclaimed_pushed_streams_.FindStream(url);
   // This is only possible in tests.
   // TODO(bnc): Change to DCHECK once Http2PushPromiseIndexTest stops using
   // actual SpdySession instances.  https://crbug.com/791055.
-  if (unclaimed_it == unclaimed_pushed_streams_.end())
+  if (stream_id == kNoPushedStreamFound)
     return;
 
-  LogPushStreamClaimed(url, unclaimed_it->second);
+  LogPushStreamClaimed(url, stream_id);
 }
 
 base::WeakPtr<SpdySession> SpdySession::GetWeakPtrToSession() {
@@ -1404,25 +1400,29 @@
 SpdySession::UnclaimedPushedStreamContainer::~UnclaimedPushedStreamContainer() =
     default;
 
-bool SpdySession::UnclaimedPushedStreamContainer::erase(const GURL& url) {
-  const_iterator it = find(url);
-  if (it == end())
-    return false;
-
-  erase(it);
-  return true;
+SpdyStreamId SpdySession::UnclaimedPushedStreamContainer::FindStream(
+    const GURL& url) const {
+  PushedStreamMap::const_iterator it = streams_.find(url);
+  if (it == streams_.end())
+    return kNoPushedStreamFound;
+  return it->second;
 }
 
-SpdySession::UnclaimedPushedStreamContainer::iterator
-SpdySession::UnclaimedPushedStreamContainer::erase(const_iterator it) {
+bool SpdySession::UnclaimedPushedStreamContainer::erase(
+    const GURL& url,
+    SpdyStreamId stream_id) {
   DCHECK(spdy_session_->pool_);
-  DCHECK(it != end());
+  PushedStreamMap::const_iterator it = streams_.find(url);
+  if (it == streams_.end() || it->second != stream_id)
+    return false;
+
   // Only allow cross-origin push for secure resources.
   if (it->first.SchemeIsCryptographic()) {
     spdy_session_->pool_->push_promise_index()->UnregisterUnclaimedPushedStream(
         it->first, spdy_session_);
   }
-  return streams_.erase(it);
+  streams_.erase(it);
+  return true;
 }
 
 bool SpdySession::UnclaimedPushedStreamContainer::insert(
@@ -1764,7 +1764,8 @@
   // push is hardly used. Write tests for this and fix this. (See
   // http://crbug.com/261712 .)
   if (owned_stream->type() == SPDY_PUSH_STREAM) {
-    if (unclaimed_pushed_streams_.erase(owned_stream->url())) {
+    if (unclaimed_pushed_streams_.erase(owned_stream->url(),
+                                        owned_stream->stream_id())) {
       bytes_pushed_and_unclaimed_count_ += owned_stream->recv_bytes();
     }
     bytes_pushed_count_ += owned_stream->recv_bytes();
@@ -2440,13 +2441,12 @@
 }
 
 SpdyStream* SpdySession::GetActivePushStream(const GURL& url) {
-  UnclaimedPushedStreamContainer::const_iterator unclaimed_it =
-      unclaimed_pushed_streams_.find(url);
-  if (unclaimed_it == unclaimed_pushed_streams_.end())
+  const SpdyStreamId stream_id = unclaimed_pushed_streams_.FindStream(url);
+  if (stream_id == kNoPushedStreamFound)
     return nullptr;
 
-  const SpdyStreamId stream_id = unclaimed_it->second;
-  unclaimed_pushed_streams_.erase(unclaimed_it);
+  const bool result = unclaimed_pushed_streams_.erase(url, stream_id);
+  DCHECK(result);
 
   ActiveStreamMap::iterator active_it = active_streams_.find(stream_id);
   if (active_it == active_streams_.end()) {
@@ -2513,7 +2513,7 @@
   DcheckGoingAway();
   DCHECK_EQ(availability_state_, STATE_DRAINING);
   DCHECK(active_streams_.empty());
-  DCHECK(unclaimed_pushed_streams_.empty());
+  DCHECK_EQ(0u, unclaimed_pushed_streams_.CountStreamsForSession());
 }
 
 void SpdySession::DoDrainSession(Error err, const SpdyString& description) {
@@ -2615,13 +2615,10 @@
 
   // Grab URL for faster lookup in unclaimed_pushed_streams_.
   const GURL& url = active_it->second->url();
-  UnclaimedPushedStreamContainer::const_iterator unclaimed_it =
-      unclaimed_pushed_streams_.find(url);
   // Make sure to cancel the correct stream.  It is possible that the pushed
   // stream |stream_id| is already claimed, and another stream has been pushed
   // for the same URL.
-  if (unclaimed_it == unclaimed_pushed_streams_.end() ||
-      unclaimed_it->second != stream_id) {
+  if (unclaimed_pushed_streams_.FindStream(url) != stream_id) {
     return;
   }
 
@@ -2740,8 +2737,9 @@
   net_log_.AddEvent(
       NetLogEventType::HTTP2_SESSION_RECV_GOAWAY,
       base::Bind(&NetLogSpdyRecvGoAwayCallback, last_accepted_stream_id,
-                 active_streams_.size(), unclaimed_pushed_streams_.size(),
-                 error_code, debug_data));
+                 active_streams_.size(),
+                 unclaimed_pushed_streams_.CountStreamsForSession(), error_code,
+                 debug_data));
   MakeUnavailable();
   if (error_code == ERROR_CODE_HTTP_1_1_REQUIRED) {
     // TODO(bnc): Record histogram with number of open streams capped at 50.
diff --git a/net/spdy/chromium/spdy_session.h b/net/spdy/chromium/spdy_session.h
index 0e173b4..5f39b6d 100644
--- a/net/spdy/chromium/spdy_session.h
+++ b/net/spdy/chromium/spdy_session.h
@@ -58,6 +58,11 @@
 class SpdyStreamTest;
 }
 
+// This value means that UnclaimedPushedStreamContainer::FindStream() has not
+// found any streams.
+// TODO(bnc): Move to Http2PushPromiseIndex.  https://crbug.com/791054
+const SpdyStreamId kNoPushedStreamFound = 0;
+
 // This is somewhat arbitrary and not really fixed, but it will always work
 // reasonably with ethernet. Chop the world into 2-packet chunks.  This is
 // somewhat arbitrary, but is reasonably small and ensures that we elicit
@@ -452,7 +457,7 @@
   size_t num_active_streams() const { return active_streams_.size(); }
   size_t num_unclaimed_pushed_streams() const;
   size_t num_created_streams() const { return created_streams_.size(); }
-  size_t count_unclaimed_pushed_streams_for_url(const GURL& url) const;
+  bool has_unclaimed_pushed_stream_for_url(const GURL& url) const;
 
   size_t num_pushed_streams() const { return num_pushed_streams_; }
   size_t num_active_pushed_streams() const {
@@ -598,29 +603,15 @@
   // an unclaimed pushed stream is claimed.
   class UnclaimedPushedStreamContainer {
    public:
-    using PushedStreamMap = std::map<GURL, SpdyStreamId>;
-    using iterator = PushedStreamMap::iterator;
-    using const_iterator = PushedStreamMap::const_iterator;
-
     UnclaimedPushedStreamContainer() = delete;
     explicit UnclaimedPushedStreamContainer(SpdySession* spdy_session);
     ~UnclaimedPushedStreamContainer();
 
-    bool empty() const { return streams_.empty(); }
-    size_t size() const { return streams_.size(); }
-    const_iterator begin() const { return streams_.begin(); }
-    const_iterator end() const { return streams_.end(); }
-    const_iterator find(const GURL& url) const { return streams_.find(url); }
-    size_t count(const GURL& url) const { return streams_.count(url); }
-    const_iterator lower_bound(const GURL& url) const {
-      return streams_.lower_bound(url);
-    }
+    size_t CountStreamsForSession() const { return streams_.size(); }
+    SpdyStreamId FindStream(const GURL& url) const;
 
     // Return true if there was an element with |url|, which was then erased.
-    bool erase(const GURL& url);
-
-    // Return the iterator following |it|.
-    iterator erase(const_iterator it);
+    bool erase(const GURL& url, SpdyStreamId stream_id) WARN_UNUSED_RESULT;
 
     // Return true if there was not already an entry with |url|,
     // in which case the insertion was successful.
@@ -629,6 +620,8 @@
     size_t EstimateMemoryUsage() const;
 
    private:
+    using PushedStreamMap = std::map<GURL, SpdyStreamId>;
+
     SpdySession* spdy_session_;
 
     // (Bijective) map from the URL to the ID of the streams that have
diff --git a/net/spdy/chromium/spdy_session_unittest.cc b/net/spdy/chromium/spdy_session_unittest.cc
index f45ebc6..5e8020b 100644
--- a/net/spdy/chromium/spdy_session_unittest.cc
+++ b/net/spdy/chromium/spdy_session_unittest.cc
@@ -1322,8 +1322,8 @@
 
   // Verify that there is one unclaimed push stream.
   EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
-  EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(
-                    GURL("https://www.example.org/a.dat")));
+  EXPECT_TRUE(session_->has_unclaimed_pushed_stream_for_url(
+      GURL("https://www.example.org/a.dat")));
 
   // Unclaimed push body consumes bytes from the session window.
   EXPECT_EQ(kDefaultInitialWindowSize - kUploadDataSize,
@@ -1423,7 +1423,7 @@
   // Verify that there is one unclaimed push stream.
   const GURL pushed_url("https://www.example.org/a.dat");
   EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
-  EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(pushed_url));
+  EXPECT_TRUE(session_->has_unclaimed_pushed_stream_for_url(pushed_url));
 
   // Unclaimed push body consumes bytes from the session window.
   EXPECT_EQ(kDefaultInitialWindowSize - kUploadDataSize,
@@ -1531,7 +1531,7 @@
   // Verify that there is one unclaimed push stream.
   const GURL pushed_url("https://www.example.org/a.dat");
   EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
-  EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(pushed_url));
+  EXPECT_TRUE(session_->has_unclaimed_pushed_stream_for_url(pushed_url));
 
   // Unclaimed push body consumes bytes from the session window.
   EXPECT_EQ(kDefaultInitialWindowSize - kUploadDataSize,
@@ -1608,7 +1608,7 @@
   // Verify that there is one unclaimed push stream.
   const GURL pushed_url("https://www.example.org/a.dat");
   EXPECT_EQ(1u, session_->num_unclaimed_pushed_streams());
-  EXPECT_EQ(1u, session_->count_unclaimed_pushed_streams_for_url(pushed_url));
+  EXPECT_TRUE(session_->has_unclaimed_pushed_stream_for_url(pushed_url));
 
   // Unclaimed push body consumes bytes from the session window.
   EXPECT_EQ(kDefaultInitialWindowSize - kUploadDataSize,
@@ -1618,7 +1618,7 @@
   // Cancel the push before it is claimed.
   EXPECT_TRUE(test_push_delegate_->CancelPush(pushed_url));
   EXPECT_EQ(0u, session_->num_unclaimed_pushed_streams());
-  EXPECT_EQ(0u, session_->count_unclaimed_pushed_streams_for_url(pushed_url));
+  EXPECT_FALSE(session_->has_unclaimed_pushed_stream_for_url(pushed_url));
 
   // Verify that the session window reclaimed the evicted stream body.
   EXPECT_EQ(kDefaultInitialWindowSize, session_->session_recv_window_size_);
diff --git a/testing/buildbot/filters/mus.content_browsertests.filter b/testing/buildbot/filters/mus.content_browsertests.filter
index b5300b3..fe114d1fb 100644
--- a/testing/buildbot/filters/mus.content_browsertests.filter
+++ b/testing/buildbot/filters/mus.content_browsertests.filter
@@ -108,6 +108,7 @@
 -SnapshotBrowserTest.AsyncMultiWindowTest
 -SnapshotBrowserTest.SingleWindowTest
 -SnapshotBrowserTest.SyncMultiWindowTest
+-WebContentsViewAuraTest.ReplaceStateReloadPushState
 -WebRtcCaptureFromElementBrowserTest.CaptureFromCanvas2DHandlesContextLoss
 -WebRtcCaptureFromElementBrowserTest.CaptureFromOpaqueCanvas2DHandlesContextLoss
 
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
index edd992d..92cade2 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-features=NetworkService
@@ -122,6 +122,7 @@
 crbug.com/721408 http/tests/inspector-protocol/network/request-interception-resource-types.js [ Failure ]
 crbug.com/721408 http/tests/inspector-protocol/network/request-response-interception-disable-between.js [ Failure Timeout ]
 crbug.com/721408 http/tests/inspector-protocol/network/response-interception-cancel-xhr-while-responding-error.js [ Failure Timeout ]
+crbug.com/721408 http/tests/inspector-protocol/network/response-interception-main-resource-cross-origin.js [ Failure Timeout ]
 crbug.com/721408 http/tests/inspector-protocol/network/response-interception-no-change-content-not-ready.js [ Failure Timeout ]
 crbug.com/721408 http/tests/inspector-protocol/network/response-interception-request-completes-network-closes.js [ Failure Timeout ]
 crbug.com/721408 http/tests/inspector-protocol/network/response-interception-with-data-url.js [ Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 8b35a4d..02fd350 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2384,8 +2384,6 @@
 # css-multicol tests failing on initial import from web-platform-tests
 crbug.com/788337 external/wpt/css/css-multicol/multicol-block-no-clip-001.xht [ Failure ]
 crbug.com/788337 external/wpt/css/css-multicol/multicol-block-no-clip-002.xht [ Failure ]
-crbug.com/788337 external/wpt/css/css-multicol/multicol-count-computed-001.xht [ Failure ]
-crbug.com/788337 external/wpt/css/css-multicol/multicol-count-computed-002.xht [ Failure ]
 crbug.com/788337 external/wpt/css/css-multicol/multicol-count-computed-003.xht [ Failure ]
 crbug.com/788337 external/wpt/css/css-multicol/multicol-count-computed-005.xht [ Failure ]
 crbug.com/788337 external/wpt/css/css-multicol/multicol-count-large-001.xht [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/cookies/meta-blocked.html b/third_party/WebKit/LayoutTests/external/wpt/cookies/meta-blocked.html
new file mode 100644
index 0000000..1b86e65c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/cookies/meta-blocked.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<head>
+  <meta http-equiv="set-cookie" content="meta-set-cookie=1">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+  <script>
+    test(t => {
+      assert_equals(document.cookie.indexOf('meta-set-cookie'), -1);
+    }, "Cookie is not set from `<meta>`.");
+  </script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-001.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-001.xht
deleted file mode 100644
index 3c9ea3a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-001.xht
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-gaps-and-rules"/>
-<link rel="match" href="multicol-count-computed-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body {
-	margin: 0;
-}
-div {
-	font-family: ahem;
-	font-size: 1em;
-	line-height: 1em;
-	color: black;
-	background: yellow;
-	margin: 1em;
-	border: 1em solid gray;
-	width: 12em;
-	widows: 1;
-	orphans: 1;
-
-	column-count: 3;
-	column-gap: 6em;
-	column-rule-color: blue;
-	column-rule-width: 1.5em;
-	column-rule-style: solid;
-}
-#pink {color: pink;}
-#orange {color: orange;}
-#purple {color: purple;}
-#grey {color: grey;}
-]]></style>
-</head>
-
-<body>
-
-<div>
-	<span id="pink">xxxx</span>
-	<span id="orange">xxxx</span>
-	<span id="purple">xxxx</span>
-	<span id="grey">xxxx</span>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-002.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-002.xht
deleted file mode 100644
index 7bd1b3e..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-002.xht
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-gaps-and-rules"/>
-<link rel="match" href="multicol-count-computed-2-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body {
-	margin: 0;
-}
-div {
-	font-family: ahem;
-	font-size: 1em;
-	line-height: 1em;
-	color: black;
-	background: yellow;
-	margin: 1em;
-	border: 1em solid gray;
-	width: 12em;
-	widows: 1;
-	orphans: 1;
-
-	column-count: 3;
-	column-gap: 7em;
-	column-rule-color: red;
-	column-rule-width: 1.5em;
-	column-rule-style: solid;
-}
-#pink {color: pink;}
-#orange {color: orange;}
-#purple {color: purple;}
-#grey {color: grey;}
-]]></style>
-</head>
-
-<body>
-
-<div>
-	<span id="pink">xxxx</span>
-	<span id="orange">xxxx</span>
-	<span id="purple">xxxx</span>
-	<span id="grey">xxxx</span>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-2-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-2-ref.xht
deleted file mode 100644
index 15d365cf..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-2-ref.xht
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body {
-	margin: 0;
-}
-div {
-	font-family: ahem;
-	font-size: 1em;
-	line-height: 1em;
-	color: black;
-	background: yellow;
-	margin: 1em;
-	border: 1em solid gray;
-	width: 12em;
-	height: 2em;
-	position: relative;
-	widows: 1;
-	orphans: 1;
-}
-#pink {color: pink;}
-#orange {color: orange;}
-#purple {color: purple;}
-#grey {color: grey;}
-span {
-	display: block;
-	position: absolute;
-}
-#orange {
-	left: 5em;
-	top: 0;
-}
-#purple {
-	left: 0;
-	top: 1em;
-}
-#grey {
-	left: 5em;
-	top: 1em;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
-	<span id="purple">xxxx</span>
-	<span id="orange">xxxx</span>
-	<span id="grey">xxxx</span>
-	<span id="pink">xxxx</span>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-ref.xht b/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-ref.xht
deleted file mode 100644
index ac6d8c1..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-multicol/multicol-count-computed-ref.xht
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body {
-	margin: 0;
-}
-div {
-	font-family: ahem;
-	font-size: 1em;
-	line-height: 1em;
-	color: black;
-	background: yellow;
-	margin: 1em;
-	border: 1em solid gray;
-	width: 12em;
-	height: 2em;
-	position: relative;
-	widows: 1;
-	orphans: 1;
-
-}
-span {
-	display: block;
-	position: absolute;
-}
-#pink {
-	color: pink;
-}
-#orange {
-	color: orange;
-	left: 0;
-	top: 1em;
-}
-#purple {
-	color: purple;
-	left: 9em;
-	top: 0;
-}
-#grey {
-	color: grey;
-	left: 9em;
-	top: 1em;
-}
-#blue {
-	left: 5.25em;
-	top: 0;
-	width: 1.5em;
-	height: 2em;
-	background: blue;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
-	<span id="pink">xxxx</span>
-	<span id="orange">xxxx</span>
-	<span id="purple">xxxx</span>
-	<span id="grey">xxxx</span>
-	<span id="blue"></span>
-</div>
-
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https-expected.txt
index 02cf2a8..71bbea7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-FAIL A disabled video track is rendered as blackness Uncaught SyntaxError: Unexpected token )
+FAIL Tests that a disabled video track in a MediaStream is rendered as blackness assert_equals: No red component in pixel #0 expected 0 but got 255
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
index 8aee8e2..9f44a341 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
@@ -46,7 +46,7 @@
       vid.srcObject = stream;
       vid.play();
       vid.addEventListener("loadeddata", testOnceLoadeddata, false);
-    })));
+    }));
 });
 </script>
 </body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/cookies/meta-expected.txt b/third_party/WebKit/LayoutTests/http/tests/cookies/meta-expected.txt
index 28183d17..333ee8e 100644
--- a/third_party/WebKit/LayoutTests/http/tests/cookies/meta-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/cookies/meta-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE WARNING: Setting cookies via `<meta http-equiv='Set-Cookie' ...>` is deprecated, and will stop working in M65, around March 2018. Consider switching to `document.cookie = ...`, or to `Set-Cookie` HTTP headers instead. See https://www.chromestatus.com/feature/6170540112871424 for more details.
+CONSOLE WARNING: Setting cookies via `<meta http-equiv='Set-Cookie' ...>` no longer works, as of M65. Consider switching to  `document.cookie = ...`, or to `Set-Cookie` HTTP headers instead. See https://www.chromestatus.com/feature/6170540112871424 for more details.
 CONSOLE ERROR: line 3: Blocked setting the `meta-set-cookie=1` cookie from a `<meta>` tag.
 This is a testharness.js-based test.
 PASS Cookie is not set from `<meta>`.
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp
index db80f4a..ec6bd80 100644
--- a/third_party/WebKit/Source/core/frame/Deprecation.cpp
+++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -296,11 +296,10 @@
     case WebFeature::kMetaSetCookie:
       return {"MetaSetCookie", M65,
               String::Format(
-                  "Setting cookies via `<meta http-equiv='Set-Cookie' ...>` is "
-                  "deprecated, and will stop working in %s. Consider switching "
-                  "to `document.cookie = ...`, or to `Set-Cookie` HTTP headers "
+                  "Setting cookies via `<meta http-equiv='Set-Cookie' ...>` no "
+                  "longer works, as of M65. Consider switching to "
+                  " `document.cookie = ...`, or to `Set-Cookie` HTTP headers "
                   "instead. See %s for more details.",
-                  milestoneString(M65),
                   "https://www.chromestatus.com/feature/6170540112871424")};
 
     // Powerful features on insecure origins (https://goo.gl/rStTGz)
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
index a99c5b3..22ec69fd 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -1156,7 +1156,7 @@
 
 // TODO: rename this just AutoComplete, it's not only ARIA.
 String AXNodeObject::AriaAutoComplete() const {
-  if (IsARIATextControl()) {
+  if (IsNativeTextControl() || IsARIATextControl()) {
     const AtomicString& aria_auto_complete =
         GetAOMPropertyOrARIAAttribute(AOMStringProperty::kAutocomplete)
             .DeprecatedLower();
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
index a876a6f..98e550b 100644
--- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5
+++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -134,7 +134,7 @@
     },
     {
       name: "BlockMetaSetCookie",
-      status: "experimental"
+      status: "stable"
     },
     {
       name: "Budget",
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc
index d0c5630dd..8b41780 100644
--- a/ui/ozone/public/ozone_platform.cc
+++ b/ui/ozone/public/ozone_platform.cc
@@ -4,6 +4,7 @@
 
 #include "ui/ozone/public/ozone_platform.h"
 
+#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/events/devices/device_data_manager.h"
@@ -16,10 +17,18 @@
 
 bool g_platform_initialized_ui = false;
 bool g_platform_initialized_gpu = false;
+base::LazyInstance<base::OnceCallback<void(OzonePlatform*)>>::Leaky
+    instance_callback = LAZY_INSTANCE_INITIALIZER;
+
+base::Lock& GetOzoneInstanceLock() {
+  static base::Lock lock;
+  return lock;
+}
 
 }  // namespace
 
 OzonePlatform::OzonePlatform() {
+  GetOzoneInstanceLock().AssertAcquired();
   DCHECK(!instance_) << "There should only be a single OzonePlatform.";
   instance_ = this;
   g_platform_initialized_ui = false;
@@ -38,6 +47,8 @@
   // This is deliberately created after initializing so that the platform can
   // create its own version of DDM.
   DeviceDataManager::CreateInstance();
+  if (!instance_callback.Get().is_null())
+    std::move(instance_callback.Get()).Run(instance_);
 }
 
 // static
@@ -47,10 +58,13 @@
     return;
   g_platform_initialized_gpu = true;
   instance_->InitializeGPU(args);
+  if (!args.single_process && !instance_callback.Get().is_null())
+    std::move(instance_callback.Get()).Run(instance_);
 }
 
 // static
 void OzonePlatform::Shutdown() {
+  base::AutoLock lock(GetOzoneInstanceLock());
   auto* tmp = instance_;
   instance_ = nullptr;
   delete tmp;
@@ -58,12 +72,14 @@
 
 // static
 OzonePlatform* OzonePlatform::GetInstance() {
+  base::AutoLock lock(GetOzoneInstanceLock());
   DCHECK(instance_) << "OzonePlatform is not initialized";
   return instance_;
 }
 
 // static
 OzonePlatform* OzonePlatform::EnsureInstance() {
+  base::AutoLock lock(GetOzoneInstanceLock());
   if (!instance_) {
     TRACE_EVENT1("ozone",
                  "OzonePlatform::Initialize",
@@ -80,6 +96,21 @@
 }
 
 // static
+void OzonePlatform::RegisterStartupCallback(
+    base::OnceCallback<void(OzonePlatform*)> callback) {
+  OzonePlatform* inst = nullptr;
+  {
+    base::AutoLock lock(GetOzoneInstanceLock());
+    if (!instance_ || !g_platform_initialized_ui) {
+      instance_callback.Get() = std::move(callback);
+      return;
+    }
+    inst = instance_;
+  }
+  std::move(callback).Run(inst);
+}
+
+// static
 OzonePlatform* OzonePlatform::instance_ = nullptr;
 
 IPC::MessageFilter* OzonePlatform::GetGpuMessageFilter() {
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index 4fe0e9f..b6335ea 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -96,6 +96,15 @@
 
   static OzonePlatform* GetInstance();
 
+  // Registers a callback to be run when the OzonePlatform is initialized. Note
+  // that if an instance already exists, then the callback is called
+  // immediately. If an instance does not exist, and is created later, then the
+  // callback is called once the instance is created and initialized, on the
+  // thread it is initialized on. If the caller requires the callback to run on
+  // a specific thread, then it needs to do ensure that by itself.
+  static void RegisterStartupCallback(
+      base::OnceCallback<void(OzonePlatform*)> callback);
+
   // Factory getters to override in subclasses. The returned objects will be
   // injected into the appropriate layer at startup. Subclasses should not
   // inject these objects themselves. Ownership is retained by OzonePlatform.