diff --git a/.vpython b/.vpython
index 27117b1..c249e9c 100644
--- a/.vpython
+++ b/.vpython
@@ -153,7 +153,7 @@
 >
 wheel: <
   name: "infra/python/wheels/six-py2_py3"
-  version: "version:1.10.0"
+  version: "version:1.15.0"
 >
 wheel: <
   name: "infra/python/wheels/pyftpdlib-py2_py3"
@@ -218,7 +218,7 @@
 #   third_party/catapult
 wheel: <
   name: "infra/python/wheels/six-py2_py3"
-  version: "version:1.10.0"
+  version: "version:1.15.0"
 >
 wheel: <
   name: "infra/python/wheels/pbr-py2_py3"
@@ -248,7 +248,7 @@
 
 wheel <
   name: "infra/python/wheels/six-py2_py3"
-  version: "version:1.10.0"
+  version: "version:1.15.0"
 >
 
 wheel <
diff --git a/DEPS b/DEPS
index 467140e8..4948461 100644
--- a/DEPS
+++ b/DEPS
@@ -195,11 +195,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': 'fcb7ba035aae4958edf9d298daa0e6f8c11f2b65',
+  'skia_revision': '5bc663a55b26c22f658232e68285201489dfc8f6',
   # 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': '5e336253ddc9a811d2336b79553403e82dbe5896',
+  'v8_revision': '33aadb77fef52be264780851920ccc7d3669c7c2',
   # 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.
@@ -207,7 +207,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'bd7cef282080f66873b066b629ad3569276d19e0',
+  'angle_revision': '41442cce3d0f30dbfce4d95bdda18c0faa452b43',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -215,7 +215,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': 'bd9fea3cfc8e3420bc9f5e0b1c84fde0c55df7f1',
+  'pdfium_revision': 'f045cb21c570b9feb65b7e02c54d0b2cf096a513',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -266,7 +266,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '828c1805a64b1aeb3917d1648515efd8ed215f60',
+  'devtools_frontend_revision': '9fcc573bd51a414d3554298a0051d1052f329c00',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -318,11 +318,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'fada50119020483021a6b620c8fb85d62fc3e8f0',
+  'dawn_revision': '8c9858e9b8e36b8c13606b1053133ab395c03418',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '2146ce8055a5e96371eb31a169c46f322afac527',
+  'quiche_revision': '95d85af7aa56429eb52ad33bc67057c9d0e4cb8c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -545,7 +545,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'd8463cb28eb365143777007f58917083561ed0d2',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'bb04d0aab52f75f8b4596b340482791c549472e1',
       'condition': 'checkout_ios',
   },
 
@@ -1465,7 +1465,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '81bbd7199a2e97680a4488c2da4f8248137e12e0',
+    Var('webrtc_git') + '/src.git' + '@' + '353dcec4c1e839753875ed515e106647dc241e39',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1537,7 +1537,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9aa97c0bd39e7f564a7408bcf2184efb2a0e8316',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ba78a47d745f01b174e7687a89a2c74feb6c357f',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/android_protocol_handler.cc b/android_webview/browser/android_protocol_handler.cc
index 27142bc..7325d75e 100644
--- a/android_webview/browser/android_protocol_handler.cc
+++ b/android_webview/browser/android_protocol_handler.cc
@@ -43,7 +43,7 @@
   ScopedJavaLocalRef<jobject> stream =
       android_webview::Java_AndroidProtocolHandler_open(env, jurl);
 
-  if (stream.is_null()) {
+  if (!stream) {
     DLOG(ERROR) << "Unable to open input stream for Android URL";
     return nullptr;
   }
@@ -61,7 +61,7 @@
   ScopedJavaLocalRef<jstring> returned_type =
       android_webview::Java_AndroidProtocolHandler_getMimeType(
           env, stream->jobj(), java_url);
-  if (returned_type.is_null())
+  if (!returned_type)
     return false;
 
   *mime_type = base::android::ConvertJavaStringToUTF8(returned_type);
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc
index fe35023..7887e18 100644
--- a/android_webview/browser/aw_autofill_client.cc
+++ b/android_webview/browser/aw_autofill_client.cc
@@ -218,7 +218,7 @@
 void AwAutofillClient::HideAutofillPopup(autofill::PopupHidingReason reason) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   delegate_.reset();
   Java_AwAutofillClient_hideAutofillPopup(env, obj);
@@ -313,7 +313,7 @@
     const std::vector<autofill::Suggestion>& suggestions) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   // We need an array of AutofillSuggestion.
@@ -335,11 +335,11 @@
     return;
 
   const ScopedJavaLocalRef<jobject> current_view = anchor_view_.view();
-  if (current_view.is_null())
+  if (!current_view)
     anchor_view_ = view_android->AcquireAnchorView();
 
   const ScopedJavaLocalRef<jobject> view = anchor_view_.view();
-  if (view.is_null())
+  if (!view)
     return;
 
   view_android->SetAnchorRect(view, element_bounds);
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index 49501be4..d01416e 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -281,7 +281,7 @@
       web_contents_.get(), std::make_unique<InterceptNavigationDelegate>(
                                env, intercept_navigation_delegate));
 
-  if (!autofill_provider.is_null()) {
+  if (autofill_provider) {
     autofill_provider_ = std::make_unique<autofill::AutofillProviderAndroid>(
         autofill_provider, web_contents_.get());
   }
@@ -308,7 +308,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   // Just return, if the app neither runs on O sdk nor enables autocomplete.
@@ -327,7 +327,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   Java_AwContents_setAwAutofillClient(env, obj, client);
 }
@@ -500,7 +500,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return false;
 
   ScopedJavaLocalRef<jstring> jhost = ConvertUTF8ToJavaString(env, host);
@@ -631,12 +631,12 @@
 void AwContents::OnPermissionRequest(
     base::android::ScopedJavaLocalRef<jobject> j_request,
     AwPermissionRequest* request) {
-  DCHECK(!j_request.is_null());
+  DCHECK(j_request);
   DCHECK(request);
 
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
-  if (j_ref.is_null()) {
+  if (!j_ref) {
     permission_request_handler_->CancelRequest(request->GetOrigin(),
                                                request->GetResources());
     return;
@@ -649,7 +649,7 @@
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> j_request = request->GetJavaObject();
   ScopedJavaLocalRef<jobject> j_ref = java_ref_.get(env);
-  if (j_request.is_null() || j_ref.is_null())
+  if (!j_request || !j_ref)
     return;
 
   Java_AwContents_onPermissionRequestCanceled(env, j_ref, j_request);
@@ -682,7 +682,7 @@
     base::OnceCallback<void(bool)> callback) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj)) {
@@ -697,7 +697,7 @@
 void AwContents::CancelGeolocationPermissionRequests(const GURL& origin) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   if (Java_AwContents_useLegacyGeolocationPermissionAPI(env, obj)) {
@@ -785,7 +785,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   Java_AwContents_onFindResultReceived(env, obj, active_ordinal, match_count,
@@ -800,7 +800,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   content::NavigationEntry* entry =
@@ -820,7 +820,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   Java_AwContents_onReceivedTouchIconUrl(
@@ -831,7 +831,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null())
+  if (obj)
     Java_AwContents_postInvalidateOnAnimation(env, obj);
 }
 
@@ -839,7 +839,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null()) {
+  if (obj) {
     devtools_instrumentation::ScopedEmbedderCallbackTask embedder_callback(
         "onNewPicture");
     Java_AwContents_onNewPicture(env, obj);
@@ -1131,7 +1131,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return gfx::Point();
   std::vector<int> location;
   base::android::JavaIntArrayToIntVector(
@@ -1143,7 +1143,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   Java_AwContents_scrollContainerViewTo(env, obj, new_value.x(), new_value.y());
 }
@@ -1156,7 +1156,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   Java_AwContents_updateScrollState(
       env, obj, max_scroll_offset.x(), max_scroll_offset.y(),
@@ -1169,7 +1169,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   Java_AwContents_didOverscroll(env, obj, overscroll_delta.x(),
                                 overscroll_delta.y(), overscroll_velocity.x(),
@@ -1179,7 +1179,7 @@
 ui::TouchHandleDrawable* AwContents::CreateDrawable() {
   JNIEnv* env = AttachCurrentThread();
   const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return nullptr;
   return reinterpret_cast<ui::TouchHandleDrawable*>(
       Java_AwContents_onCreateTouchHandle(env, obj));
@@ -1237,7 +1237,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   Java_AwContents_onWebLayoutPageScaleFactorChanged(env, obj,
                                                     page_scale_factor);
@@ -1248,7 +1248,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   gfx::Size contents_size_css =
       content::IsUseZoomForDSFEnabled()
@@ -1282,7 +1282,7 @@
                                bool result) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   Java_AwContents_invokeVisualStateCallback(env, obj, callback, request_id);
 }
@@ -1531,7 +1531,7 @@
 bool AwContents::CanShowInterstitial() {
   JNIEnv* env = AttachCurrentThread();
   const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return false;
   return Java_AwContents_canShowInterstitial(env, obj);
 }
@@ -1539,7 +1539,7 @@
 int AwContents::GetErrorUiType() {
   JNIEnv* env = AttachCurrentThread();
   const ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return false;
   return Java_AwContents_getErrorUiType(env, obj);
 }
@@ -1556,7 +1556,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   AwRenderProcess* aw_render_process =
@@ -1570,7 +1570,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   AwRenderProcess* aw_render_process =
@@ -1585,7 +1585,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return RenderProcessGoneResult::kHandled;
 
   bool result =
diff --git a/android_webview/browser/aw_contents_client_bridge.cc b/android_webview/browser/aw_contents_client_bridge.cc
index 1bd2d18..04a4f11 100644
--- a/android_webview/browser/aw_contents_client_bridge.cc
+++ b/android_webview/browser/aw_contents_client_bridge.cc
@@ -116,7 +116,7 @@
 AwContentsClientBridge::AwContentsClientBridge(JNIEnv* env,
                                                const JavaRef<jobject>& obj)
     : java_ref_(env, obj) {
-  DCHECK(!obj.is_null());
+  DCHECK(obj);
   Java_AwContentsClientBridge_setNativeContentsClientBridge(
       env, obj, reinterpret_cast<intptr_t>(this));
 }
@@ -125,7 +125,7 @@
   JNIEnv* env = AttachCurrentThread();
 
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null()) {
+  if (obj) {
     // Clear the weak reference from the java peer to the native object since
     // it is possible that java object lifetime can exceed the AwContens.
     Java_AwContentsClientBridge_setNativeContentsClientBridge(env, obj, 0);
@@ -141,7 +141,7 @@
   JNIEnv* env = AttachCurrentThread();
 
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   base::StringPiece der_string =
@@ -189,7 +189,7 @@
 
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   // Build the |key_types| JNI parameter, as a String[]
@@ -210,7 +210,7 @@
 
   ScopedJavaLocalRef<jobjectArray> key_types_ref =
       base::android::ToJavaArrayOfStrings(env, key_types);
-  if (key_types_ref.is_null()) {
+  if (!key_types_ref) {
     LOG(ERROR) << "Could not create key types array (String[])";
     return;
   }
@@ -219,7 +219,7 @@
   ScopedJavaLocalRef<jobjectArray> principals_ref =
       base::android::ToJavaArrayOfByteArray(
           env, cert_request_info->cert_authorities);
-  if (principals_ref.is_null()) {
+  if (!principals_ref) {
     LOG(ERROR) << "Could not create principals array (byte[][])";
     return;
   }
@@ -253,7 +253,7 @@
   pending_client_cert_request_delegates_.Remove(request_id);
   DCHECK(delegate);
 
-  if (encoded_chain_ref.is_null() || private_key_ref.is_null()) {
+  if (!encoded_chain_ref || !private_key_ref) {
     LOG(ERROR) << "No client certificate selected";
     delegate->ContinueWithCertificate(nullptr, nullptr);
     return;
@@ -261,7 +261,7 @@
 
   // Convert the encoded chain to a vector of strings.
   std::vector<std::string> encoded_chain_strings;
-  if (!encoded_chain_ref.is_null()) {
+  if (encoded_chain_ref) {
     base::android::JavaArrayOfByteArrayToStringVector(env, encoded_chain_ref,
                                                       &encoded_chain_strings);
   }
@@ -300,7 +300,7 @@
   JNIEnv* env = AttachCurrentThread();
 
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null()) {
+  if (!obj) {
     std::move(callback).Run(false, base::string16());
     return;
   }
@@ -346,7 +346,7 @@
   JNIEnv* env = AttachCurrentThread();
 
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null()) {
+  if (!obj) {
     std::move(callback).Run(false, base::string16());
     return;
   }
@@ -375,7 +375,7 @@
   *ignore_navigation = false;
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return true;
   ScopedJavaLocalRef<jstring> jurl = ConvertUTF16ToJavaString(env, url);
   devtools_instrumentation::ScopedEmbedderCallbackTask(
@@ -402,7 +402,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   ScopedJavaLocalRef<jstring> jstring_url =
@@ -425,7 +425,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm);
@@ -448,7 +448,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   ScopedJavaLocalRef<jstring> jstring_description =
@@ -475,7 +475,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request;
@@ -494,7 +494,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request;
@@ -554,7 +554,7 @@
     return;
   }
   base::string16 prompt_text;
-  if (!prompt.is_null()) {
+  if (prompt) {
     prompt_text = ConvertJavaStringToUTF16(env, prompt);
   }
   std::move(*callback).Run(true, prompt_text);
diff --git a/android_webview/browser/aw_contents_io_thread_client.cc b/android_webview/browser/aw_contents_io_thread_client.cc
index 5203305..2701e71 100644
--- a/android_webview/browser/aw_contents_io_thread_client.cc
+++ b/android_webview/browser/aw_contents_io_thread_client.cc
@@ -242,7 +242,7 @@
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> java_delegate =
       client_data.io_thread_client.get(env);
-  DCHECK(!client_data.pending_association || java_delegate.is_null());
+  DCHECK(!client_data.pending_association || !java_delegate);
   return std::make_unique<AwContentsIoThreadClient>(
       client_data.pending_association, java_delegate);
 }
@@ -257,7 +257,7 @@
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> java_delegate =
       client_data.io_thread_client.get(env);
-  DCHECK(!client_data.pending_association || java_delegate.is_null());
+  DCHECK(!client_data.pending_association || !java_delegate);
   return std::make_unique<AwContentsIoThreadClient>(
       client_data.pending_association, java_delegate);
 }
@@ -312,7 +312,7 @@
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> java_delegate = g_sw_instance_.Get().get(env);
 
-  if (java_delegate.is_null())
+  if (!java_delegate)
     return nullptr;
 
   return std::make_unique<AwContentsIoThreadClient>(false, java_delegate);
@@ -331,7 +331,7 @@
 AwContentsIoThreadClient::CacheMode AwContentsIoThreadClient::GetCacheMode()
     const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (java_object_.is_null())
+  if (!java_object_)
     return AwContentsIoThreadClient::LOAD_DEFAULT;
 
   JNIEnv* env = AttachCurrentThread();
@@ -421,7 +421,7 @@
 
   JNIEnv* env = AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> obj = ref.get(env);
-  if (obj.is_null()) {
+  if (!obj) {
     return NoInterceptRequest();
   }
 
@@ -437,9 +437,9 @@
           java_web_resource_request.jheader_names,
           java_web_resource_request.jheader_values);
 
-  RecordInterceptedScheme(ret.is_null(), request.url);
+  RecordInterceptedScheme(!ret, request.url);
 
-  if (ret.is_null())
+  if (!ret)
     return NoInterceptRequest();
 
   auto response = std::make_unique<AwWebResourceInterceptResponse>(ret);
@@ -462,12 +462,12 @@
   base::OnceCallback<std::unique_ptr<AwWebResourceInterceptResponse>()>
       get_response = base::BindOnce(&NoInterceptRequest);
   JNIEnv* env = AttachCurrentThread();
-  if (bg_thread_client_object_.is_null() && !java_object_.is_null()) {
+  if (!bg_thread_client_object_ && java_object_) {
     bg_thread_client_object_.Reset(
         Java_AwContentsIoThreadClient_getBackgroundThreadClient(env,
                                                                 java_object_));
   }
-  if (!bg_thread_client_object_.is_null()) {
+  if (bg_thread_client_object_) {
     get_response = base::BindOnce(
         &RunShouldInterceptRequest, std::move(request),
         JavaObjectWeakGlobalRef(env, bg_thread_client_object_.obj()));
@@ -479,7 +479,7 @@
 
 bool AwContentsIoThreadClient::ShouldBlockContentUrls() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (java_object_.is_null())
+  if (!java_object_)
     return false;
 
   JNIEnv* env = AttachCurrentThread();
@@ -489,7 +489,7 @@
 
 bool AwContentsIoThreadClient::ShouldBlockFileUrls() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (java_object_.is_null())
+  if (!java_object_)
     return false;
 
   JNIEnv* env = AttachCurrentThread();
@@ -498,7 +498,7 @@
 
 bool AwContentsIoThreadClient::ShouldAcceptThirdPartyCookies() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (java_object_.is_null())
+  if (!java_object_)
     return false;
 
   JNIEnv* env = AttachCurrentThread();
@@ -508,7 +508,7 @@
 
 bool AwContentsIoThreadClient::GetSafeBrowsingEnabled() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (java_object_.is_null())
+  if (!java_object_)
     return false;
 
   JNIEnv* env = AttachCurrentThread();
@@ -518,7 +518,7 @@
 
 bool AwContentsIoThreadClient::ShouldBlockNetworkLoads() const {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (java_object_.is_null())
+  if (!java_object_)
     return false;
 
   JNIEnv* env = AttachCurrentThread();
diff --git a/android_webview/browser/aw_pdf_exporter.cc b/android_webview/browser/aw_pdf_exporter.cc
index 2d0436c4..5adcf168 100644
--- a/android_webview/browser/aw_pdf_exporter.cc
+++ b/android_webview/browser/aw_pdf_exporter.cc
@@ -44,7 +44,7 @@
                              const JavaRef<jobject>& obj,
                              content::WebContents* web_contents)
     : java_ref_(env, obj), web_contents_(web_contents) {
-  DCHECK(!obj.is_null());
+  DCHECK(obj);
   Java_AwPdfExporter_setNativeAwPdfExporter(env, obj,
                                             reinterpret_cast<intptr_t>(this));
 }
@@ -52,7 +52,7 @@
 AwPdfExporter::~AwPdfExporter() {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   // Clear the Java peer's weak pointer to |this| object.
   Java_AwPdfExporter_setNativeAwPdfExporter(env, obj, 0);
@@ -122,7 +122,7 @@
 void AwPdfExporter::DidExportPdf(int page_count) {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   Java_AwPdfExporter_didExportPdf(env, obj, page_count);
 }
diff --git a/android_webview/browser/aw_proxy_controller.cc b/android_webview/browser/aw_proxy_controller.cc
index 753ac7f9..4764f2073 100644
--- a/android_webview/browser/aw_proxy_controller.cc
+++ b/android_webview/browser/aw_proxy_controller.cc
@@ -32,7 +32,7 @@
                           const JavaRef<jobject>& listener,
                           const JavaRef<jobject>& executor) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (listener.is_null())
+  if (!listener)
     return;
   JNIEnv* env = AttachCurrentThread();
   Java_AwProxyController_proxyOverrideChanged(env, obj, listener, executor);
diff --git a/android_webview/browser/aw_quota_manager_bridge.cc b/android_webview/browser/aw_quota_manager_bridge.cc
index c87567c..1d94aa6 100644
--- a/android_webview/browser/aw_quota_manager_bridge.cc
+++ b/android_webview/browser/aw_quota_manager_bridge.cc
@@ -252,7 +252,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   Java_AwQuotaManagerBridge_onGetOriginsCallback(
@@ -318,7 +318,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
 
   Java_AwQuotaManagerBridge_onGetUsageAndQuotaForOriginCallback(
diff --git a/android_webview/browser/aw_render_process.cc b/android_webview/browser/aw_render_process.cc
index 0f8514a..bf8eb59 100644
--- a/android_webview/browser/aw_render_process.cc
+++ b/android_webview/browser/aw_render_process.cc
@@ -42,7 +42,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   java_obj_.Reset(Java_AwRenderProcess_create(AttachCurrentThread()));
-  CHECK(!java_obj_.is_null());
+  CHECK(java_obj_);
   if (render_process_host_->IsReady()) {
     Ready();
   }
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc
index e68dadde..c30942c2 100644
--- a/android_webview/browser/aw_settings.cc
+++ b/android_webview/browser/aw_settings.cc
@@ -91,7 +91,7 @@
 
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
-  if (scoped_obj.is_null())
+  if (!scoped_obj)
     return;
   Java_AwSettings_nativeAwSettingsGone(env, scoped_obj,
                                        reinterpret_cast<intptr_t>(this));
@@ -139,7 +139,7 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   CHECK(env);
   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
-  if (scoped_obj.is_null())
+  if (!scoped_obj)
     return;
   // Grab the lock and call UpdateEverythingLocked.
   Java_AwSettings_updateEverything(env, scoped_obj);
@@ -166,7 +166,7 @@
 
   ScopedJavaLocalRef<jstring> str =
       Java_AwSettings_getUserAgentLocked(env, obj);
-  bool ua_overidden = str.obj() != NULL;
+  bool ua_overidden = !!str;
 
   if (ua_overidden) {
     std::string override = base::android::ConvertJavaStringToUTF8(str);
@@ -313,7 +313,7 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   CHECK(env);
   ScopedJavaLocalRef<jobject> scoped_obj = aw_settings_.get(env);
-  if (scoped_obj.is_null())
+  if (!scoped_obj)
     return;
   // Grab the lock and call PopulateWebPreferencesLocked.
   Java_AwSettings_populateWebPreferences(env, scoped_obj,
diff --git a/android_webview/browser/aw_ssl_host_state_delegate.cc b/android_webview/browser/aw_ssl_host_state_delegate.cc
index 0a0cf0b..8ede404d 100644
--- a/android_webview/browser/aw_ssl_host_state_delegate.cc
+++ b/android_webview/browser/aw_ssl_host_state_delegate.cc
@@ -70,7 +70,7 @@
 
 void AwSSLHostStateDelegate::Clear(
     base::RepeatingCallback<bool(const std::string&)> host_filter) {
-  if (host_filter.is_null()) {
+  if (!host_filter) {
     cert_policy_for_host_.clear();
     return;
   }
diff --git a/android_webview/browser/gfx/aw_gl_functor.cc b/android_webview/browser/gfx/aw_gl_functor.cc
index 850f6ae..ce3b86f 100644
--- a/android_webview/browser/gfx/aw_gl_functor.cc
+++ b/android_webview/browser/gfx/aw_gl_functor.cc
@@ -49,7 +49,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return false;
   return Java_AwGLFunctor_requestInvokeGL(env, obj, wait_for_completion);
 }
@@ -58,7 +58,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null())
+  if (obj)
     Java_AwGLFunctor_detachFunctorFromView(env, obj);
 }
 
diff --git a/android_webview/browser/gfx/aw_gl_surface.cc b/android_webview/browser/gfx/aw_gl_surface.cc
index 237a96f..66e4df59 100644
--- a/android_webview/browser/gfx/aw_gl_surface.cc
+++ b/android_webview/browser/gfx/aw_gl_surface.cc
@@ -26,7 +26,7 @@
 }
 
 gfx::SwapResult AwGLSurface::SwapBuffers(PresentationCallback callback) {
-  DCHECK(pending_presentation_callback_.is_null());
+  DCHECK(!pending_presentation_callback_);
   pending_presentation_callback_ = std::move(callback);
   return gfx::SwapResult::SWAP_ACK;
 }
@@ -60,7 +60,7 @@
 }
 
 void AwGLSurface::MaybeDidPresent(gfx::PresentationFeedback feedback) {
-  if (pending_presentation_callback_.is_null())
+  if (!pending_presentation_callback_)
     return;
   std::move(pending_presentation_callback_).Run(std::move(feedback));
 }
diff --git a/android_webview/browser/input_stream.cc b/android_webview/browser/input_stream.cc
index 3441702..6971788 100644
--- a/android_webview/browser/input_stream.cc
+++ b/android_webview/browser/input_stream.cc
@@ -35,7 +35,7 @@
 InputStream::InputStream() {}
 
 InputStream::InputStream(const JavaRef<jobject>& stream) : jobject_(stream) {
-  DCHECK(!stream.is_null());
+  DCHECK(stream);
 }
 
 InputStream::~InputStream() {
diff --git a/android_webview/browser/input_stream_unittest.cc b/android_webview/browser/input_stream_unittest.cc
index bd099de..d048ff338 100644
--- a/android_webview/browser/input_stream_unittest.cc
+++ b/android_webview/browser/input_stream_unittest.cc
@@ -44,7 +44,7 @@
                                                   int* bytes_read) {
     ScopedJavaLocalRef<jobject> counting_jstream =
         Java_InputStreamUnittest_getCountingStream(env_, stream_size);
-    EXPECT_FALSE(counting_jstream.is_null());
+    EXPECT_TRUE(counting_jstream);
 
     std::unique_ptr<InputStream> input_stream(
         new InputStream(counting_jstream));
@@ -60,7 +60,7 @@
 TEST_F(InputStreamTest, ReadEmptyStream) {
   ScopedJavaLocalRef<jobject> empty_jstream =
       Java_InputStreamUnittest_getEmptyStream(env_);
-  EXPECT_FALSE(empty_jstream.is_null());
+  EXPECT_TRUE(empty_jstream);
 
   std::unique_ptr<InputStream> input_stream(new InputStream(empty_jstream));
   const int bytes_requested = 10;
@@ -120,7 +120,7 @@
 TEST_F(InputStreamTest, DoesNotCrashWhenExceptionThrown) {
   ScopedJavaLocalRef<jobject> throw_jstream =
       Java_InputStreamUnittest_getThrowingStream(env_);
-  EXPECT_FALSE(throw_jstream.is_null());
+  EXPECT_TRUE(throw_jstream);
 
   std::unique_ptr<InputStream> input_stream(new InputStream(throw_jstream));
 
diff --git a/android_webview/browser/js_java_interaction/js_reply_proxy.cc b/android_webview/browser/js_java_interaction/js_reply_proxy.cc
index aeb5cbb..2f55ef2 100644
--- a/android_webview/browser/js_java_interaction/js_reply_proxy.cc
+++ b/android_webview/browser/js_java_interaction/js_reply_proxy.cc
@@ -19,7 +19,7 @@
 }
 
 JsReplyProxy::~JsReplyProxy() {
-  if (java_ref_.is_null())
+  if (!java_ref_)
     return;
 
   JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/android_webview/browser/network_service/aw_web_resource_intercept_response.cc b/android_webview/browser/network_service/aw_web_resource_intercept_response.cc
index 7ecf6b2..502123f 100644
--- a/android_webview/browser/network_service/aw_web_resource_intercept_response.cc
+++ b/android_webview/browser/network_service/aw_web_resource_intercept_response.cc
@@ -27,15 +27,14 @@
 }
 
 bool AwWebResourceInterceptResponse::HasResponse(JNIEnv* env) const {
-  return !Java_AwWebResourceInterceptResponse_getResponse(env, java_object_)
-              .is_null();
+  return !!Java_AwWebResourceInterceptResponse_getResponse(env, java_object_);
 }
 
 std::unique_ptr<AwWebResourceResponse>
 AwWebResourceInterceptResponse::GetResponse(JNIEnv* env) const {
   ScopedJavaLocalRef<jobject> j_response =
       Java_AwWebResourceInterceptResponse_getResponse(env, java_object_);
-  if (j_response.is_null())
+  if (!j_response)
     return nullptr;
   return std::make_unique<AwWebResourceResponse>(j_response);
 }
diff --git a/android_webview/browser/network_service/aw_web_resource_response.cc b/android_webview/browser/network_service/aw_web_resource_response.cc
index 8feb9a2a..144832a5 100644
--- a/android_webview/browser/network_service/aw_web_resource_response.cc
+++ b/android_webview/browser/network_service/aw_web_resource_response.cc
@@ -31,7 +31,7 @@
 bool AwWebResourceResponse::HasInputStream(JNIEnv* env) const {
   ScopedJavaLocalRef<jobject> jstream =
       Java_AwWebResourceResponse_getData(env, java_object_);
-  return !jstream.is_null();
+  return !!jstream;
 }
 
 std::unique_ptr<InputStream> AwWebResourceResponse::GetInputStream(
@@ -49,7 +49,7 @@
   input_stream_transferred_ = true;
   ScopedJavaLocalRef<jobject> jstream =
       Java_AwWebResourceResponse_getData(env, java_object_);
-  if (jstream.is_null())
+  if (!jstream)
     return nullptr;
   return std::make_unique<InputStream>(jstream);
 }
@@ -58,7 +58,7 @@
                                         std::string* mime_type) const {
   ScopedJavaLocalRef<jstring> jstring_mime_type =
       Java_AwWebResourceResponse_getMimeType(env, java_object_);
-  if (jstring_mime_type.is_null())
+  if (!jstring_mime_type)
     return false;
   *mime_type = ConvertJavaStringToUTF8(jstring_mime_type);
   return true;
@@ -68,7 +68,7 @@
                                        std::string* charset) const {
   ScopedJavaLocalRef<jstring> jstring_charset =
       Java_AwWebResourceResponse_getCharset(env, java_object_);
-  if (jstring_charset.is_null())
+  if (!jstring_charset)
     return false;
   *charset = ConvertJavaStringToUTF8(jstring_charset);
   return true;
@@ -80,7 +80,7 @@
   int status = Java_AwWebResourceResponse_getStatusCode(env, java_object_);
   ScopedJavaLocalRef<jstring> jstring_reason_phrase =
       Java_AwWebResourceResponse_getReasonPhrase(env, java_object_);
-  if (status < 100 || status >= 600 || jstring_reason_phrase.is_null())
+  if (status < 100 || status >= 600 || !jstring_reason_phrase)
     return false;
   *status_code = status;
   *reason_phrase = ConvertJavaStringToUTF8(jstring_reason_phrase);
@@ -94,7 +94,7 @@
       Java_AwWebResourceResponse_getResponseHeaderNames(env, java_object_);
   ScopedJavaLocalRef<jobjectArray> jstringArray_headerValues =
       Java_AwWebResourceResponse_getResponseHeaderValues(env, java_object_);
-  if (jstringArray_headerNames.is_null() || jstringArray_headerValues.is_null())
+  if (!jstringArray_headerNames || !jstringArray_headerValues)
     return false;
   std::vector<std::string> header_names;
   std::vector<std::string> header_values;
diff --git a/android_webview/browser/permission/aw_permission_request.cc b/android_webview/browser/permission/aw_permission_request.cc
index 1890884d..70e2a3e 100644
--- a/android_webview/browser/permission/aw_permission_request.cc
+++ b/android_webview/browser/permission/aw_permission_request.cc
@@ -61,7 +61,7 @@
 
 void AwPermissionRequest::DeleteThis() {
   ScopedJavaLocalRef<jobject> j_request = GetJavaObject();
-  if (j_request.is_null())
+  if (!j_request)
     return;
   Java_AwPermissionRequest_destroyNative(AttachCurrentThread(), j_request);
 }
diff --git a/android_webview/browser/popup_touch_handle_drawable.cc b/android_webview/browser/popup_touch_handle_drawable.cc
index 9798840..1dfb75a 100644
--- a/android_webview/browser/popup_touch_handle_drawable.cc
+++ b/android_webview/browser/popup_touch_handle_drawable.cc
@@ -23,14 +23,14 @@
 PopupTouchHandleDrawable::~PopupTouchHandleDrawable() {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null())
+  if (obj)
     Java_PopupTouchHandleDrawable_destroy(env, obj);
 }
 
 void PopupTouchHandleDrawable::SetEnabled(bool enabled) {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return;
   if (enabled)
     Java_PopupTouchHandleDrawable_show(env, obj);
@@ -44,7 +44,7 @@
     bool mirror_horizontal) {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null()) {
+  if (obj) {
     Java_PopupTouchHandleDrawable_setOrientation(
         env, obj, static_cast<int>(orientation), mirror_vertical,
         mirror_horizontal);
@@ -54,7 +54,7 @@
 void PopupTouchHandleDrawable::SetOrigin(const gfx::PointF& origin) {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (!obj.is_null()) {
+  if (obj) {
     Java_PopupTouchHandleDrawable_setOrigin(env, obj, origin.x(), origin.y());
   }
 }
@@ -63,14 +63,14 @@
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
   bool visible = alpha > 0;
-  if (!obj.is_null())
+  if (obj)
     Java_PopupTouchHandleDrawable_setVisible(env, obj, visible);
 }
 
 gfx::RectF PopupTouchHandleDrawable::GetVisibleBounds() const {
   JNIEnv* env = base::android::AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
-  if (obj.is_null())
+  if (!obj)
     return gfx::RectF();
   return gfx::RectF(
       Java_PopupTouchHandleDrawable_getOriginXDip(env, obj),
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 67fa7f7..c2fabf06 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1944,7 +1944,6 @@
     "system/message_center/ash_message_popup_collection_unittest.cc",
     "system/message_center/inactive_user_notification_blocker_unittest.cc",
     "system/message_center/message_center_ui_controller_unittest.cc",
-    "system/message_center/notification_swipe_control_view_unittest.cc",
     "system/message_center/notifier_settings_view_unittest.cc",
     "system/message_center/session_state_notification_blocker_unittest.cc",
     "system/message_center/unified_message_center_bubble_unittest.cc",
diff --git a/ash/accessibility/spoken_feedback_enabler.cc b/ash/accessibility/spoken_feedback_enabler.cc
index 8c2f350..e85f5db 100644
--- a/ash/accessibility/spoken_feedback_enabler.cc
+++ b/ash/accessibility/spoken_feedback_enabler.cc
@@ -32,7 +32,7 @@
 
 void SpokenFeedbackEnabler::OnTimer() {
   base::TimeTicks now = ui::EventTimeForNow();
-  double tick_count_f = (now - start_time_) / kTimerDelay;
+  double tick_count_f = (now - start_time_).IntDiv(kTimerDelay);
   int tick_count = roundf(tick_count_f);
 
   AccessibilityControllerImpl* controller =
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc
index 6357487..0eafbe63 100644
--- a/ash/ambient/ambient_controller.cc
+++ b/ash/ambient/ambient_controller.cc
@@ -48,9 +48,6 @@
 
 namespace {
 
-constexpr base::TimeDelta kAutoShowWaitTimeInterval =
-    base::TimeDelta::FromSeconds(15);
-
 // Used by wake lock APIs.
 constexpr char kWakeLockReason[] = "AmbientMode";
 
@@ -242,7 +239,8 @@
       } else {
         DCHECK(visibility == AmbientUiVisibility::kClosed);
         inactivity_monitor_.reset();
-        power_status_observer_.Remove(PowerStatus::Get());
+        if (power_status_observer_.IsObserving(PowerStatus::Get()))
+          power_status_observer_.Remove(PowerStatus::Get());
       }
 
       break;
@@ -341,15 +339,19 @@
 
 void AmbientController::ScreenIdleStateChanged(
     const power_manager::ScreenIdleState& idle_state) {
-  if (!IsUiClosed(ambient_ui_model_.ui_visibility()))
+  if (!AmbientClient::Get()->IsAmbientModeAllowed())
+    return;
+
+  if (!idle_state.dimmed())
     return;
 
   auto* session_controller = Shell::Get()->session_controller();
-  if (idle_state.dimmed() && !session_controller->IsScreenLocked() &&
-      session_controller->CanLockScreen()) {
+  if (session_controller->CanLockScreen() &&
+      session_controller->ShouldLockScreenAutomatically()) {
     // TODO(b/161469136): revise this behavior after further discussion.
-    // Locks the device when screen is dimmed to start ambient screen.
     Shell::Get()->session_controller()->LockScreen();
+  } else {
+    ShowUi(AmbientUiMode::kInSessionUi);
   }
 }
 
@@ -364,15 +366,20 @@
 }
 
 void AmbientController::ShowUi(AmbientUiMode mode) {
-  // TODO(meilinw): move the eligibility check to the idle entry point once
-  // implemented: b/149246117.
   if (!AmbientClient::Get()->IsAmbientModeAllowed()) {
     LOG(WARNING) << "Ambient mode is not allowed.";
     return;
   }
 
   ambient_ui_model_.SetUiMode(mode);
-  ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kShown);
+  switch (mode) {
+    case AmbientUiMode::kInSessionUi:
+      ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kShown);
+      break;
+    case AmbientUiMode::kLockScreenUi:
+      ambient_ui_model_.SetUiVisibility(AmbientUiVisibility::kHidden);
+      break;
+  }
 }
 
 void AmbientController::CloseUi() {
@@ -480,7 +487,7 @@
 
 void AmbientController::OnImagesChanged() {
   if (!container_view_)
-    CreateWidget();
+    CreateAndShowWidget();
 }
 
 std::unique_ptr<AmbientContainerView> AmbientController::CreateContainerView() {
@@ -491,7 +498,7 @@
   return container;
 }
 
-void AmbientController::CreateWidget() {
+void AmbientController::CreateAndShowWidget() {
   DCHECK(!container_view_);
 
   views::Widget::InitParams params;
@@ -529,4 +536,5 @@
   ambient_backend_controller_ = std::move(backend_controller);
 }
 
+constexpr base::TimeDelta AmbientController::kAutoShowWaitTimeInterval;
 }  // namespace ash
diff --git a/ash/ambient/ambient_controller.h b/ash/ambient/ambient_controller.h
index 3abe5975..2a8363a 100644
--- a/ash/ambient/ambient_controller.h
+++ b/ash/ambient/ambient_controller.h
@@ -43,6 +43,9 @@
       public PowerStatus::Observer,
       public chromeos::PowerManagerClient::Observer {
  public:
+  static constexpr base::TimeDelta kAutoShowWaitTimeInterval =
+      base::TimeDelta::FromSeconds(15);
+
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
 
   AmbientController();
@@ -109,7 +112,7 @@
   // TODO(meilinw): reuses the lock-screen widget: b/156531168, b/157175030.
   // Creates and shows a full-screen widget responsible for showing
   // the ambient UI.
-  void CreateWidget();
+  void CreateAndShowWidget();
 
   void StartRefreshingImages();
   void StopRefreshingImages();
diff --git a/ash/ambient/ambient_controller_unittest.cc b/ash/ambient/ambient_controller_unittest.cc
index 2ba8c7ec8..ad0804d 100644
--- a/ash/ambient/ambient_controller_unittest.cc
+++ b/ash/ambient/ambient_controller_unittest.cc
@@ -22,10 +22,26 @@
 
 namespace ash {
 
-using AmbientControllerTest = AmbientAshTestBase;
+class AmbientControllerTest : public AmbientAshTestBase {
+ public:
+  AmbientControllerTest() : AmbientAshTestBase() {}
+  ~AmbientControllerTest() override = default;
+
+  // AmbientAshTestBase:
+  void SetUp() override {
+    AmbientAshTestBase::SetUp();
+    GetSessionControllerClient()->set_show_lock_screen_views(true);
+  }
+};
 
 TEST_F(AmbientControllerTest, ShowAmbientScreenUponLock) {
   LockScreen();
+  // Lockscreen will not immediately show Ambient mode.
+  EXPECT_FALSE(ambient_controller()->IsShown());
+
+  // Ambient mode will show after inacivity and successfully loading first
+  // image.
+  FastForwardToInactivity();
   FastForwardToNextImage();
 
   EXPECT_TRUE(container_view());
@@ -34,11 +50,13 @@
   EXPECT_TRUE(ambient_controller()->IsShown());
 
   // Clean up.
-  CloseAmbientScreen();
+  UnlockScreen();
+  EXPECT_FALSE(ambient_controller()->IsShown());
 }
 
 TEST_F(AmbientControllerTest, HideAmbientScreen) {
   LockScreen();
+  FastForwardToInactivity();
   FastForwardToNextImage();
 
   EXPECT_TRUE(container_view());
@@ -53,11 +71,13 @@
             AmbientUiVisibility::kHidden);
 
   // Clean up.
-  CloseAmbientScreen();
+  UnlockScreen();
+  EXPECT_FALSE(ambient_controller()->IsShown());
 }
 
 TEST_F(AmbientControllerTest, CloseAmbientScreenUponUnlock) {
   LockScreen();
+  FastForwardToInactivity();
   FastForwardToNextImage();
 
   EXPECT_TRUE(container_view());
@@ -138,10 +158,6 @@
 
 TEST_F(AmbientControllerTest,
        CheckAcquireAndReleaseWakeLockWhenBatteryIsCharging) {
-  // Flush the loop first to ensure the |PowerStatus| has picked up the initial
-  // status.
-  base::RunLoop().RunUntilIdle();
-
   // Simulate a device being connected to a charger initially.
   power_manager::PowerSupplyProperties proto;
   proto.set_battery_state(
@@ -151,7 +167,8 @@
   // Lock screen to start ambient mode, and flush the loop to ensure
   // the acquire wake lock request has reached the wake lock provider.
   LockScreen();
-  base::RunLoop().RunUntilIdle();
+  FastForwardToInactivity();
+  FastForwardToNextImage();
 
   EXPECT_EQ(1, GetNumOfActiveWakeLocks(
                    device::mojom::WakeLockType::kPreventDisplaySleep));
@@ -162,11 +179,8 @@
   EXPECT_EQ(0, GetNumOfActiveWakeLocks(
                    device::mojom::WakeLockType::kPreventDisplaySleep));
 
-  // TODO(meilinw): refactor |AmbientAshTestBase| to make this built-in.
-  // Simulate the ambient screen being shown again.
-  ambient_controller()->OnAmbientUiVisibilityChanged(
-      AmbientUiVisibility::kShown);
-  base::RunLoop().RunUntilIdle();
+  // Ambient screen showup again after inactivity.
+  FastForwardToInactivity();
 
   EXPECT_EQ(1, GetNumOfActiveWakeLocks(
                    device::mojom::WakeLockType::kPreventDisplaySleep));
@@ -181,10 +195,6 @@
 
 TEST_F(AmbientControllerTest,
        CheckAcquireAndReleaseWakeLockWhenBatteryStateChanged) {
-  // Flush the loop first to ensure the |PowerStatus| has picked up the initial
-  // status.
-  base::RunLoop().RunUntilIdle();
-
   // Simulate a device being disconnected with a charger initially.
   power_manager::PowerSupplyProperties proto;
   proto.set_battery_state(
@@ -194,7 +204,10 @@
   PowerStatus::Get()->SetProtoForTesting(proto);
   // Lock screen to start ambient mode.
   LockScreen();
+  FastForwardToInactivity();
+  FastForwardToNextImage();
 
+  EXPECT_TRUE(ambient_controller()->IsShown());
   // Should not acquire wake lock when device is not charging.
   EXPECT_EQ(0, GetNumOfActiveWakeLocks(
                    device::mojom::WakeLockType::kPreventDisplaySleep));
@@ -274,11 +287,21 @@
   EXPECT_FALSE(container_view());
 }
 
-TEST_F(AmbientControllerTest, UpdateUiAndWakeLockWhenSystemSuspendOrResume) {
-  // Flush the loop first to ensure the |PowerStatus| has picked up the initial
-  // status.
-  base::RunLoop().RunUntilIdle();
+TEST_F(AmbientControllerTest, ShouldDismissAndThenComesBack) {
+  LockScreen();
+  FastForwardToInactivity();
+  FastForwardToNextImage();
+  EXPECT_TRUE(container_view()->GetWidget()->IsVisible());
 
+  GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_1, ui::EF_NONE);
+  EXPECT_FALSE(container_view());
+
+  FastForwardToInactivity();
+  FastForwardToNextImage();
+  EXPECT_TRUE(container_view()->GetWidget()->IsVisible());
+}
+
+TEST_F(AmbientControllerTest, UpdateUiAndWakeLockWhenSystemSuspendOrResume) {
   // Simulate a device being connected with a charger initially to acquire a
   // wake lock upon shown.
   power_manager::PowerSupplyProperties proto;
@@ -312,11 +335,32 @@
                    device::mojom::WakeLockType::kPreventDisplaySleep));
 }
 
-TEST_F(AmbientControllerTest, ShouldShowAmbientScreenWhenScreenIsDimmed) {
+TEST_F(AmbientControllerTest,
+       ShouldShowAmbientScreenWithLockscreenWhenScreenIsDimmed) {
+  GetSessionControllerClient()->SetShouldLockScreenAutomatically(true);
   EXPECT_FALSE(ambient_controller()->IsShown());
 
   // Should lock the device and enter ambient mode when the screen is dimmed.
   SetScreenDimmedAndWait(true);
+  EXPECT_TRUE(IsLocked());
+  EXPECT_FALSE(ambient_controller()->IsShown());
+
+  FastForwardToInactivity();
+  FastForwardToNextImage();
+  EXPECT_TRUE(ambient_controller()->IsShown());
+
+  // Closes ambient for clean-up.
+  UnlockScreen();
+  EXPECT_FALSE(ambient_controller()->IsShown());
+}
+
+TEST_F(AmbientControllerTest, ShouldShowAmbientScreenWhenScreenIsDimmed) {
+  GetSessionControllerClient()->SetShouldLockScreenAutomatically(false);
+  EXPECT_FALSE(ambient_controller()->IsShown());
+
+  // Should lock the device and enter ambient mode when the screen is dimmed.
+  SetScreenDimmedAndWait(true);
+  EXPECT_FALSE(IsLocked());
 
   FastForwardToNextImage();
   EXPECT_TRUE(ambient_controller()->IsShown());
diff --git a/ash/ambient/test/ambient_ash_test_base.cc b/ash/ambient/test/ambient_ash_test_base.cc
index 181aa21..c9c2883 100644
--- a/ash/ambient/test/ambient_ash_test_base.cc
+++ b/ash/ambient/test/ambient_ash_test_base.cc
@@ -98,6 +98,7 @@
       std::make_unique<TestAmbientURLLoaderImpl>());
   photo_controller()->set_image_decoder_for_testing(
       std::make_unique<TestAmbientImageDecoderImpl>());
+  base::RunLoop().RunUntilIdle();
 }
 
 void AmbientAshTestBase::TearDown() {
@@ -109,7 +110,7 @@
 
 void AmbientAshTestBase::ShowAmbientScreen() {
   // The widget will be destroyed in |AshTestBase::TearDown()|.
-  ambient_controller()->ShowUi(AmbientUiMode::kLockScreenUi);
+  ambient_controller()->ShowUi(AmbientUiMode::kInSessionUi);
   // The UI only shows when images are downloaded to avoid showing blank screen.
   FastForwardToNextImage();
   // Flush the message loop to finish all async calls.
@@ -133,6 +134,10 @@
   GetSessionControllerClient()->UnlockScreen();
 }
 
+bool AmbientAshTestBase::IsLocked() {
+  return Shell::Get()->session_controller()->IsScreenLocked();
+}
+
 void AmbientAshTestBase::SimulateSystemSuspendAndWait(
     power_manager::SuspendImminent::Reason reason) {
   chromeos::FakePowerManagerClient::Get()->SendSuspendImminent(reason);
@@ -167,6 +172,11 @@
       AssistantViewID::kAmbientBackgroundImageView));
 }
 
+void AmbientAshTestBase::FastForwardToInactivity() {
+  task_environment()->FastForwardBy(
+      2 * AmbientController::kAutoShowWaitTimeInterval);
+}
+
 void AmbientAshTestBase::FastForwardToNextImage() {
   task_environment()->FastForwardBy(1.2 * kPhotoRefreshInterval);
 }
diff --git a/ash/ambient/test/ambient_ash_test_base.h b/ash/ambient/test/ambient_ash_test_base.h
index b8e7663..2e2be06 100644
--- a/ash/ambient/test/ambient_ash_test_base.h
+++ b/ash/ambient/test/ambient_ash_test_base.h
@@ -47,6 +47,8 @@
   // shown/closed.
   void LockScreen();
   void UnlockScreen();
+  // Whether lockscreen is shown.
+  bool IsLocked();
 
   // Simulates the system starting to suspend with Reason |reason|.
   // Wait until the event has been processed.
@@ -64,6 +66,9 @@
   // Set the size of the next image that will be loaded.
   void SetPhotoViewImageSize(int width, int height);
 
+  // Advance the task environment timer to expire the inactivity monitor.
+  void FastForwardToInactivity();
+
   // Advance the task environment timer to load the next photo.
   void FastForwardToNextImage();
 
diff --git a/ash/app_list/views/expand_arrow_view.cc b/ash/app_list/views/expand_arrow_view.cc
index 84517e7..9ac662d 100644
--- a/ash/app_list/views/expand_arrow_view.cc
+++ b/ash/app_list/views/expand_arrow_view.cc
@@ -323,15 +323,15 @@
     pulse_opacity_ =
         kPulseMinOpacity +
         (kPulseMaxOpacity - kPulseMinOpacity) *
-            (time - kPulseOpacityShowBeginTime) /
-            (kPulseOpacityShowEndTime - kPulseOpacityShowBeginTime);
+            (time - kPulseOpacityShowBeginTime)
+                .IntDiv(kPulseOpacityShowEndTime - kPulseOpacityShowBeginTime);
   } else if (time > kPulseOpacityHideBeginTime &&
              time <= kPulseOpacityHideEndTime) {
     pulse_opacity_ =
         kPulseMaxOpacity -
         (kPulseMaxOpacity - kPulseMinOpacity) *
-            (time - kPulseOpacityHideBeginTime) /
-            (kPulseOpacityHideEndTime - kPulseOpacityHideBeginTime);
+            (time - kPulseOpacityHideBeginTime)
+                .IntDiv(kPulseOpacityHideEndTime - kPulseOpacityHideBeginTime);
   }
 
   // Update pulse radius.
diff --git a/ash/metrics/demo_session_metrics_recorder.cc b/ash/metrics/demo_session_metrics_recorder.cc
index d4f7bf82..9f65d2c 100644
--- a/ash/metrics/demo_session_metrics_recorder.cc
+++ b/ash/metrics/demo_session_metrics_recorder.cc
@@ -42,7 +42,7 @@
 // recorded samples for a full minute while the device is in between uses, we
 // would bias our measurements toward whatever app was used last.
 constexpr int kMaxPeriodsWithoutActivity =
-    base::TimeDelta::FromSeconds(15) / kSamplePeriod;
+    base::TimeDelta::FromSeconds(15).IntDiv(kSamplePeriod);
 
 // Maps a Chrome app ID to a DemoModeApp value for metrics.
 DemoModeApp GetAppFromAppId(const std::string& app_id) {
diff --git a/ash/session/test_session_controller_client.cc b/ash/session/test_session_controller_client.cc
index 9ccd1a20..00ee858 100644
--- a/ash/session/test_session_controller_client.cc
+++ b/ash/session/test_session_controller_client.cc
@@ -7,10 +7,12 @@
 #include <algorithm>
 #include <string>
 
+#include "ash/login/login_screen_controller.h"
 #include "ash/login_status.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/session/test_pref_service_provider.h"
 #include "ash/shell.h"
+#include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/run_loop.h"
@@ -196,6 +198,12 @@
 }
 
 void TestSessionControllerClient::RequestLockScreen() {
+  if (should_show_lock_screen_) {
+    // The lock screen can't be shown without a wallpaper.
+    Shell::Get()->wallpaper_controller()->ShowDefaultWallpaperForTesting();
+    Shell::Get()->login_screen_controller()->ShowLockScreen();
+  }
+
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(&TestSessionControllerClient::SetSessionState,
                                 weak_ptr_factory_.GetWeakPtr(),
diff --git a/ash/session/test_session_controller_client.h b/ash/session/test_session_controller_client.h
index 869d9c8..dc5527d 100644
--- a/ash/session/test_session_controller_client.h
+++ b/ash/session/test_session_controller_client.h
@@ -116,6 +116,13 @@
   PrefService* GetSigninScreenPrefService() override;
   PrefService* GetUserPrefService(const AccountId& account_id) override;
 
+  // By default `LockScreen()` only changes the session state but no UI views
+  // will be created.  If your tests requires the lock screen to be created,
+  // please set this to true.
+  void set_show_lock_screen_views(bool should_show) {
+    should_show_lock_screen_ = should_show;
+  }
+
  private:
   void DoSwitchUser(const AccountId& account_id, bool switch_user);
 
@@ -128,6 +135,8 @@
   bool use_lower_case_user_id_ = true;
   int request_sign_out_count_ = 0;
 
+  bool should_show_lock_screen_ = false;
+
   std::unique_ptr<views::Widget> multi_profile_login_widget_;
 
   base::WeakPtrFactory<TestSessionControllerClient> weak_ptr_factory_{this};
diff --git a/ash/system/message_center/notification_swipe_control_view.cc b/ash/system/message_center/notification_swipe_control_view.cc
index 203ae61..45e5d018 100644
--- a/ash/system/message_center/notification_swipe_control_view.cc
+++ b/ash/system/message_center/notification_swipe_control_view.cc
@@ -185,25 +185,17 @@
 void NotificationSwipeControlView::ButtonPressed(views::Button* sender,
                                                  const ui::Event& event) {
   DCHECK(sender);
-  std::string notification_id = message_view_->notification_id();
-  auto weak_this = weak_factory_.GetWeakPtr();
-
   if (sender == settings_button_) {
     message_view_->OnSettingsButtonPressed(event);
-    metrics_utils::LogSettingsShown(notification_id,
+    metrics_utils::LogSettingsShown(message_view_->notification_id(),
                                     /*is_slide_controls=*/true,
                                     /*is_popup=*/false);
   } else if (sender == snooze_button_) {
     message_view_->OnSnoozeButtonPressed(event);
-    metrics_utils::LogSnoozed(notification_id,
+    metrics_utils::LogSnoozed(message_view_->notification_id(),
                               /*is_slide_controls=*/true,
                               /*is_popup=*/false);
   }
-
-  // Button handlers of |message_view_| may have closed |this|.
-  if (!weak_this)
-    return;
-
   HideButtons();
 
   // Closing the swipe control is done in these button pressed handlers.
diff --git a/ash/system/message_center/notification_swipe_control_view.h b/ash/system/message_center/notification_swipe_control_view.h
index d78f06bc..84bb0bc 100644
--- a/ash/system/message_center/notification_swipe_control_view.h
+++ b/ash/system/message_center/notification_swipe_control_view.h
@@ -6,7 +6,7 @@
 #define ASH_SYSTEM_MESSAGE_CENTER_NOTIFICATION_SWIPE_CONTROL_VIEW_H_
 
 #include "ash/ash_export.h"
-#include "base/memory/weak_ptr.h"
+#include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -35,9 +35,6 @@
 
   explicit NotificationSwipeControlView(
       message_center::MessageView* message_view);
-  NotificationSwipeControlView(const NotificationSwipeControlView&) = delete;
-  NotificationSwipeControlView& operator=(const NotificationSwipeControlView&) =
-      delete;
   ~NotificationSwipeControlView() override;
 
   // views::View
@@ -53,11 +50,6 @@
   void UpdateCornerRadius(int top_radius, int bottom_radius);
 
  private:
-  FRIEND_TEST_ALL_PREFIXES(NotificationSwipeControlViewTest,
-                           DeleteOnSettingsButtonPressed);
-  FRIEND_TEST_ALL_PREFIXES(NotificationSwipeControlViewTest,
-                           DeleteOnSnoozeButtonPressed);
-
   // Change the visibility of the settings button.
   void ShowButtons(ButtonPosition button_position,
                    bool has_settings,
@@ -76,7 +68,7 @@
   views::ImageButton* settings_button_ = nullptr;
   views::ImageButton* snooze_button_ = nullptr;
 
-  base::WeakPtrFactory<NotificationSwipeControlView> weak_factory_{this};
+  DISALLOW_COPY_AND_ASSIGN(NotificationSwipeControlView);
 };
 
 }  // namespace ash
diff --git a/ash/system/message_center/notification_swipe_control_view_unittest.cc b/ash/system/message_center/notification_swipe_control_view_unittest.cc
deleted file mode 100644
index 813b7aa8..0000000
--- a/ash/system/message_center/notification_swipe_control_view_unittest.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2020 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 "ash/system/message_center/notification_swipe_control_view.h"
-
-#include <memory>
-
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/base_event_utils.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/image/image.h"
-#include "ui/message_center/lock_screen/fake_lock_screen_controller.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/public/cpp/notification.h"
-#include "ui/message_center/views/message_view.h"
-#include "ui/message_center/views/notification_control_buttons_view.h"
-#include "url/gurl.h"
-
-namespace {
-
-class MockMessageView : public message_center::MessageView {
- public:
-  explicit MockMessageView(const message_center::Notification& notification)
-      : message_center::MessageView(notification),
-        buttons_view_(
-            std::make_unique<message_center::NotificationControlButtonsView>(
-                this)) {
-    buttons_view_->ShowSettingsButton(
-        notification.should_show_settings_button());
-    buttons_view_->ShowSnoozeButton(notification.should_show_snooze_button());
-  }
-  ~MockMessageView() override = default;
-
-  message_center::NotificationControlButtonsView* GetControlButtonsView()
-      const override {
-    return buttons_view_.get();
-  }
-
-  MOCK_METHOD(void,
-              OnSettingsButtonPressed,
-              (const ui::Event& event),
-              (override));
-  MOCK_METHOD(void,
-              OnSnoozeButtonPressed,
-              (const ui::Event& event),
-              (override));
-
- private:
-  std::unique_ptr<message_center::NotificationControlButtonsView> buttons_view_;
-};
-
-}  // namespace
-
-namespace ash {
-
-class NotificationSwipeControlViewTest : public testing::Test {
- public:
-  NotificationSwipeControlViewTest() = default;
-  ~NotificationSwipeControlViewTest() override = default;
-
-  void SetUp() override {
-    message_center::MessageCenter::Initialize(
-        std::make_unique<message_center::FakeLockScreenController>());
-
-    message_center::RichNotificationData rich_data;
-    rich_data.settings_button_handler =
-        message_center::SettingsButtonHandler::DELEGATE;
-    rich_data.should_show_snooze_button = true;
-    message_center::Notification notification(
-        message_center::NOTIFICATION_TYPE_SIMPLE, "id",
-        base::UTF8ToUTF16("title"), base::UTF8ToUTF16("id"), gfx::Image(),
-        base::string16(), GURL(),
-        message_center::NotifierId(message_center::NotifierType::APPLICATION,
-                                   "notifier_id"),
-        rich_data, nullptr);
-
-    message_view_ = std::make_unique<MockMessageView>(notification);
-  }
-
-  void TearDown() override { message_center::MessageCenter::Shutdown(); }
-
- protected:
-  MockMessageView* message_view() { return message_view_.get(); }
-
- private:
-  std::unique_ptr<MockMessageView> message_view_;
-};
-
-TEST_F(NotificationSwipeControlViewTest, DeleteOnSettingsButtonPressed) {
-  auto swipe_control_view =
-      std::make_unique<NotificationSwipeControlView>(message_view());
-
-  EXPECT_CALL(*message_view(), OnSettingsButtonPressed(testing::_))
-      .WillOnce(testing::DoDefault())
-      .WillOnce(
-          testing::InvokeWithoutArgs([&]() { swipe_control_view.reset(); }));
-
-  ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(),
-                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
-                       ui::EF_NONE);
-
-  // First click will do nothing, expect that to work.
-  swipe_control_view->ShowButtons(
-      NotificationSwipeControlView::ButtonPosition::LEFT,
-      /*has_settings_button=*/true, /*has_snooze_button=*/true);
-  swipe_control_view->ButtonPressed(swipe_control_view->settings_button_,
-                                    press);
-  EXPECT_TRUE(swipe_control_view);
-
-  // Second click deletes |swipe_control_view| in the handler.
-  swipe_control_view->ShowButtons(
-      NotificationSwipeControlView::ButtonPosition::LEFT,
-      /*has_settings_button=*/true, /*has_snooze_button=*/true);
-  swipe_control_view->ButtonPressed(swipe_control_view->settings_button_,
-                                    press);
-  EXPECT_FALSE(swipe_control_view);
-}
-
-TEST_F(NotificationSwipeControlViewTest, DeleteOnSnoozeButtonPressed) {
-  auto swipe_control_view =
-      std::make_unique<NotificationSwipeControlView>(message_view());
-
-  EXPECT_CALL(*message_view(), OnSnoozeButtonPressed(testing::_))
-      .WillOnce(testing::DoDefault())
-      .WillOnce(
-          testing::InvokeWithoutArgs([&]() { swipe_control_view.reset(); }));
-
-  ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::PointF(), gfx::PointF(),
-                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
-                       ui::EF_NONE);
-
-  // First click will do nothing, expect that to work.
-  swipe_control_view->ShowButtons(
-      NotificationSwipeControlView::ButtonPosition::LEFT,
-      /*has_settings_button=*/true, /*has_snooze_button=*/true);
-  swipe_control_view->ButtonPressed(swipe_control_view->snooze_button_, press);
-  EXPECT_TRUE(swipe_control_view);
-
-  // Second click deletes |swipe_control_view| in the handler.
-  swipe_control_view->ShowButtons(
-      NotificationSwipeControlView::ButtonPosition::LEFT,
-      /*has_settings_button=*/true, /*has_snooze_button=*/true);
-  swipe_control_view->ButtonPressed(swipe_control_view->snooze_button_, press);
-  EXPECT_FALSE(swipe_control_view);
-}
-
-}  // namespace ash
diff --git a/base/threading/scoped_blocking_call_internal.cc b/base/threading/scoped_blocking_call_internal.cc
index 7ee3d70..bdc5d4c 100644
--- a/base/threading/scoped_blocking_call_internal.cc
+++ b/base/threading/scoped_blocking_call_internal.cc
@@ -194,8 +194,10 @@
   if (call_end >= start_time_ + kMonitoringWindow)
     MonitorNextJankWindowIfNecessary(call_end);
 
-  const int jank_start_index = (call_start - start_time_) / kIOJankInterval;
-  const int num_janky_intervals = (call_end - call_start) / kIOJankInterval;
+  const int jank_start_index =
+      (call_start - start_time_).IntDiv(kIOJankInterval);
+  const int num_janky_intervals =
+      (call_end - call_start).IntDiv(kIOJankInterval);
 
   AddJank(jank_start_index, num_janky_intervals);
 }
diff --git a/base/threading/scoped_blocking_call_internal.h b/base/threading/scoped_blocking_call_internal.h
index 73ba4810..bb3d8e9 100644
--- a/base/threading/scoped_blocking_call_internal.h
+++ b/base/threading/scoped_blocking_call_internal.h
@@ -91,7 +91,8 @@
   static constexpr TimeDelta kIOJankInterval = TimeDelta::FromSeconds(1);
   static constexpr TimeDelta kMonitoringWindow = TimeDelta::FromMinutes(1);
   static constexpr TimeDelta kTimeDiscrepancyTimeout = kIOJankInterval * 10;
-  static constexpr int kNumIntervals = kMonitoringWindow / kIOJankInterval;
+  static constexpr int kNumIntervals =
+      kMonitoringWindow.IntDiv(kIOJankInterval);
 
  private:
   friend class base::RefCountedThreadSafe<IOJankMonitoringWindow>;
diff --git a/base/time/time.h b/base/time/time.h
index ca757df4..b7958b4 100644
--- a/base/time/time.h
+++ b/base/time/time.h
@@ -297,7 +297,8 @@
     return *this = (*this / a);
   }
 
-  constexpr int64_t operator/(TimeDelta a) const {
+  constexpr int64_t operator/(TimeDelta a) const = delete;
+  constexpr int64_t IntDiv(TimeDelta a) const {
     if (!is_inf() && !a.is_zero())
       return delta_ / a.delta_;
     return ((delta_ < 0) == (a.delta_ < 0))
diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc
index 166d3a47..3ed261e 100644
--- a/base/time/time_unittest.cc
+++ b/base/time/time_unittest.cc
@@ -1777,8 +1777,8 @@
                 "");
   static_assert(TimeDelta::FromSeconds(-8) == kThreeSeconds - kElevenSeconds,
                 "");
-  static_assert(3 == kElevenSeconds / kThreeSeconds, "");
-  static_assert(0 == kThreeSeconds / kElevenSeconds, "");
+  static_assert(3 == kElevenSeconds.IntDiv(kThreeSeconds), "");
+  static_assert(0 == kThreeSeconds.IntDiv(kElevenSeconds), "");
   static_assert(TimeDelta::FromSeconds(2) == kElevenSeconds % kThreeSeconds,
                 "");
 }
@@ -1814,16 +1814,16 @@
   EXPECT_TRUE((kLargeDelta / 0.5).is_max());
   EXPECT_TRUE((kLargeDelta / -0.5).is_min());
 
-  static_assert(TimeDelta::Max() / TimeDelta::FromSeconds(10) ==
+  static_assert(TimeDelta::Max().IntDiv(TimeDelta::FromSeconds(10)) ==
                     std::numeric_limits<int64_t>::max(),
                 "");
-  static_assert(TimeDelta::Max() / TimeDelta::FromSeconds(-10) ==
+  static_assert(TimeDelta::Max().IntDiv(TimeDelta::FromSeconds(-10)) ==
                     std::numeric_limits<int64_t>::min(),
                 "");
-  static_assert(TimeDelta::Min() / TimeDelta::FromSeconds(10) ==
+  static_assert(TimeDelta::Min().IntDiv(TimeDelta::FromSeconds(10)) ==
                     std::numeric_limits<int64_t>::min(),
                 "");
-  static_assert(TimeDelta::Min() / TimeDelta::FromSeconds(-10) ==
+  static_assert(TimeDelta::Min().IntDiv(TimeDelta::FromSeconds(-10)) ==
                     std::numeric_limits<int64_t>::max(),
                 "");
 
@@ -1833,36 +1833,37 @@
   static_assert((TimeDelta::FromSeconds(-1) / 0).is_min(), "");
   static_assert((TimeDelta::Max() / 0).is_max(), "");
   static_assert((TimeDelta::Min() / 0).is_min(), "");
-  static_assert(TimeDelta::FromSeconds(1) / TimeDelta() ==
+  static_assert(TimeDelta::FromSeconds(1).IntDiv(TimeDelta()) ==
                     std::numeric_limits<int64_t>::max(),
                 "");
   static_assert(
-      TimeDelta() / TimeDelta() == std::numeric_limits<int64_t>::max(), "");
-  static_assert(TimeDelta::FromSeconds(-1) / TimeDelta() ==
+      TimeDelta().IntDiv(TimeDelta()) == std::numeric_limits<int64_t>::max(),
+      "");
+  static_assert(TimeDelta::FromSeconds(-1).IntDiv(TimeDelta()) ==
                     std::numeric_limits<int64_t>::min(),
                 "");
-  static_assert(
-      TimeDelta::Max() / TimeDelta() == std::numeric_limits<int64_t>::max(),
-      "");
-  static_assert(
-      TimeDelta::Min() / TimeDelta() == std::numeric_limits<int64_t>::min(),
-      "");
+  static_assert(TimeDelta::Max().IntDiv(TimeDelta()) ==
+                    std::numeric_limits<int64_t>::max(),
+                "");
+  static_assert(TimeDelta::Min().IntDiv(TimeDelta()) ==
+                    std::numeric_limits<int64_t>::min(),
+                "");
 
   // Division by infinity.
-  static_assert(kLargeDelta / TimeDelta::Min() == 0, "");
-  static_assert(kLargeDelta / TimeDelta::Max() == 0, "");
-  static_assert(kLargeNegative / TimeDelta::Min() == 0, "");
-  static_assert(kLargeNegative / TimeDelta::Max() == 0, "");
-  static_assert(TimeDelta::Min() / TimeDelta::Min() ==
+  static_assert(kLargeDelta.IntDiv(TimeDelta::Min()) == 0, "");
+  static_assert(kLargeDelta.IntDiv(TimeDelta::Max()) == 0, "");
+  static_assert(kLargeNegative.IntDiv(TimeDelta::Min()) == 0, "");
+  static_assert(kLargeNegative.IntDiv(TimeDelta::Max()) == 0, "");
+  static_assert(TimeDelta::Min().IntDiv(TimeDelta::Min()) ==
                     std::numeric_limits<int64_t>::max(),
                 "");
-  static_assert(TimeDelta::Min() / TimeDelta::Max() ==
+  static_assert(TimeDelta::Min().IntDiv(TimeDelta::Max()) ==
                     std::numeric_limits<int64_t>::min(),
                 "");
-  static_assert(TimeDelta::Max() / TimeDelta::Min() ==
+  static_assert(TimeDelta::Max().IntDiv(TimeDelta::Min()) ==
                     std::numeric_limits<int64_t>::min(),
                 "");
-  static_assert(TimeDelta::Max() / TimeDelta::Max() ==
+  static_assert(TimeDelta::Max().IntDiv(TimeDelta::Max()) ==
                     std::numeric_limits<int64_t>::max(),
                 "");
 
diff --git a/build/fuchsia/emu_target.py b/build/fuchsia/emu_target.py
index 5ba68fe8..e6ef52d 100644
--- a/build/fuchsia/emu_target.py
+++ b/build/fuchsia/emu_target.py
@@ -66,6 +66,10 @@
       temporary_log_file = tempfile.NamedTemporaryFile('w')
       stdout = temporary_log_file
 
+    # TODO(crbug.com/1100402): Delete when no longer needed for debug info.
+    # Log system statistics at the start of the emulator run.
+    _LogSystemStatistics('system_start_statistics_log')
+
     self._emu_process = subprocess.Popen(emu_command,
                                          stdin=open(os.devnull),
                                          stdout=stdout,
@@ -104,6 +108,11 @@
       logging.error('%s quit unexpectedly with exit code %d' %
                     (self._GetEmulatorName(), returncode))
 
+    # TODO(crbug.com/1100402): Delete when no longer needed for debug info.
+    # Log system statistics at the end of the emulator run.
+    _LogSystemStatistics('system_end_statistics_log')
+
+
   def _IsEmuStillRunning(self):
     if not self._emu_process:
       return False
@@ -116,3 +125,12 @@
 
   def _GetSshConfigPath(self):
     return boot_data.GetSSHConfigPath(self._output_dir)
+
+
+# TODO(crbug.com/1100402): Delete when no longer needed for debug info.
+def _LogSystemStatistics(log_file_name):
+  # Log the cpu load and process information.
+  subprocess.call(['top', '-b', '-n', '1'],
+                  stdin=open(os.devnull),
+                  stdout=runner_logs.FileStreamFor(log_file_name),
+                  stderr=subprocess.STDOUT)
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 32172f8..4d4f86cd 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20200731.2.1
+0.20200801.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 32172f8..565edda 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20200731.2.1
+0.20200801.1.1
diff --git a/build/fuchsia/runner_logs.py b/build/fuchsia/runner_logs.py
index 19da4f5a..20ab6b2 100644
--- a/build/fuchsia/runner_logs.py
+++ b/build/fuchsia/runner_logs.py
@@ -35,7 +35,7 @@
     self._build_ids_files = build_ids_files
     self._runner_logs = []
 
-    if self._log_dir:
+    if self._log_dir and not os.path.isdir(self._log_dir):
       os.makedirs(self._log_dir)
 
     _instance = self
@@ -54,7 +54,7 @@
 
   def _FileStreamFor(self, name, symbolize):
     if any(elem.name == name for elem in self._runner_logs):
-      raise Exception('RunnerLogManager can only open "%" once' % name)
+      raise Exception('RunnerLogManager can only open "%s" once' % name)
 
     path = os.path.join(self._log_dir, name) if self._log_dir else os.devnull
     log_file = open(path, 'w')
diff --git a/cc/animation/keyframe_model.cc b/cc/animation/keyframe_model.cc
index 9c47d989..7006f23a 100644
--- a/cc/animation/keyframe_model.cc
+++ b/cc/animation/keyframe_model.cc
@@ -317,7 +317,7 @@
   else if (iteration_time == curve_->Duration())
     iteration = ceil(iteration_start_ + iterations_ - 1);
   else
-    iteration = static_cast<int>(scaled_active_time / curve_->Duration());
+    iteration = static_cast<int>(scaled_active_time.IntDiv(curve_->Duration()));
 
   // Check if we are running the keyframe model in reverse direction for the
   // current iteration
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 7b74ae2..8ca906a4 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -962,7 +962,6 @@
   if (inputs.scroll_offset == scroll_offset)
     return;
   inputs.scroll_offset = scroll_offset;
-  SetNeedsPushProperties();
 
   UpdatePropertyTreeScrollOffset();
 
diff --git a/cc/metrics/frame_sequence_tracker.cc b/cc/metrics/frame_sequence_tracker.cc
index 47f6f0a..f9010338 100644
--- a/cc/metrics/frame_sequence_tracker.cc
+++ b/cc/metrics/frame_sequence_tracker.cc
@@ -525,7 +525,7 @@
                                  : feedback.interval;
       DCHECK(!interval.is_zero()) << TRACKER_DCHECK_MSG;
       constexpr base::TimeDelta kEpsilon = base::TimeDelta::FromMilliseconds(1);
-      int64_t frames = (difference + kEpsilon) / interval;
+      int64_t frames = (difference + kEpsilon).IntDiv(interval);
       metrics_->add_checkerboarded_frames(frames);
     }
 
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 00bad6f..e9c7fd33 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -937,15 +937,11 @@
       // This update closely follows
       // blink::PropertyTreeManager::DirectlyUpdateScrollOffsetTransform.
 
-      // Update the offset in the scroll tree.
-      if (scroll_tree.SetScrollOffset(id, new_offset)) {
-        // Scroll offset animations are clobbered via |Layer::PushPropertiesTo|.
-        // TODO(pdr): This follows the pattern of |SetScrollOffsetFromImplSide|
-        // and PropertyTreeManager::DirectlyUpdateScrollOffsetTransform but do
-        // we need to clobber scroll animations as a result of impl scrolls?
-        if (auto* layer = LayerByElementId(id))
-          layer->SetNeedsPushProperties();
-      }
+      scroll_tree.SetScrollOffset(id, new_offset);
+      // |blink::PropertyTreeManager::DirectlySetScrollOffset| (called from
+      // |blink::PropertyTreeManager::DirectlyUpdateScrollOffsetTransform|)
+      // marks the layer as needing to push properties in order to clobber
+      // animations, but that is not needed for an impl-side scroll.
 
       // Update the offset in the transform node.
       DCHECK(scroll_node->transform_id != TransformTree::kInvalidNodeId);
diff --git a/chrome/VERSION b/chrome/VERSION
index 97a0bbbf..810e02f86 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=86
 MINOR=0
-BUILD=4219
+BUILD=4220
 PATCH=0
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java
index 9a60dcdb..efc7085 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java
@@ -72,6 +72,22 @@
                 "webxr_test_basic_hittest", PAGE_LOAD_TIMEOUT_S);
         mWebXrArTestFramework.enterSessionWithUserGestureOrFail();
         mWebXrArTestFramework.executeStepAndWait("stepStartHitTesting()");
-        mWebXrArTestFramework.assertNoJavaScriptErrors();
+        mWebXrArTestFramework.endTest();
+    }
+
+    /**
+     * Tests that hit test results are available in the subsequent frame after hit
+     * test source was returned.
+     */
+    @Test
+    @MediumTest
+    @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
+    @ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
+    public void testHitTestResultsAvailableInSubsequentFrame() {
+        mWebXrArTestFramework.loadFileAndAwaitInitialization(
+                "webxr_test_basic_hittest_results_availability", PAGE_LOAD_TIMEOUT_S);
+        mWebXrArTestFramework.enterSessionWithUserGestureOrFail();
+        mWebXrArTestFramework.executeStepAndWait("stepStartHitTesting()");
+        mWebXrArTestFramework.endTest();
     }
 }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index a85cffc..84f0a6b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1309,8 +1309,6 @@
     "prerender/prerender_processor_impl.h",
     "prerender/prerender_tab_helper.cc",
     "prerender/prerender_tab_helper.h",
-    "prerender/prerender_util.cc",
-    "prerender/prerender_util.h",
     "previews/previews_content_util.cc",
     "previews/previews_content_util.h",
     "previews/previews_https_notification_infobar_decider.cc",
diff --git a/chrome/browser/chromeos/arc/app_shortcuts/OWNERS b/chrome/browser/chromeos/arc/app_shortcuts/OWNERS
index eb939e5..d6544a4 100644
--- a/chrome/browser/chromeos/arc/app_shortcuts/OWNERS
+++ b/chrome/browser/chromeos/arc/app_shortcuts/OWNERS
@@ -1 +1,2 @@
 khmel@chromium.org
+lgcheng@google.com
diff --git a/chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing_session.cc b/chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing_session.cc
index b382cf5..4204bf1 100644
--- a/chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing_session.cc
+++ b/chrome/browser/chromeos/arc/tracing/arc_app_performance_tracing_session.cc
@@ -132,7 +132,7 @@
 
   if (detect_idles_) {
     const uint64_t display_frames_passed =
-        (frame_delta + kTargetFrameTime / 2) / kTargetFrameTime;
+        (frame_delta + kTargetFrameTime / 2).IntDiv(kTargetFrameTime);
     if (display_frames_passed >= kIdleThresholdFrames) {
       // Idle is detected, try the next time.
       Stop();
@@ -174,7 +174,7 @@
     // fractional part of target frame interval |kTargetFrameTime| and is less
     // or equal half of it.
     const uint64_t display_frames_passed =
-        (frame_delta + kTargetFrameTime / 2) / kTargetFrameTime;
+        (frame_delta + kTargetFrameTime / 2).IntDiv(kTargetFrameTime);
     // Calculate difference from the ideal commit time, that should happen with
     // equal delay for each display frame.
     const base::TimeDelta vsync_error =
diff --git a/chrome/browser/chromeos/child_accounts/parent_access_code/authenticator_unittest.cc b/chrome/browser/chromeos/child_accounts/parent_access_code/authenticator_unittest.cc
index ed01882..12768dff 100644
--- a/chrome/browser/chromeos/child_accounts/parent_access_code/authenticator_unittest.cc
+++ b/chrome/browser/chromeos/child_accounts/parent_access_code/authenticator_unittest.cc
@@ -63,7 +63,8 @@
   ASSERT_NO_FATAL_FAILURE(Verify(first_code, timestamp));
 
   int range =
-      (config.code_validity() / Authenticator::kAccessCodeGranularity) - 1;
+      (config.code_validity().IntDiv(Authenticator::kAccessCodeGranularity)) -
+      1;
   for (int i = 0; i < range; ++i) {
     timestamp += Authenticator::kAccessCodeGranularity;
     base::Optional<AccessCode> code = gen.Generate(timestamp);
@@ -208,7 +209,8 @@
   EXPECT_FALSE(validated_code);
 
   // In valid period.
-  int range = config.code_validity() / Authenticator::kAccessCodeGranularity;
+  int range =
+      config.code_validity().IntDiv(Authenticator::kAccessCodeGranularity);
   for (int i = 0; i < range; ++i) {
     validated_code = validator.Validate(
         generated_code->code(),
@@ -245,7 +247,8 @@
   EXPECT_FALSE(validated_code);
 
   // In valid period.
-  int range = config.code_validity() / Authenticator::kAccessCodeGranularity;
+  int range =
+      config.code_validity().IntDiv(Authenticator::kAccessCodeGranularity);
   for (int i = 0; i < range; ++i) {
     validated_code = authenticator.Validate(
         generated_code->code(),
@@ -279,7 +282,8 @@
   ASSERT_NO_FATAL_FAILURE(Verify(generated_code, generation_timestamp));
 
   // Both validators accept the code in valid period.
-  int range = kDefaultCodeValidity / Authenticator::kAccessCodeGranularity;
+  int range =
+      kDefaultCodeValidity.IntDiv(Authenticator::kAccessCodeGranularity);
   base::Time timestamp;
   base::Optional<AccessCode> validated_code_no_tolerance;
   base::Optional<AccessCode> validated_code_with_tolerance;
diff --git a/chrome/browser/chromeos/power/ml/recent_events_counter.cc b/chrome/browser/chromeos/power/ml/recent_events_counter.cc
index 8f4fa61..06764295 100644
--- a/chrome/browser/chromeos/power/ml/recent_events_counter.cc
+++ b/chrome/browser/chromeos/power/ml/recent_events_counter.cc
@@ -83,7 +83,7 @@
 int RecentEventsCounter::GetBucketIndex(base::TimeDelta timestamp) const {
   DCHECK_GE(timestamp, base::TimeDelta());
 
-  int index = (timestamp % duration_) / bucket_duration_;
+  int index = (timestamp % duration_).IntDiv(bucket_duration_);
   DCHECK_GE(index, 0);
   DCHECK_LT(index, num_buckets_);
   return index;
diff --git a/chrome/browser/net/cert_verify_proc_browsertest.cc b/chrome/browser/net/cert_verify_proc_browsertest.cc
index 479b23a..93ec5fbe 100644
--- a/chrome/browser/net/cert_verify_proc_browsertest.cc
+++ b/chrome/browser/net/cert_verify_proc_browsertest.cc
@@ -43,7 +43,7 @@
     // Try for up to 5 seconds to read the netlog file.
     constexpr auto kMaxWaitTime = base::TimeDelta::FromSeconds(5);
     constexpr auto kWaitInterval = base::TimeDelta::FromMilliseconds(50);
-    int tries_left = kMaxWaitTime / kWaitInterval;
+    int tries_left = kMaxWaitTime.IntDiv(kWaitInterval);
 
     base::Optional<base::Value> parsed_net_log;
     while (true) {
diff --git a/chrome/browser/prerender/chrome_prerender_manager_delegate.cc b/chrome/browser/prerender/chrome_prerender_manager_delegate.cc
index d82be0d..6dcaf67 100644
--- a/chrome/browser/prerender/chrome_prerender_manager_delegate.cc
+++ b/chrome/browser/prerender/chrome_prerender_manager_delegate.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/predictors/loading_predictor.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
+#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h"
 #include "chrome/browser/prerender/prerender_manager_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/tab_contents/tab_util.h"
@@ -47,4 +48,8 @@
   }
 }
 
+std::unique_ptr<PrerenderContentsDelegate>
+ChromePrerenderManagerDelegate::GetPrerenderContentsDelegate() {
+  return std::make_unique<ChromePrerenderContentsDelegate>();
+}
 }  // namespace prerender
diff --git a/chrome/browser/prerender/chrome_prerender_manager_delegate.h b/chrome/browser/prerender/chrome_prerender_manager_delegate.h
index cfd4437..a0114f2 100644
--- a/chrome/browser/prerender/chrome_prerender_manager_delegate.h
+++ b/chrome/browser/prerender/chrome_prerender_manager_delegate.h
@@ -23,6 +23,8 @@
   // PrerenderManagerDelegate overrides.
   scoped_refptr<content_settings::CookieSettings> GetCookieSettings() override;
   void MaybePreconnect(const GURL& url) override;
+  std::unique_ptr<PrerenderContentsDelegate> GetPrerenderContentsDelegate()
+      override;
 
  private:
   Profile* profile_;
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc
index 525dccc9..235dea3 100644
--- a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc
+++ b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc
@@ -840,6 +840,8 @@
   // before the end of the method if the handle is not created.
   IsolatedPrerenderSubresourceManager* manager =
       service->OnAboutToNoStatePrefetch(url, CopyPrefetchResponseForNSP(url));
+  DCHECK_EQ(manager, service->GetSubresourceManagerForURL(url));
+
   manager->SetCreateIsolatedLoaderFactoryCallback(base::BindRepeating(
       &IsolatedPrerenderTabHelper::CreateNewURLLoaderFactory,
       weak_factory_.GetWeakPtr()));
@@ -866,12 +868,28 @@
     return;
   }
 
+  page_->number_of_no_state_prefetch_attempts_++;
+
+  // It is possible for the manager to be destroyed during the NoStatePrefetch
+  // navigation. If this happens, abort the NSP and try again.
+  manager = service->GetSubresourceManagerForURL(url);
+  if (!manager) {
+    handle->OnCancel();
+    handle.reset();
+
+    page_->failed_no_state_prefetch_urls_.push_back(url);
+
+    // Try the next URL.
+    page_->urls_to_no_state_prefetch_.erase(
+        page_->urls_to_no_state_prefetch_.begin());
+    DoNoStatePrefetch();
+    return;
+  }
+
   manager->ManageNoStatePrefetch(
       std::move(handle),
       base::BindOnce(&IsolatedPrerenderTabHelper::OnPrerenderDone,
                      weak_factory_.GetWeakPtr(), url));
-
-  page_->number_of_no_state_prefetch_attempts_++;
 }
 
 void IsolatedPrerenderTabHelper::OnPrerenderDone(const GURL& url) {
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index e5c55ba0..806b345 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -34,17 +34,16 @@
 #include "chrome/browser/net/prediction_options.h"
 #include "chrome/browser/predictors/loading_predictor.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
-#include "chrome/browser/prerender/chrome_prerender_contents_delegate.h"
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_field_trial.h"
 #include "chrome/browser/prerender/prerender_handle.h"
 #include "chrome/browser/prerender/prerender_manager_delegate.h"
 #include "chrome/browser/prerender/prerender_tab_helper.h"
-#include "chrome/browser/prerender/prerender_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/prerender/browser/prerender_histograms.h"
 #include "components/prerender/browser/prerender_history.h"
+#include "components/prerender/browser/prerender_util.h"
 #include "components/prerender/common/prerender_final_status.h"
 #include "components/prerender/common/prerender_types.mojom.h"
 #include "content/public/browser/browser_thread.h"
@@ -795,8 +794,8 @@
     Origin origin) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents(
-      std::make_unique<ChromePrerenderContentsDelegate>(), this, profile_, url,
-      referrer, initiator_origin, origin));
+      delegate_->GetPrerenderContentsDelegate(), this, profile_, url, referrer,
+      initiator_origin, origin));
 }
 
 void PrerenderManager::SortActivePrerenders() {
diff --git a/chrome/browser/prerender/prerender_manager_delegate.h b/chrome/browser/prerender/prerender_manager_delegate.h
index bdd33de..e11c0d5 100644
--- a/chrome/browser/prerender/prerender_manager_delegate.h
+++ b/chrome/browser/prerender/prerender_manager_delegate.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_DELEGATE_H_
 
 #include "base/memory/scoped_refptr.h"
+#include "chrome/browser/prerender/prerender_contents_delegate.h"
 #include "url/gurl.h"
 
 namespace content_settings {
@@ -26,6 +27,10 @@
 
   // Perform preconnect, if feasible.
   virtual void MaybePreconnect(const GURL& url) = 0;
+
+  // Get the prerender contents delegate.
+  virtual std::unique_ptr<PrerenderContentsDelegate>
+  GetPrerenderContentsDelegate() = 0;
 };
 
 }  // namespace prerender
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html
index 5ef4718..6dd8bcf 100644
--- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html
+++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html
@@ -210,7 +210,7 @@
   </button>
 
   <button id="show-annotations-button"
-      class="dropdown-item" on-click="onShowAnnotationsClick_">
+      class="dropdown-item" on-click="toggleDisplayAnnotations_">
     <span class="check-container">
       <iron-icon icon="pdf:check" hidden="[[!displayAnnotations_]]"></iron-icon>
     </span>
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js
index 2d1e3bd..95e8c5c 100644
--- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js
+++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js
@@ -169,10 +169,16 @@
   }
 
   /** @private */
-  onShowAnnotationsClick_() {
+  toggleDisplayAnnotations_() {
     this.displayAnnotations_ = !this.displayAnnotations_;
     this.dispatchEvent(new CustomEvent(
         'display-annotations-changed', {detail: this.displayAnnotations_}));
+
+    // <if expr="chromeos">
+    if (!this.displayAnnotations_ && this.annotationMode) {
+      this.toggleAnnotation();
+    }
+    // </if>
   }
 
   /** @private */
@@ -283,6 +289,10 @@
     this.annotationMode = !this.annotationMode;
     this.dispatchEvent(new CustomEvent(
         'annotation-mode-toggled', {detail: this.annotationMode}));
+
+    if (this.annotationMode && !this.displayAnnotations_) {
+      this.toggleDisplayAnnotations_();
+    }
   }
   // </if>
 }
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index cbe594d..798c5bfa 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -266,8 +266,8 @@
     #"os_apps_page/app_management_page/plugin_vm_page:closure_compile_module",
     #"os_files_page:closure_compile_module",
     "os_languages_page:closure_compile_module",
-
-    #"os_people_page:closure_compile_module",
+    "os_people_page:closure_compile_module",
+    
     #"os_printing_page:closure_compile_module",
     #"os_privacy_page:closure_compile_module",
     "os_reset_page:closure_compile_module",
@@ -291,7 +291,7 @@
     ":metrics_recorder.m",
 
     #  ":os_icons.m",
-    #  ":os_page_visibility.m",
+    ":os_page_visibility.m",
     ":os_route.m",
 
     #  ":os_settings.m",
@@ -333,10 +333,8 @@
 
 js_library("os_page_visibility.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/os_page_visibility.m.js" ]
-  deps = [
-    # TODO: Fill those in.
-  ]
-  extra_deps = [ ":os_page_visibility_module" ]
+  deps = [ "//ui/webui/resources/js:load_time_data.m" ]
+  extra_deps = [ ":modulize" ]
 }
 
 js_library("os_route.m") {
@@ -421,7 +419,6 @@
     # Local targets
     ":modulize",
     ":os_icons_module",
-    ":os_page_visibility_module",
     ":os_settings_icons_css_module",
 
     # Shared with browser settings
@@ -442,12 +439,6 @@
   html_type = "iron-iconset"
 }
 
-polymer_modulizer("os_page_visibility") {
-  js_file = "os_page_visibility.js"
-  html_file = "os_page_visibility.html"
-  html_type = "dom-module"
-}
-
 polymer_modulizer("os_settings_icons_css") {
   js_file = "os_settings_icons_css.m.js"
   html_file = "os_settings_icons_css.html"
@@ -461,6 +452,7 @@
     "route_origin_behavior.js",
     "search_handler.js",
     "os_route.js",
+    "os_page_visibility.js",
     "deep_linking_behavior.js",
   ]
   namespace_rewrites = os_settings_namespace_rewrites
diff --git a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js
index 7f2912d..62aa199 100644
--- a/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/bluetooth_page/bluetooth_subpage.js
@@ -195,6 +195,7 @@
   /**
    * Overridden from DeepLinkingBehavior.
    * @param {!chromeos.settings.mojom.Setting} settingId
+   * @return {boolean}
    */
   beforeDeepLinkAttempt(settingId) {
     // If lastFocused_ is an internal element of a Focus Row (such as the menu
@@ -209,6 +210,8 @@
         settingId == chromeos.settings.mojom.Setting.kBluetoothUnpairDevice) {
       this.lastFocused_ = null;
     }
+    // Should continue with deep link attempt.
+    return true;
   },
 
   /** @override */
diff --git a/chrome/browser/resources/settings/chromeos/deep_linking_behavior.js b/chrome/browser/resources/settings/chromeos/deep_linking_behavior.js
index bb17814..c27d121a 100644
--- a/chrome/browser/resources/settings/chromeos/deep_linking_behavior.js
+++ b/chrome/browser/resources/settings/chromeos/deep_linking_behavior.js
@@ -36,8 +36,8 @@
     },
 
     /**
-     * Set of settingIds that could be deep linked to. Initialized as an
-     * empty set, should be overridden with applicable settingIds.
+     * Set of setting IDs that could be deep linked to. Initialized as an
+     * empty set, should be overridden with applicable setting IDs.
      * @type {!Set<!chromeos.settings.mojom.Setting>}
      */
     supportedSettingIds: {
@@ -92,11 +92,14 @@
 
   /**
    * Override this method to execute code after a supported settingId is found
-   * and before the deep link is shown. Default behavior is no op.
+   * and before the deep link is shown. Returns whether or not the deep link
+   * attempt should continue. Default behavior is to no op and then return
+   * true, continuing the deep link attempt.
    * @param {!chromeos.settings.mojom.Setting} settingId
+   * @return {boolean}
    */
   beforeDeepLinkAttempt(settingId) {
-    return;
+    return true;
   },
 
   /**
@@ -109,13 +112,22 @@
    */
   attemptDeepLink() {
     const settingId = this.getDeepLinkSettingId();
-    if (settingId && this.supportedSettingIds.has(settingId)) {
-      this.beforeDeepLinkAttempt(settingId);
-      return this.showDeepLink(settingId);
+    // Explicitly check for null to handle settingId = 0.
+    if (settingId === null || !this.supportedSettingIds.has(settingId)) {
+      // No deep link was shown since the settingId was unsupported.
+      return new Promise(resolve => {
+        resolve({deepLinkShown: false, pendingSettingId: null});
+      });
     }
-    // No deep link was shown since the settingId was unsupported.
-    return new Promise(resolve => {
-      resolve({deepLinkShown: false, pendingSettingId: null});
-    });
+
+    const shouldContinue = this.beforeDeepLinkAttempt(settingId);
+    if (!shouldContinue) {
+      // Don't continue the deep link attempt since it was presumably
+      // handled manually in beforeDeepLinkAttempt().
+      return new Promise(resolve => {
+        resolve({deepLinkShown: false, pendingSettingId: settingId});
+      });
+    }
+    return this.showDeepLink(settingId);
   },
 };
diff --git a/chrome/browser/resources/settings/chromeos/os_page_visibility.js b/chrome/browser/resources/settings/chromeos/os_page_visibility.js
index 3a76b0d..b915b73 100644
--- a/chrome/browser/resources/settings/chromeos/os_page_visibility.js
+++ b/chrome/browser/resources/settings/chromeos/os_page_visibility.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+
 /**
  * Specifies page visibility based on incognito status and Chrome OS guest mode.
  * @typedef {{
@@ -23,7 +25,7 @@
  *   reset: (boolean|undefined),
  * }}
  */
-let OSPageVisibility;
+/* #export */ let OSPageVisibility;
 
 /**
  * @typedef {{
@@ -34,7 +36,7 @@
  *   setWallpaper: boolean,
  * }}
  */
-let OSAppearancePageVisibility;
+/* #export */ let OSAppearancePageVisibility;
 
 /**
  * @typedef {{
@@ -42,7 +44,7 @@
  *   smbShares: boolean,
  * }}
  */
-let DownloadsPageVisibility;
+/* #export */ let DownloadsPageVisibility;
 
 /**
  * @typedef {{
@@ -52,7 +54,7 @@
  *   manageUsers: boolean,
  * }}
  */
-let PeoplePageVisibility;
+/* #export */ let PeoplePageVisibility;
 
 /**
  * @typedef {{
@@ -62,7 +64,7 @@
  *   wakeOnWifi: boolean,
  * }}
  */
-let OSPrivacyPageVisibility;
+/* #export */ let OSPrivacyPageVisibility;
 
 /**
  * @typedef {{
@@ -70,14 +72,14 @@
  *   inputMethodsList: boolean,
  * }}
  */
-let LanguagesPageVisibility;
+/* #export */ let LanguagesPageVisibility;
 
 cr.define('settings', function() {
   /**
    * Dictionary defining page visibility.
    * @type {!OSPageVisibility}
    */
-  let osPageVisibility;
+  /* #export */ let osPageVisibility;
 
   const isAccountManagerEnabled =
       loadTimeData.valueExists('isAccountManagerEnabled') &&
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
index fe132c7..bd257f78 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
@@ -249,6 +249,7 @@
     "../localized_link:localized_link.m",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
     "//ui/webui/resources/js:i18n_behavior.m",
     "//ui/webui/resources/js:icon.m",
     "//ui/webui/resources/js:web_ui_listener_behavior.m",
@@ -500,12 +501,15 @@
     ":modulize",
     ":os_people_page_module",
     ":os_sync_controls_module",
+    ":pin_autosubmit_dialog_module",
     ":setup_fingerprint_dialog_module",
     ":setup_pin_dialog_module",
     ":user_list_module",
     ":users_add_user_dialog_module",
     ":users_page_module",
-    "../../people_page:modulize",
+    "../../people_page:polymer3_elements",
+    "../../privacy_page:polymer3_elements",
+    "../../:icons_module",
   ]
 }
 
@@ -641,4 +645,5 @@
     "lock_state_behavior.js",
     "os_sync_browser_proxy.js",
   ]
+  namespace_rewrites = os_settings_namespace_rewrites
 }
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js b/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js
index e0ca9ba7..cbb26dd 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.js
@@ -2,9 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-(function() {
-'use strict';
-
 /**
  * The duration in ms of a background flash when a user touches the fingerprint
  * sensor on this page.
@@ -117,7 +114,8 @@
    */
   onAttemptReceived_(fingerprintAttempt) {
     /** @type {NodeList<!HTMLElement>} */ const listItems =
-        this.$.fingerprintsList.querySelectorAll('.list-item');
+        /** @type {NodeList<!HTMLElement>} */
+        (this.$.fingerprintsList.querySelectorAll('.list-item'));
     /** @type {Array<number>} */ const filteredIndexes =
         fingerprintAttempt.indexes.filter(function(index) {
           return index >= 0 && index < listItems.length;
@@ -232,4 +230,3 @@
     return this.i18n('lockScreenDeleteFingerprintLabel', item);
   },
 });
-})();
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/kerberos_accounts.html b/chrome/browser/resources/settings/chromeos/os_people_page/kerberos_accounts.html
index 7c2ae9b..fd1dbd5 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/kerberos_accounts.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/kerberos_accounts.html
@@ -10,6 +10,7 @@
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="../../i18n_setup.html">
+<link rel="import" href="../../people_page/account_manager_browser_proxy.html">
 <link rel="import" href="../../router.html">
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="../metrics_recorder.html">
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen_password_prompt_dialog.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen_password_prompt_dialog.js
index c1f8ca4..c460a0d 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen_password_prompt_dialog.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen_password_prompt_dialog.js
@@ -16,10 +16,6 @@
  *   id="lockScreenPasswordPrompt"
  * </settings-lock-screen-password-prompt-dialog>
  */
-
-(function() {
-'use strict';
-
 Polymer({
   is: 'settings-lock-screen-password-prompt-dialog',
 
@@ -71,4 +67,3 @@
     return this.i18n('passwordPromptEnterPasswordLock');
   },
 });
-})();
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js b/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js
index 9ba6619..554207c3 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.js
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
+// #import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
+
 /**
  * @fileoverview
  * Contains utilities that help identify the current way that the lock screen
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
index cf26cb29..ba1e35e 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
@@ -13,18 +14,20 @@
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="../../controls/settings_toggle_button.html">
-<link rel="import" href="../parental_controls_page/parental_controls_page.html">
 <link rel="import" href="../../people_page/account_manager_browser_proxy.html">
 <link rel="import" href="../../people_page/profile_info_browser_proxy.html">
 <link rel="import" href="../../people_page/signout_dialog.html">
 <link rel="import" href="../../people_page/sync_browser_proxy.html">
 <link rel="import" href="../../people_page/sync_controls.html">
 <link rel="import" href="../../people_page/sync_page.html">
-<link rel="import" href="../os_route.html">
 <link rel="import" href="../../router.html">
 <link rel="import" href="../../settings_page/settings_animated_pages.html">
 <link rel="import" href="../../settings_page/settings_subpage.html">
 <link rel="import" href="../../settings_shared_css.html">
+<link rel="import" href="../../i18n_setup.html">
+<link rel="import" href="../os_route.html">
+<link rel="import" href="../os_page_visibility.html">
+<link rel="import" href="../parental_controls_page/parental_controls_page.html">
 <link rel="import" href="account_manager.html">
 <link rel="import" href="fingerprint_list.html">
 <link rel="import" href="kerberos_accounts.html">
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js
index 0b7c7947..4b93a33d 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.js
@@ -26,10 +26,10 @@
    *   osWifiConfigurationsSynced: boolean,
    * }}
    */
-  let OsSyncPrefs;
+  /* #export */ let OsSyncPrefs;
 
   /** @interface */
-  class OsSyncBrowserProxy {
+  /* #export */ class OsSyncBrowserProxy {
     /**
      * Function to invoke when the sync page has been navigated to. This
      * registers the UI as the "active" sync UI.
@@ -64,7 +64,7 @@
   /**
    * @implements {settings.OsSyncBrowserProxy}
    */
-  class OsSyncBrowserProxyImpl {
+  /* #export */ class OsSyncBrowserProxyImpl {
     /** @override */
     didNavigateToOsSyncPage() {
       chrome.send('DidNavigateToOsSyncPage');
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
index e121c960..63f0d094a 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
@@ -10,7 +10,9 @@
 <link rel="import" href="../localized_link/localized_link.html">
 <link rel="import" href="../metrics_recorder.html">
 <link rel="import" href="../os_route.html">
+<link rel="import" href="../../router.html">
 <link rel="import" href="os_sync_browser_proxy.html">
+<link rel="import" href="../../people_page/sync_browser_proxy.html">
 
 <dom-module id="os-sync-controls">
   <template>
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.html b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.html
index cc389cd..15a473f 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.html
@@ -6,7 +6,6 @@
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="../../i18n_setup.html">
 <link rel="import" href="../../settings_shared_css.html">
 
 <dom-module id="settings-pin-autosubmit-dialog">
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.html b/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.html
index a32b56a..de57c8f 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.html
@@ -10,6 +10,7 @@
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="../metrics_recorder.html">
 <link rel="import" href="fingerprint_browser_proxy.html">
+<link rel="import" href="../../i18n_setup.html">
 
 <dom-module id="settings-setup-fingerprint-dialog">
   <template>
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/users_page.html b/chrome/browser/resources/settings/chromeos/os_people_page/users_page.html
index 7e226c8..710f284 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/users_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/users_page.html
@@ -9,6 +9,7 @@
 <link rel="import" href="../../settings_shared_css.html">
 <link rel="import" href="user_list.html">
 <link rel="import" href="users_add_user_dialog.html">
+<link rel="import" href="../../i18n_setup.html">
 
 <dom-module id="settings-users-page">
   <template>
diff --git a/chrome/browser/resources/settings/chromeos/os_route.html b/chrome/browser/resources/settings/chromeos/os_route.html
index 8860cb1c..cd01063 100644
--- a/chrome/browser/resources/settings/chromeos/os_route.html
+++ b/chrome/browser/resources/settings/chromeos/os_route.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../router.html">
+<link rel="import" href="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.html">
 
 <script src="chrome://os-settings/constants/routes.mojom-lite.js"></script>
 <script src="os_route.js"></script>
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js
index 44842ec..fc68ea7 100644
--- a/chrome/browser/resources/settings/chromeos/os_route.js
+++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// #import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'
+// #import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
 // #import '../constants/routes.mojom-lite.js';
 
-// #import {OsSettingsRoutes} from './os_settings_routes.m.js'
+// #import {OsSettingsRoutes} from './os_settings_routes.m.js';
 // #import {Route, Router} from '../router.m.js';
 // #import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni
index ab4a8cc9..2350de3 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.gni
+++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -11,6 +11,7 @@
     settings_namespace_rewrites + cr_components_chromeos_namespace_rewrites +
     cr_elements_chromeos_namespace_rewrites +
     [
+      "parental_controls.ParentalControlsBrowserProxy|ParentalControlsBrowserProxy",
       "settings.AccountManagerBrowserProxy|AccountManagerBrowserProxy",
       "settings.AmbientModeBrowserProxy|AmbientModeBrowserProxy",
       "settings.ChangePictureBrowserProxy|ChangePictureBrowserProxy",
@@ -32,6 +33,17 @@
       "settings.recordSettingChange|recordSettingChange",
       "settings.SmartLockSignInEnabledState|SmartLockSignInEnabledState",
       "settings.WallpaperBrowserProxy|WallpaperBrowserProxy",
+      "settings.FingerprintBrowserProxy|FingerprintBrowserProxy",
+      "settings.FingerprintResultType|FingerprintResultType",
+      "settings.recordLockScreenProgress|recordLockScreenProgress",
+      "settings.OsSyncBrowserProxy|OsSyncBrowserProxy",
+      "settings.FingerprintInfo|FingerprintInfo",
+      "settings.FingerprintSetupStep|FingerprintSetupStep",
+      "settings.FingerprintAttempt|FingerprintAttempt",
+      "settings.FingerprintScan|FingerprintScan",
+      "settings.KerberosAccount|KerberosAccount",
+      "settings.OsSyncPrefs|OsSyncPrefs",
+      "settings.ValidateKerberosConfigResult|ValidateKerberosConfigResult",
     ]
 
 os_settings_auto_imports = settings_auto_imports +
@@ -46,18 +58,25 @@
                              "chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_browser_proxy.html|MultiDeviceBrowserProxy,MultiDeviceBrowserProxyImpl",
                              "chrome/browser/resources/settings/chromeos/os_people_page/kerberos_accounts_browser_proxy.html|KerberosAccount,KerberosAccountsBrowserProxyImpl,KerberosAccountsBrowserProxy,KerberosErrorType,KerberosConfigErrorCode,ValidateKerberosConfigResult",
                              "chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.html|OsSyncBrowserProxy,OsSyncBrowserProxyImpl,OsSyncPrefs",
+                             "chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.html|LockScreenUnlockType,LockStateBehaviorImpl,LockStateBehavior",
+                             "chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.html|FingerprintInfo,FingerprintBrowserProxy,FingerprintResultType,FingerprintBrowserProxyImpl,FingerprintAttempt,FingerprintScan",
+                             "chrome/browser/resources/settings/chromeos/os_page_visibility.html|OSPageVisibility",
                              "chrome/browser/resources/settings/chromeos/os_reset_page/os_reset_browser_proxy.html|OsResetBrowserProxy,OsResetBrowserProxyImpl",
                              "chrome/browser/resources/settings/chromeos/os_route.html|routes",
                              "chrome/browser/resources/settings/chromeos/os_settings_routes.html|OsSettingsRoutes",
                              "chrome/browser/resources/settings/chromeos/personalization_page/change_picture_browser_proxy.html|ChangePictureBrowserProxy,ChangePictureBrowserProxyImpl,DefaultImage",
                              "chrome/browser/resources/settings/chromeos/personalization_page/wallpaper_browser_proxy.html|WallpaperBrowserProxy,WallpaperBrowserProxyImpl",
+                             "chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.html|ParentalControlsBrowserProxy,ParentalControlsBrowserProxyImpl",
                              "chrome/browser/resources/settings/chromeos/route_origin_behavior.html|RouteOriginBehaviorImpl,RouteOriginBehavior",
                              "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxy,LifetimeBrowserProxyImpl",
-                             "chrome/browser/resources/settings/people_page/account_manager_browser_proxy.html|AccountManagerBrowserProxy,AccountManagerBrowserProxyImpl",
+                             "chrome/browser/resources/settings/people_page/account_manager_browser_proxy.html|AccountManagerBrowserProxy,AccountManagerBrowserProxyImpl,Account",
+                             "chrome/browser/resources/settings/people_page/profile_info_browser_proxy.html|ProfileInfoBrowserProxyImpl,ProfileInfoBrowserProxy,ProfileInfo",
+                             "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncBrowserProxy,StatusAction,SyncStatus",
                              "chrome/browser/resources/settings/route.html|routes",
                              "chrome/browser/resources/settings/router.html|Router,Route,RouteObserverBehavior",
-                             "ui/webui/resources/html/polymer.html|Polymer,html,flush",
+                             "ui/webui/resources/html/polymer.html|Polymer,html,flush, afterNextRender",
                              "ui/webui/resources/html/icon.html|getImage",
+                             "ui/webui/resources/html/cr.html|sendWithPromise",
                            ]
 
 os_settings_migrated_imports = settings_migrated_imports
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js
index 374c2277..b054dcd 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -16,17 +16,23 @@
 import './personalization_page/change_picture.m.js';
 import './os_people_page/account_manager.m.js';
 import './os_people_page/kerberos_accounts.m.js';
+import './parental_controls_page/parental_controls_page.m.js';
+import './os_people_page/os_people_page.m.js';
 
 export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '../lifetime_browser_proxy.m.js';
 export {AccountManagerBrowserProxy, AccountManagerBrowserProxyImpl} from '../people_page/account_manager_browser_proxy.m.js';
+export {ParentalControlsBrowserProxyImpl, ParentalControlsBrowserProxy} from './parental_controls_page/parental_controls_browser_proxy.m.js';
 export {CrSettingsPrefs} from '../prefs/prefs_types.m.js';
 export {Route, Router} from '../router.m.js';
 export {AmbientModeBrowserProxyImpl} from './ambient_mode_page/ambient_mode_browser_proxy.m.js';
 export {bluetoothApis} from './bluetooth_page/bluetooth_page.m.js';
+export {pageVisibility} from '../page_visibility.js';
 export {MultiDeviceBrowserProxy, MultiDeviceBrowserProxyImpl} from './multidevice_page/multidevice_browser_proxy.m.js';
 export {MultiDeviceFeature, MultiDeviceFeatureState, MultiDevicePageContentData, MultiDeviceSettingsMode, SmartLockSignInEnabledState} from './multidevice_page/multidevice_constants.m.js';
 export {KerberosAccountsBrowserProxyImpl, KerberosConfigErrorCode, KerberosErrorType} from './os_people_page/kerberos_accounts_browser_proxy.m.js';
 export {OsResetBrowserProxyImpl} from './os_reset_page/os_reset_browser_proxy.m.js';
+export {SyncBrowserProxy, SyncBrowserProxyImpl, PageStatus, StoredAccount, SyncStatus} from '../people_page/sync_browser_proxy.m.js';
+export {ProfileInfoBrowserProxyImpl, ProfileInfoBrowserProxy} from '../people_page/profile_info_browser_proxy.m.js';
 export {routes} from './os_route.m.js';
 export {ChangePictureBrowserProxy, ChangePictureBrowserProxyImpl} from './personalization_page/change_picture_browser_proxy.m.js';
 export {WallpaperBrowserProxyImpl} from './personalization_page/wallpaper_browser_proxy.m.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
index 92d890a..34c7744 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
+++ b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
@@ -67,6 +67,62 @@
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
+    <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_PROFILE_INFO_BROWSER_PROXY_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SYNC_BROWSER_PROXY_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_browser_proxy.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_account_control.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SYNC_ENCRYPTION_OPTIONS_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_encryption_options.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SIGNOUT_DIALOG_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/people_page/signout_dialog.m.js"
+           use_base_dir="false"
+           preprocess="true"
+           compress="false" type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SYNC_CONTROLS_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_controls.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SYNC_PAGE_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_page.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PRIVACY_PAGE_PERSONALIZATION_OPTIONS_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/personalization_options.m.js"
+           use_base_dir="false"
+           compress="false"
+           preprocess="true"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PRIVACY_PAGE_BROWSER_PROXY_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PARENTAL_CONTROLS_PAGE_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PARENTAL_CONTROLS_BROWSER_PROXY_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
   <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_M_JS"
            file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/kerberos_accounts.m.js"
            use_base_dir="false"
@@ -87,6 +143,76 @@
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_FINGERPRINT_LIST_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_list.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_LOCK_SCREEN_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_LOCK_SCREEN_PASSWORD_PROMPT_DIALOG_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/lock_screen_password_prompt_dialog.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_LOCK_STATE_BEHAVIOR_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/lock_state_behavior.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_OS_SYNC_CONTROLS_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_USERS_PAGE_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/users_page.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_USERS_ADD_USER_DIALOG_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/users_add_user_dialog.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_OS_SYNC_BROWSER_PROXY_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_browser_proxy.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_USERS_LIST_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/user_list.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_FINGERPRINT_BROWSER_PROXY_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SETUP_FINGERPRINT_DIALOG_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/setup_fingerprint_dialog.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_PIN_AUTOSUBMIT_DIALOG_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/pin_autosubmit_dialog.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_SETUP_PIN_DIALOG_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/setup_pin_dialog.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PEOPLE_PAGE_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
   <include name="IDR_OS_SETTINGS_RESET_POWERWASH_DIALOG_M_JS"
            file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_reset_page/os_powerwash_dialog.m.js"
            use_base_dir="false"
@@ -132,6 +258,15 @@
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_OS_PAGE_VISIBILITY_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_page_visibility.m.js"
+           use_base_dir="false"
+           compress="false"
+           type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_PAGE_VISIBILITY_JS"
+           file="page_visibility.js"
+           preprocess="true"
+           compress="false" type="BINDATA" />
   <include name="IDR_OS_SETTINGS_MULTIDEVICE_PAGE_M_JS"
            file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.m.js"
            use_base_dir="false"
@@ -197,6 +332,11 @@
            use_base_dir="false"
            compress="false"
            type="BINDATA" />
+  <include name="IDR_OS_SETTINGS_ICONS_M_JS"
+           file="${root_gen_dir}/chrome/browser/resources/settings/icons.m.js"
+           use_base_dir="false"
+           compress="false" type="BINDATA"
+           preprocess="true" />
   <include name="IDR_OS_SETTINGS_SETTINGS_OS_ROUTE_M_JS"
            file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_route.m.js"
            use_base_dir="false"
diff --git a/chrome/browser/resources/settings/chromeos/parental_controls_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/parental_controls_page/BUILD.gn
index 9c9e665..e423491 100644
--- a/chrome/browser/resources/settings/chromeos/parental_controls_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/parental_controls_page/BUILD.gn
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../os_settings.gni")
 
 js_type_check("closure_compile") {
   deps = [ ":parental_controls_page" ]
@@ -22,33 +25,30 @@
   ]
 }
 
-# TODO: Uncomment as the Polymer3 migration makes progress.
-#js_type_check("closure_compile_module") {
-#  is_polymer3 = true
-#  deps = [
-#    ":parental_controls_browser_proxy.m",
-#    ":parental_controls_page.m"
-#  ]
-#}
+js_type_check("closure_compile_module") {
+  is_polymer3 = true
+  deps = [
+    ":parental_controls_browser_proxy.m",
+    ":parental_controls_page.m",
+  ]
+}
 
 js_library("parental_controls_browser_proxy.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.m.js" ]
-  deps = [
-    # TODO: Fill those in.
-  ]
   extra_deps = [ ":modulize" ]
 }
 
 js_library("parental_controls_page.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.m.js" ]
   deps = [
-    # TODO: Fill those in.
+    ":parental_controls_browser_proxy.m",
+    "../..:router.m",
+    "//ui/webui/resources/js:i18n_behavior.m",
+    "//ui/webui/resources/js:web_ui_listener_behavior.m",
   ]
   extra_deps = [ ":parental_controls_page_module" ]
 }
 
-import("//tools/polymer/polymer.gni")
-
 group("polymer3_elements") {
   public_deps = [
     ":modulize",
@@ -60,10 +60,12 @@
   js_file = "parental_controls_page.js"
   html_file = "parental_controls_page.html"
   html_type = "dom-module"
+  migrated_imports = os_settings_migrated_imports
+  namespace_rewrites = os_settings_namespace_rewrites
+  auto_imports = os_settings_auto_imports
 }
 
-import("//ui/webui/resources/tools/js_modulizer.gni")
-
 js_modulizer("modulize") {
   input_files = [ "parental_controls_browser_proxy.js" ]
+  namespace_rewrites = os_settings_namespace_rewrites
 }
diff --git a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js
index 38865a54..af24c80 100644
--- a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js
+++ b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_browser_proxy.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
+
 /**
  * @fileoverview
  * Browser Proxy for Parental Controls functions.
@@ -9,7 +11,7 @@
 
 cr.define('parental_controls', function() {
   /** @interface */
-  class BrowserProxy {
+  /* #export */ class ParentalControlsBrowserProxy {
     /**
      * Shows the Add Supervsion dialog.
      */
@@ -23,8 +25,8 @@
     launchFamilyLinkSettings() {}
   }
 
-  /** @implements {parental_controls.BrowserProxy} */
-  class BrowserProxyImpl {
+  /** @implements {parental_controls.ParentalControlsBrowserProxy} */
+  /* #export */ class ParentalControlsBrowserProxyImpl {
     /** @override */
     showAddSupervisionDialog() {
       chrome.send('showAddSupervisionDialog');
@@ -36,11 +38,11 @@
     }
   }
 
-  cr.addSingletonGetter(BrowserProxyImpl);
+  cr.addSingletonGetter(ParentalControlsBrowserProxyImpl);
 
   // #cr_define_end
   return {
-    BrowserProxy: BrowserProxy,
-    BrowserProxyImpl: BrowserProxyImpl,
+    ParentalControlsBrowserProxy: ParentalControlsBrowserProxy,
+    ParentalControlsBrowserProxyImpl: ParentalControlsBrowserProxyImpl,
   };
 });
diff --git a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
index 6ab8140..95e12215 100644
--- a/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
+++ b/chrome/browser/resources/settings/chromeos/parental_controls_page/parental_controls_page.js
@@ -34,7 +34,7 @@
 
   /** @override */
   created() {
-    this.browserProxy_ = parental_controls.BrowserProxyImpl.getInstance();
+    this.browserProxy_ = parental_controls.ParentalControlsBrowserProxyImpl.getInstance();
   },
 
   /** @override */
diff --git a/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
index 988af02..6a87663 100644
--- a/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
+++ b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
@@ -21,7 +21,7 @@
    *   organization: (string|undefined),
    * }}
    */
-  let Account;
+  /* #export */ let Account;
 
   /** @interface */
   /* #export */ class AccountManagerBrowserProxy {
diff --git a/chrome/browser/resources/tab_strip/tab_list.js b/chrome/browser/resources/tab_strip/tab_list.js
index 11f4261..f878e2e0 100644
--- a/chrome/browser/resources/tab_strip/tab_list.js
+++ b/chrome/browser/resources/tab_strip/tab_list.js
@@ -358,9 +358,6 @@
           'tab-group-visuals-changed',
           (groupId, visualData) =>
               this.onTabGroupVisualsChanged_(groupId, visualData));
-      this.addWebUIListener_(
-          'tab-group-id-replaced',
-          (oldId, newId) => this.onTabGroupIdReplaced_(oldId, newId));
     });
   }
 
@@ -590,18 +587,6 @@
   }
 
   /**
-   * @param {string} oldId
-   * @param {string} newId
-   * @private
-   */
-  onTabGroupIdReplaced_(oldId, newId) {
-    const tabGroupElement = this.findTabGroupElement_(oldId);
-    if (tabGroupElement) {
-      tabGroupElement.dataset.groupId = newId;
-    }
-  }
-
-  /**
    * @param {number} tabId
    * @param {number} index
    * @param {string} groupId
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
index e067dd4..f381eb0 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -90,6 +90,7 @@
 #include "net/test/url_request/url_request_mock_http_job.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "third_party/blink/public/common/features.h"
 #include "ui/base/l10n/l10n_util.h"
 
 using chrome_browser_interstitials::SecurityInterstitialIDNTest;
@@ -1812,18 +1813,26 @@
           testing::tuple<bool /* IsolateAllSitesForTesting */,
                          bool /* Show warning on mouse click */>> {
  public:
-  SafeBrowsingBlockingPageDelayedWarningBrowserTest() {
+  SafeBrowsingBlockingPageDelayedWarningBrowserTest() = default;
+
+  void SetUp() override {
     if (warning_on_mouse_click_enabled()) {
       const std::map<std::string, std::string> parameters{{"mouse", "true"}};
       std::vector<base::test::ScopedFeatureList::FeatureAndParams>
           enabled_features{base::test::ScopedFeatureList::FeatureAndParams(
-              kDelayedWarnings, parameters)};
+                               kDelayedWarnings, parameters),
+                           base::test::ScopedFeatureList::FeatureAndParams(
+                               blink::features::kPortals, {}),
+                           base::test::ScopedFeatureList::FeatureAndParams(
+                               blink::features::kPortalsCrossOrigin, {})};
       scoped_feature_list_.InitWithFeaturesAndParameters(enabled_features, {});
     } else {
       scoped_feature_list_.InitWithFeatures(
-          /*enabled_features=*/{kDelayedWarnings},
+          /*enabled_features=*/{kDelayedWarnings, blink::features::kPortals,
+                                blink::features::kPortalsCrossOrigin},
           /*disabled_features=*/{});
     }
+    InProcessBrowserTest::SetUp();
   }
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -1961,8 +1970,10 @@
         ->SetURLThreatType(url, threat_type);
   }
 
- private:
+ protected:
   base::test::ScopedFeatureList scoped_feature_list_;
+
+ private:
   TestSafeBrowsingServiceFactory factory_;
   TestSafeBrowsingBlockingPageFactory blocking_page_factory_;
   TestThreatDetailsFactory details_factory_;
@@ -2402,4 +2413,54 @@
                                      SB_THREAT_TYPE_URL_PHISHING,
                                      SB_THREAT_TYPE_URL_UNWANTED)));
 
+// Tests with the <portal> tag.
+class SafeBrowsingBlockingPageDelayedWarningWithPortalBrowserTest
+    : public SafeBrowsingBlockingPageDelayedWarningBrowserTest {
+ public:
+  SafeBrowsingBlockingPageDelayedWarningWithPortalBrowserTest() = default;
+
+  void SetUp() override {
+    scoped_feature_list_.InitWithFeatures(
+        /*enabled_features=*/{kDelayedWarnings, blink::features::kPortals,
+                              blink::features::kPortalsCrossOrigin},
+        /*disabled_features=*/{});
+    InProcessBrowserTest::SetUp();
+  }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    SafeBrowsingBlockingPageDelayedWarningWithPortalBrowserTest,
+    testing::Combine(
+        testing::Values(false, true), /* IsolateAllSitesForTesting */
+        testing::Values(false, true) /* Show warning on mouse click */));
+
+// Tests that if a page embeds a portal whose contents are considered dangerous
+// by Safe Browsing, the embedder is also treated as dangerous, and the
+// interstitial isn't delayed. This is similar to
+// PortalBrowserTest.EmbedderOfDangerousPortalConsideredDangerous.
+IN_PROC_BROWSER_TEST_P(
+    SafeBrowsingBlockingPageDelayedWarningWithPortalBrowserTest,
+    Portal_WarningNotDelayed) {
+  GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+  GURL dangerous_url(
+      embedded_test_server()->GetURL("evil.com", "/title2.html"));
+  SetURLThreatType(dangerous_url, SB_THREAT_TYPE_URL_PHISHING);
+
+  ui_test_utils::NavigateToURL(browser(), main_url);
+  WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents();
+
+  content::TestNavigationObserver observer(contents);
+  ASSERT_TRUE(content::ExecJs(
+      contents,
+      content::JsReplace("let portal = document.createElement('portal');"
+                         "portal.src = $1;"
+                         "document.body.appendChild(portal);",
+                         dangerous_url)));
+  observer.WaitForNavigationFinished();
+  // The interstitial should be shown immediately.
+  EXPECT_TRUE(WaitForReady(browser()));
+  EXPECT_TRUE(IsShowingInterstitial(contents));
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
index 9642d29..4b84751 100644
--- a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
+++ b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
@@ -48,10 +48,11 @@
     bool is_main_frame,
     scoped_refptr<SafeBrowsingUIManager> ui_manager) {
   content::WebContents* web_contents = web_contents_getter.Run();
-  // Don't delay the interstitial for prerender pages.
+  // Don't delay the interstitial for prerender pages and portals.
   if (!web_contents ||
       prerender::ChromePrerenderContentsDelegate::FromWebContents(
-          web_contents)) {
+          web_contents) ||
+      web_contents->IsPortal()) {
     SafeBrowsingUIManager::StartDisplayingBlockingPage(ui_manager, resource);
     return;
   }
diff --git a/chrome/browser/safe_browsing/user_interaction_observer.cc b/chrome/browser/safe_browsing/user_interaction_observer.cc
index 404f28d22..e70b0b9 100644
--- a/chrome/browser/safe_browsing/user_interaction_observer.cc
+++ b/chrome/browser/safe_browsing/user_interaction_observer.cc
@@ -97,6 +97,7 @@
   if (FromWebContents(web_contents)) {
     return;
   }
+  DCHECK(!web_contents->IsPortal());
   auto observer = std::make_unique<SafeBrowsingUserInteractionObserver>(
       web_contents, resource, is_main_frame, ui_manager);
   web_contents->SetUserData(kWebContentsUserDataKey, std::move(observer));
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.cc b/chrome/browser/sessions/chrome_tab_restore_service_client.cc
index ee39dc5d..51b24265 100644
--- a/chrome/browser/sessions/chrome_tab_restore_service_client.cc
+++ b/chrome/browser/sessions/chrome_tab_restore_service_client.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/sessions/session_common_utils.h"
 #include "chrome/common/url_constants.h"
 #include "components/sessions/content/content_live_tab.h"
+#include "components/tab_groups/tab_group_id.h"
 #include "extensions/buildflags/buildflags.h"
 
 #if BUILDFLAG(ENABLE_SESSION_SERVICE)
@@ -68,6 +69,16 @@
 #endif
 }
 
+sessions::LiveTabContext*
+ChromeTabRestoreServiceClient::FindLiveTabContextWithGroup(
+    tab_groups::TabGroupId group) {
+#if defined(OS_ANDROID)
+  return nullptr;
+#else
+  return BrowserLiveTabContext::FindContextWithGroup(profile_, group);
+#endif
+}
+
 bool ChromeTabRestoreServiceClient::ShouldTrackURLForRestore(const GURL& url) {
   return ::ShouldTrackURLForRestore(url);
 }
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.h b/chrome/browser/sessions/chrome_tab_restore_service_client.h
index 5ab5670..ad795d2 100644
--- a/chrome/browser/sessions/chrome_tab_restore_service_client.h
+++ b/chrome/browser/sessions/chrome_tab_restore_service_client.h
@@ -28,6 +28,8 @@
       const sessions::LiveTab* tab) override;
   sessions::LiveTabContext* FindLiveTabContextWithID(
       SessionID desired_id) override;
+  sessions::LiveTabContext* FindLiveTabContextWithGroup(
+      tab_groups::TabGroupId group) override;
   bool ShouldTrackURLForRestore(const GURL& url) override;
   std::string GetExtensionAppIDForTab(sessions::LiveTab* tab) override;
   base::FilePath GetPathToSaveTo() override;
diff --git a/chrome/browser/sessions/tab_restore_browsertest.cc b/chrome/browser/sessions/tab_restore_browsertest.cc
index a86ede8..3b1fdc6 100644
--- a/chrome/browser/sessions/tab_restore_browsertest.cc
+++ b/chrome/browser/sessions/tab_restore_browsertest.cc
@@ -1066,6 +1066,31 @@
   EXPECT_EQ(data->color(), visual_data_2.color());
 }
 
+// Closing a tab in a group then moving the group to a new window before
+// restoring will place the tab in the group in the new window.
+IN_PROC_BROWSER_TEST_F(TabRestoreTestWithTabGroupsEnabled,
+                       RestoreTabIntoGroupInNewWindow) {
+  const int tab_count = AddSomeTabs(browser(), 3);
+  ASSERT_LE(4, tab_count);
+
+  const int closed_tab_index = 1;
+
+  tab_groups::TabGroupId group =
+      browser()->tab_strip_model()->AddToNewGroup({0, 1});
+
+  CloseTab(closed_tab_index);
+  chrome::MoveTabsToNewWindow(browser(), {0}, group);
+
+  // Expect the tab to be restored to the new window, inside the group.
+  ASSERT_NO_FATAL_FAILURE(RestoreTab(1, closed_tab_index));
+  Browser* new_browser = active_browser_list_->get(1);
+  ASSERT_EQ(2u, new_browser->tab_strip_model()
+                    ->group_model()
+                    ->GetTabGroup(group)
+                    ->ListTabs()
+                    .size());
+}
+
 IN_PROC_BROWSER_TEST_F(TabRestoreTestWithTabGroupsEnabled,
                        RestoreWindowWithGroupedTabs) {
   ui_test_utils::NavigateToURLWithDisposition(
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index d55ba84..1612549b 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1188,6 +1188,8 @@
       "tab_sharing/tab_sharing_infobar_delegate.cc",
       "tab_sharing/tab_sharing_infobar_delegate.h",
       "tab_sharing/tab_sharing_ui.h",
+      "tabs/existing_base_sub_menu_model.cc",
+      "tabs/existing_base_sub_menu_model.h",
       "tabs/existing_tab_group_sub_menu_model.cc",
       "tabs/existing_tab_group_sub_menu_model.h",
       "tabs/existing_window_sub_menu_model.cc",
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
index bbe29c7..433fb827 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -2239,6 +2239,28 @@
   base::RunLoop run_loop;
   base::Closure quit = run_loop.QuitClosure();
 
+  if (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) {
+    apps::AppServiceProxy* proxy =
+        apps::AppServiceProxyFactory::GetForProfile(profile_.get());
+    ASSERT_NE(nullptr, proxy);
+
+    proxy->LoadIcon(
+        apps::mojom::AppType::kArc, app_id, apps::mojom::IconType::kCompressed,
+        icon_size, false /*allow_placeholder_icon*/,
+        base::BindLambdaForTesting([&](apps::mojom::IconValuePtr icon_value) {
+          EXPECT_EQ(apps::mojom::IconType::kCompressed, icon_value->icon_type);
+          EXPECT_TRUE(icon_value->compressed);
+          std::vector<uint8_t> png_data = icon_value->compressed.value();
+          std::string compressed(png_data.begin(), png_data.end());
+          // Check that |compressed| starts with the 8-byte PNG magic string.
+          EXPECT_EQ(compressed.substr(0, 8),
+                    "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a");
+          quit.Run();
+        }));
+    run_loop.Run();
+    return;
+  }
+
   apps::ArcIconOnceLoader once_loader(profile());
   once_loader.LoadIcon(
       app_id, icon_size, apps::mojom::IconType::kCompressed,
@@ -2251,7 +2273,8 @@
           if (iter != compressed_images.end()) {
             num_compressed_images_seen++;
             const std::string& compressed = iter->second;
-            // Check that |compressed| starts with the 8-byte PNG magic string.
+            // Check that |compressed| starts with the 8-byte PNG magic
+            // string.
             EXPECT_EQ(compressed.substr(0, 8),
                       "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a");
           }
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index c6d345e2..e76b8ed5 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -760,14 +760,7 @@
   Browser* new_browser =
       new Browser(Browser::CreateParams(browser->profile(), true));
 
-  base::Optional<tab_groups::TabGroupId> new_group = base::nullopt;
   if (group.has_value()) {
-    // Recreate the group in the new window with a different ID but the same
-    // title and color. Also ensure that the group is not collapsed. This is
-    // consistent with the behavior when dragging a group out of a window.
-
-    new_group = tab_groups::TabGroupId::GenerateNew();
-
     const tab_groups::TabGroupVisualData* old_visual_data =
         browser->tab_strip_model()
             ->group_model()
@@ -777,8 +770,8 @@
                                                    old_visual_data->color(),
                                                    false /* is_collapsed */);
 
-    new_browser->tab_strip_model()->group_model()->AddTabGroup(
-        new_group.value(), new_visual_data);
+    new_browser->tab_strip_model()->group_model()->AddTabGroup(group.value(),
+                                                               new_visual_data);
   }
 
   int indices_size = tab_indices.size();
@@ -799,7 +792,7 @@
 
     new_browser->tab_strip_model()->AddWebContents(std::move(contents_move), -1,
                                                    ui::PAGE_TRANSITION_TYPED,
-                                                   add_types, new_group);
+                                                   add_types, group);
   }
   new_browser->window()->Show();
 }
diff --git a/chrome/browser/ui/browser_finder.cc b/chrome/browser/ui/browser_finder.cc
index 7892106..687c5453 100644
--- a/chrome/browser/ui/browser_finder.cc
+++ b/chrome/browser/ui/browser_finder.cc
@@ -13,7 +13,9 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
+#include "chrome/browser/ui/tabs/tab_group_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "components/tab_groups/tab_group_id.h"
 #include "content/public/browser/navigation_controller.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -232,6 +234,15 @@
   return (it == all_tabs.end()) ? nullptr : it.browser();
 }
 
+Browser* FindBrowserWithGroup(Profile* profile, tab_groups::TabGroupId group) {
+  for (auto* browser : *BrowserList::GetInstance()) {
+    if (browser->profile() == profile && browser->tab_strip_model() &&
+        browser->tab_strip_model()->group_model()->ContainsTabGroup(group))
+      return browser;
+  }
+  return nullptr;
+}
+
 Browser* FindLastActiveWithProfile(Profile* profile) {
   BrowserList* list = BrowserList::GetInstance();
   // We are only interested in last active browsers, so we don't fall back to
diff --git a/chrome/browser/ui/browser_finder.h b/chrome/browser/ui/browser_finder.h
index 45ecde7..0e2cdd30 100644
--- a/chrome/browser/ui/browser_finder.h
+++ b/chrome/browser/ui/browser_finder.h
@@ -17,6 +17,10 @@
 class WebContents;
 }
 
+namespace tab_groups {
+class TabGroupId;
+}
+
 // Collection of functions to find Browsers based on various criteria.
 
 namespace chrome {
@@ -58,6 +62,10 @@
 // |web_contents| must not be NULL.
 Browser* FindBrowserWithWebContents(const content::WebContents* web_contents);
 
+// Find the browser containing the group with ID |group| or nullptr if none is
+// found within the given |profile|.
+Browser* FindBrowserWithGroup(Profile* profile, tab_groups::TabGroupId group);
+
 // Returns the Browser object owned by |profile| whose window was most recently
 // active. If no such Browsers exist, returns NULL.
 //
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc
index 5e6271f..d0bd7aa 100644
--- a/chrome/browser/ui/browser_live_tab_context.cc
+++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -252,3 +252,11 @@
   Browser* browser = chrome::FindBrowserWithID(desired_id);
   return browser ? browser->live_tab_context() : nullptr;
 }
+
+// static
+sessions::LiveTabContext* BrowserLiveTabContext::FindContextWithGroup(
+    Profile* profile,
+    tab_groups::TabGroupId group) {
+  Browser* browser = chrome::FindBrowserWithGroup(profile, group);
+  return browser ? browser->live_tab_context() : nullptr;
+}
diff --git a/chrome/browser/ui/browser_live_tab_context.h b/chrome/browser/ui/browser_live_tab_context.h
index 6f02b146..a16a579 100644
--- a/chrome/browser/ui/browser_live_tab_context.h
+++ b/chrome/browser/ui/browser_live_tab_context.h
@@ -93,6 +93,13 @@
   // such a Browser exists.
   static sessions::LiveTabContext* FindContextWithID(SessionID desired_id);
 
+  // see chrome::FindBrowserWithGroup
+  // Returns the LiveTabContext of the Browser containing the group with ID
+  // |group| if such a Browser exists within the given |profile|.
+  static sessions::LiveTabContext* FindContextWithGroup(
+      Profile* profile,
+      tab_groups::TabGroupId group);
+
  private:
   Browser* const browser_;
 
diff --git a/chrome/browser/ui/tabs/existing_base_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_base_sub_menu_model.cc
new file mode 100644
index 0000000..da5e866
--- /dev/null
+++ b/chrome/browser/ui/tabs/existing_base_sub_menu_model.cc
@@ -0,0 +1,83 @@
+// Copyright 2020 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/ui/tabs/existing_base_sub_menu_model.h"
+
+ExistingBaseSubMenuModel::ExistingBaseSubMenuModel(
+    ui::SimpleMenuModel::Delegate* parent_delegate,
+    TabStripModel* model,
+    int context_index,
+    int min_command_id)
+    : SimpleMenuModel(this),
+      parent_delegate_(parent_delegate),
+      model_(model),
+      context_index_(context_index),
+      min_command_id_(min_command_id) {}
+
+bool ExistingBaseSubMenuModel::GetAcceleratorForCommandId(
+    int command_id,
+    ui::Accelerator* accelerator) const {
+  return false;
+}
+
+bool ExistingBaseSubMenuModel::IsCommandIdChecked(int command_id) const {
+  return false;
+}
+
+bool ExistingBaseSubMenuModel::IsCommandIdEnabled(int command_id) const {
+  return true;
+}
+
+void ExistingBaseSubMenuModel::ExecuteCommand(int command_id, int event_flags) {
+  if (IsNewCommand(command_id)) {
+    ExecuteNewCommand(event_flags);
+    return;
+  }
+  ExecuteExistingCommand(command_id - min_command_id_ - 1);
+}
+
+ExistingBaseSubMenuModel::~ExistingBaseSubMenuModel() = default;
+
+ExistingBaseSubMenuModel::MenuItemInfo::MenuItemInfo(
+    const base::string16 menu_text)
+    : text(menu_text) {
+  image = base::nullopt;
+}
+
+ExistingBaseSubMenuModel::MenuItemInfo::MenuItemInfo(
+    const base::string16& menu_text,
+    ui::ImageModel menu_image)
+    : text(menu_text) {
+  image = base::Optional<ui::ImageModel>{menu_image};
+}
+
+ExistingBaseSubMenuModel::MenuItemInfo::MenuItemInfo(
+    const MenuItemInfo& menu_item_info) = default;
+
+ExistingBaseSubMenuModel::MenuItemInfo::~MenuItemInfo() = default;
+
+void ExistingBaseSubMenuModel::Build(
+    int new_text,
+    std::vector<MenuItemInfo> menu_item_infos) {
+  AddItemWithStringId(min_command_id_, new_text);
+  AddSeparator(ui::NORMAL_SEPARATOR);
+
+  // Start command ids after the parent menu's ids to avoid collisions.
+  int group_index = min_command_id_ + 1;
+  for (auto item : menu_item_infos) {
+    if (group_index > min_command_id_ + max_size)
+      break;
+
+    if (item.image.has_value()) {
+      AddItemWithIcon(group_index, item.text, item.image.value());
+    } else {
+      AddItem(group_index, item.text);
+    }
+    group_index++;
+  }
+}
+
+void ExistingBaseSubMenuModel::ExecuteNewCommand(int event_flags) {}
+
+void ExistingBaseSubMenuModel::ExecuteExistingCommand(int command_index) {}
diff --git a/chrome/browser/ui/tabs/existing_base_sub_menu_model.h b/chrome/browser/ui/tabs/existing_base_sub_menu_model.h
new file mode 100644
index 0000000..7f6b58ba7
--- /dev/null
+++ b/chrome/browser/ui/tabs/existing_base_sub_menu_model.h
@@ -0,0 +1,98 @@
+// Copyright 2020 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_UI_TABS_EXISTING_BASE_SUB_MENU_MODEL_H_
+#define CHROME_BROWSER_UI_TABS_EXISTING_BASE_SUB_MENU_MODEL_H_
+
+#include <stddef.h>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "ui/base/models/simple_menu_model.h"
+
+class TabStripModel;
+
+// Base class for creating submenus for the tab context menu. This enforces the
+// format of the submenu as follows:
+// - guaranteed unique IDs for different submenus
+// - the visual layout of the submenu
+//  - the first item of the submenu should be the option to add a tab to a new
+//    object model (e.g. group or window)
+//  - the next item in the menu should be a separator
+//  - a maximum of 200 items to add a tab to an existing model
+class ExistingBaseSubMenuModel : public ui::SimpleMenuModel,
+                                 ui::SimpleMenuModel::Delegate {
+ public:
+  ExistingBaseSubMenuModel(ui::SimpleMenuModel::Delegate* parent_delegate,
+                           TabStripModel* model,
+                           int context_index,
+                           int min_command_id);
+
+  // ui::SimpleMenuModel
+  bool GetAcceleratorForCommandId(int command_id,
+                                  ui::Accelerator* accelerator) const override;
+
+  // ui::SimpleMenuModel::Delegate
+  bool IsCommandIdChecked(int command_id) const override;
+  bool IsCommandIdEnabled(int command_id) const override;
+  void ExecuteCommand(int command_id, int event_flags) final;
+
+  ~ExistingBaseSubMenuModel() override;
+
+ protected:
+  struct MenuItemInfo {
+    explicit MenuItemInfo(const base::string16 menu_text);
+    MenuItemInfo(const base::string16& menu_text, ui::ImageModel menu_image);
+    MenuItemInfo(const MenuItemInfo& menu_item_info);
+    ~MenuItemInfo();
+
+    // The text for an entry in the sub menu.
+    const base::string16 text;
+
+    // The optional image for an entry in the sub menu.
+    base::Optional<ui::ImageModel> image;
+  };
+
+  // Helper method to create consistent submenus.|new_text| is the label to add
+  // the tab to a new object model (e.g. group or window). |menu_item_infos| is
+  // a vector of text and optionally images for adding the tab to an existing
+  // object model.
+  void Build(int new_text, std::vector<MenuItemInfo> menu_item_infos);
+
+  // Helper method for checking if the command is to add a tab to a new object
+  // model.
+  bool IsNewCommand(int command_id) const {
+    return command_id == min_command_id_;
+  }
+
+  // Performs the action for adding the tab to a new object model (e.g. group or
+  // window).
+  virtual void ExecuteNewCommand(int event_flags);
+
+  // Performs the action for adding the tab to an existing object model (e.g.
+  // group or window).
+  virtual void ExecuteExistingCommand(int command_index);
+
+  // Maximum number of entries for a submenu.
+  static const int max_size = 200;
+
+  // Command IDs for various submenus.
+  static const int kMinExistingWindowCommandId = 1001;
+  static const int kMinExistingTabGroupCommandId = 2001;
+
+  ui::SimpleMenuModel::Delegate* parent_delegate() const {
+    return parent_delegate_;
+  }
+  TabStripModel* model() { return model_; }
+  int context_index() const { return context_index_; }
+
+ private:
+  ui::SimpleMenuModel::Delegate* parent_delegate_;
+  TabStripModel* model_;
+  int context_index_;
+  int min_command_id_;
+  DISALLOW_COPY_AND_ASSIGN(ExistingBaseSubMenuModel);
+};
+
+#endif  // CHROME_BROWSER_UI_TABS_EXISTING_BASE_SUB_MENU_MODEL_H_
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
index 83def75..e3f63ed 100644
--- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
+++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
@@ -24,53 +24,43 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/native_theme/native_theme.h"
 
-constexpr int kFirstCommandIndex =
-    TabStripModel::ContextMenuCommand::CommandLast + 1;
-
 ExistingTabGroupSubMenuModel::ExistingTabGroupSubMenuModel(
     ui::SimpleMenuModel::Delegate* parent_delegate,
     TabStripModel* model,
     int context_index)
-    : SimpleMenuModel(this),
-      parent_delegate_(parent_delegate),
-      model_(model),
-      context_index_(context_index) {
-  Build();
-}
+    : ExistingBaseSubMenuModel(parent_delegate,
+                               model,
+                               context_index,
+                               kMinExistingTabGroupCommandId) {
+  const auto& tp = ThemeService::GetThemeProviderForProfile(model->profile());
+  constexpr int kIconSize = 14;
+  std::vector<MenuItemInfo> menu_item_infos;
 
-void ExistingTabGroupSubMenuModel::Build() {
-  // Start command ids after the parent menu's ids to avoid collisions.
-  int group_index = kFirstCommandIndex;
-  const auto& tp = ThemeService::GetThemeProviderForProfile(model_->profile());
-  AddItemWithStringId(TabStripModel::CommandAddToNewGroup,
-                      IDS_TAB_CXMENU_SUBMENU_NEW_GROUP);
-  AddSeparator(ui::NORMAL_SEPARATOR);
   for (tab_groups::TabGroupId group : GetOrderedTabGroups()) {
-    if (ShouldShowGroup(model_, context_index_, group)) {
-      const TabGroup* tab_group = model_->group_model()->GetTabGroup(group);
+    if (ShouldShowGroup(model, context_index, group)) {
+      const TabGroup* tab_group = model->group_model()->GetTabGroup(group);
       const base::string16 group_title = tab_group->visual_data()->title();
       const base::string16 displayed_title =
           group_title.empty() ? tab_group->GetContentString() : group_title;
-      constexpr int kIconSize = 14;
       const int color_id =
           GetTabGroupContextMenuColorId(tab_group->visual_data()->color());
       // TODO (kylixrd): Investigate passing in color_id in order to color the
       // icon using the ColorProvider.
-      AddItemWithIcon(group_index, displayed_title,
-                      ui::ImageModel::FromVectorIcon(
-                          kTabGroupIcon, tp.GetColor(color_id), kIconSize));
+      ui::ImageModel image_model = ui::ImageModel::FromVectorIcon(
+          kTabGroupIcon, tp.GetColor(color_id), kIconSize);
+      menu_item_infos.emplace_back(MenuItemInfo{displayed_title, image_model});
     }
-    group_index++;
   }
+  Build(IDS_TAB_CXMENU_SUBMENU_NEW_GROUP, menu_item_infos);
 }
 
 std::vector<tab_groups::TabGroupId>
 ExistingTabGroupSubMenuModel::GetOrderedTabGroups() {
   std::vector<tab_groups::TabGroupId> ordered_groups;
   base::Optional<tab_groups::TabGroupId> current_group = base::nullopt;
-  for (int i = 0; i < model_->count(); ++i) {
+  for (int i = 0; i < model()->count(); ++i) {
     base::Optional<tab_groups::TabGroupId> new_group =
-        model_->GetTabGroupForTab(i);
+        model()->GetTabGroupForTab(i);
     if (new_group.has_value() && new_group != current_group)
       ordered_groups.push_back(new_group.value());
     current_group = new_group;
@@ -78,28 +68,6 @@
   return ordered_groups;
 }
 
-bool ExistingTabGroupSubMenuModel::IsCommandIdChecked(int command_id) const {
-  return false;
-}
-
-bool ExistingTabGroupSubMenuModel::IsCommandIdEnabled(int command_id) const {
-  return true;
-}
-
-void ExistingTabGroupSubMenuModel::ExecuteCommand(int command_id,
-                                                  int event_flags) {
-  if (command_id == TabStripModel::CommandAddToNewGroup) {
-    parent_delegate_->ExecuteCommand(TabStripModel::CommandAddToNewGroup,
-                                     event_flags);
-    return;
-  }
-  const int group_index = command_id - kFirstCommandIndex;
-  DCHECK_LT(size_t{group_index}, model_->group_model()->ListTabGroups().size());
-  base::RecordAction(base::UserMetricsAction("TabContextMenu_NewTabInGroup"));
-  model_->ExecuteAddToExistingGroupCommand(context_index_,
-                                           GetOrderedTabGroups()[group_index]);
-}
-
 // static
 bool ExistingTabGroupSubMenuModel::ShouldShowSubmenu(TabStripModel* model,
                                                      int context_index) {
@@ -111,6 +79,19 @@
   return false;
 }
 
+void ExistingTabGroupSubMenuModel::ExecuteNewCommand(int event_flags) {
+  parent_delegate()->ExecuteCommand(TabStripModel::CommandAddToNewGroup,
+                                    event_flags);
+}
+
+void ExistingTabGroupSubMenuModel::ExecuteExistingCommand(int command_index) {
+  DCHECK_LT(size_t{command_index},
+            model()->group_model()->ListTabGroups().size());
+  base::RecordAction(base::UserMetricsAction("TabContextMenu_NewTabInGroup"));
+  model()->ExecuteAddToExistingGroupCommand(
+      context_index(), GetOrderedTabGroups()[command_index]);
+}
+
 // static
 bool ExistingTabGroupSubMenuModel::ShouldShowGroup(
     TabStripModel* model,
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h
index fcb5a5c..468e769 100644
--- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h
+++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.h
@@ -8,7 +8,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "ui/base/models/simple_menu_model.h"
+#include "chrome/browser/ui/tabs/existing_base_sub_menu_model.h"
 
 class TabStripModel;
 
@@ -16,27 +16,22 @@
 class TabGroupId;
 }
 
-class ExistingTabGroupSubMenuModel : public ui::SimpleMenuModel,
-                                     ui::SimpleMenuModel::Delegate {
+class ExistingTabGroupSubMenuModel : public ExistingBaseSubMenuModel {
  public:
   ExistingTabGroupSubMenuModel(ui::SimpleMenuModel::Delegate* parent_delegate,
                                TabStripModel* model,
                                int context_index);
   ~ExistingTabGroupSubMenuModel() override = default;
 
-  bool IsCommandIdChecked(int command_id) const override;
-
-  bool IsCommandIdEnabled(int command_id) const override;
-
-  void ExecuteCommand(int command_id, int event_flags) override;
-
   // Whether the submenu should be shown in the provided context. True iff
   // the submenu would show at least one group. Does not assume ownership of
   // |model|; |model| must outlive this instance.
-  static bool ShouldShowSubmenu(TabStripModel* model, int context_index_);
+  static bool ShouldShowSubmenu(TabStripModel* model, int context_index);
 
  private:
-  void Build();
+  // ExistingBaseSubMenuModel
+  void ExecuteNewCommand(int event_flags) override;
+  void ExecuteExistingCommand(int command_index) override;
 
   // Returns the group ids in the order that they appear in the tab strip model,
   // so that the user sees an ordered display. Only needed for creating items
@@ -44,13 +39,6 @@
   // is cheaper and sufficient for determining visibility and size of the menu.
   std::vector<tab_groups::TabGroupId> GetOrderedTabGroups();
 
-  ui::SimpleMenuModel::Delegate* parent_delegate_;
-
-  // Unowned; |model_| must outlive this instance.
-  TabStripModel* model_;
-
-  int context_index_;
-
   // Whether the submenu should contain the group |group|. True iff at least
   // one tab that would be affected by the command is not in |group|.
   static bool ShouldShowGroup(TabStripModel* model,
diff --git a/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc
index 8152fb78..66d4c3de6 100644
--- a/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc
+++ b/chrome/browser/ui/tabs/existing_window_sub_menu_model.cc
@@ -16,39 +16,21 @@
 #include "ui/views/controls/menu/menu_config.h"
 #include "ui/views/vector_icons.h"
 
-namespace {
-
-enum ExistingWindowSubMenuCommand {
-  CommandNewWindow = TabStripModel::kMinExistingWindowCommandId,
-  // CommandLast and subsequent ids will be used for the list of existing window
-  // targets.
-  CommandLast
-};
-
-}  // namespace
-
 ExistingWindowSubMenuModel::ExistingWindowSubMenuModel(
     ui::SimpleMenuModel::Delegate* parent_delegate,
     TabStripModel* model,
     int context_index)
-    : SimpleMenuModel(this),
-      parent_delegate_(parent_delegate),
-      model_(model),
-      context_index_(context_index) {
-  // Start command ids after the parent menu's ids to avoid collisions.
-  AddItemWithStringId(ExistingWindowSubMenuCommand::CommandNewWindow,
-                      IDS_TAB_CXMENU_MOVETOANOTHERNEWWINDOW);
-  AddSeparator(ui::NORMAL_SEPARATOR);
-
+    : ExistingBaseSubMenuModel(parent_delegate,
+                               model,
+                               context_index,
+                               kMinExistingWindowCommandId) {
+  std::vector<MenuItemInfo> menu_item_infos;
   auto window_titles = model->GetExistingWindowsForMoveMenu();
 
-  for (size_t i = 0; i < window_titles.size(); i++) {
-    const int command_id = ExistingWindowSubMenuCommand::CommandLast + i;
-    if (command_id > TabStripModel::kMaxExistingWindowCommandId)
-      break;
-
-    AddItem(command_id, window_titles[i]);
+  for (auto& window_title : window_titles) {
+    menu_item_infos.emplace_back(MenuItemInfo{window_title});
   }
+  Build(IDS_TAB_CXMENU_MOVETOANOTHERNEWWINDOW, menu_item_infos);
 }
 
 ExistingWindowSubMenuModel::~ExistingWindowSubMenuModel() = default;
@@ -56,55 +38,39 @@
 bool ExistingWindowSubMenuModel::GetAcceleratorForCommandId(
     int command_id,
     ui::Accelerator* accelerator) const {
-  if (command_id < ExistingWindowSubMenuCommand::CommandLast) {
-    return parent_delegate_->GetAcceleratorForCommandId(
-        SubMenuCommandToTabStripModelCommand(command_id), accelerator);
+  if (IsNewCommand(command_id)) {
+    return parent_delegate()->GetAcceleratorForCommandId(
+        TabStripModel::CommandMoveTabsToNewWindow, accelerator);
   }
   return false;
 }
 
 bool ExistingWindowSubMenuModel::IsCommandIdChecked(int command_id) const {
-  if (command_id < ExistingWindowSubMenuCommand::CommandLast) {
-    return parent_delegate_->IsCommandIdChecked(
-        SubMenuCommandToTabStripModelCommand(command_id));
+  if (IsNewCommand(command_id)) {
+    return parent_delegate()->IsCommandIdChecked(
+        TabStripModel::CommandMoveTabsToNewWindow);
   }
   return false;
 }
 
 bool ExistingWindowSubMenuModel::IsCommandIdEnabled(int command_id) const {
-  if (command_id < ExistingWindowSubMenuCommand::CommandLast) {
-    return parent_delegate_->IsCommandIdEnabled(
-        SubMenuCommandToTabStripModelCommand(command_id));
+  if (IsNewCommand(command_id)) {
+    return parent_delegate()->IsCommandIdEnabled(
+        TabStripModel::CommandMoveTabsToNewWindow);
   }
   return true;
 }
 
-void ExistingWindowSubMenuModel::ExecuteCommand(int command_id,
-                                                int event_flags) {
-  if (command_id < ExistingWindowSubMenuCommand::CommandLast) {
-    parent_delegate_->ExecuteCommand(
-        SubMenuCommandToTabStripModelCommand(command_id), event_flags);
-    return;
-  }
-
-  const int browser_index =
-      command_id - ExistingWindowSubMenuCommand::CommandLast;
-  model_->ExecuteAddToExistingWindowCommand(context_index_, browser_index);
-}
-
 // static
 bool ExistingWindowSubMenuModel::ShouldShowSubmenu(Profile* profile) {
   return chrome::GetTabbedBrowserCount(profile) > 1;
 }
 
-// static
-int ExistingWindowSubMenuModel::SubMenuCommandToTabStripModelCommand(
-    int command_id) {
-  switch (command_id) {
-    case ExistingWindowSubMenuCommand::CommandNewWindow:
-      return TabStripModel::CommandMoveTabsToNewWindow;
-    default:
-      NOTREACHED();
-      return -1;
-  }
+void ExistingWindowSubMenuModel::ExecuteNewCommand(int event_flags) {
+  parent_delegate()->ExecuteCommand(TabStripModel::CommandMoveTabsToNewWindow,
+                                    event_flags);
+}
+
+void ExistingWindowSubMenuModel::ExecuteExistingCommand(int command_index) {
+  model()->ExecuteAddToExistingWindowCommand(context_index(), command_index);
 }
diff --git a/chrome/browser/ui/tabs/existing_window_sub_menu_model.h b/chrome/browser/ui/tabs/existing_window_sub_menu_model.h
index 62b2e2f..86864310 100644
--- a/chrome/browser/ui/tabs/existing_window_sub_menu_model.h
+++ b/chrome/browser/ui/tabs/existing_window_sub_menu_model.h
@@ -8,13 +8,12 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "ui/base/models/simple_menu_model.h"
+#include "chrome/browser/ui/tabs/existing_base_sub_menu_model.h"
 
 class Profile;
 class TabStripModel;
 
-class ExistingWindowSubMenuModel : public ui::SimpleMenuModel,
-                                   ui::SimpleMenuModel::Delegate {
+class ExistingWindowSubMenuModel : public ExistingBaseSubMenuModel {
  public:
   ExistingWindowSubMenuModel(ui::SimpleMenuModel::Delegate* parent_delegate,
                              TabStripModel* model,
@@ -28,7 +27,6 @@
   // ui::SimpleMenuModel::Delegate
   bool IsCommandIdChecked(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
-  void ExecuteCommand(int command_id, int event_flags) override;
 
   // Whether the submenu should be shown in the provided context. True iff
   // the submenu would show at least one window. Does not assume ownership of
@@ -36,10 +34,9 @@
   static bool ShouldShowSubmenu(Profile* profile);
 
  private:
-  static int SubMenuCommandToTabStripModelCommand(int command_id);
-  ui::SimpleMenuModel::Delegate* parent_delegate_;
-  TabStripModel* model_;
-  int context_index_;
+  // ExistingBaseSubMenuModel
+  void ExecuteNewCommand(int event_flags) override;
+  void ExecuteExistingCommand(int command_index) override;
 
   DISALLOW_COPY_AND_ASSIGN(ExistingWindowSubMenuModel);
 };
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h
index 10f7e0b..6a445c9 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.h
+++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -496,10 +496,6 @@
     CommandLast
   };
 
-  // Range of command IDs reserved for the "Move to another window" submenu.
-  static const int kMinExistingWindowCommandId = 1001;
-  static const int kMaxExistingWindowCommandId = 1200;
-
   // Returns true if the specified command is enabled. If |context_index| is
   // selected the response applies to all selected tabs.
   bool IsContextMenuCommandEnabled(int context_index,
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
index 363944ca..fa748f1 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -33,6 +33,7 @@
 #include "extensions/common/api/extension_action/action_info.h"
 #include "extensions/common/manifest_handlers/icons_handler.h"
 #include "extensions/grit/extensions_browser_resources.h"
+#include "third_party/blink/public/common/page/page_zoom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/favicon_size.h"
@@ -401,7 +402,6 @@
   auto label = std::make_unique<ZoomValue>(web_contents());
   label->SetProperty(views::kMarginsKey, gfx::Insets(label_margin));
   label_ = label.get();
-  UpdateZoomPercent();
   AddChildView(std::move(label));
 
   // Add Zoom Out ("-") button.
@@ -428,6 +428,7 @@
   zoom_level_alert_ = zoom_level_alert.get();
   GetViewAccessibility().AddVirtualChildView(std::move(zoom_level_alert));
 
+  UpdateZoomPercent();
   StartTimerIfNecessary();
 }
 
@@ -536,6 +537,19 @@
 void ZoomBubbleView::UpdateZoomPercent() {
   label_->SetText(base::FormatPercent(
       zoom::ZoomController::FromWebContents(web_contents())->GetZoomPercent()));
+
+  // Disable buttons at min, max and default
+  auto* zoom_controller = zoom::ZoomController::FromWebContents(web_contents());
+  double current_zoom_level = zoom_controller->GetZoomLevel();
+  double default_zoom_level = zoom_controller->GetDefaultZoomLevel();
+  std::vector<double> zoom_levels =
+      zoom::PageZoom::PresetZoomLevels(default_zoom_level);
+  DCHECK(zoom_out_button_);
+  zoom_out_button_->SetEnabled(
+      !blink::PageZoomValuesEqual(zoom_levels.front(), current_zoom_level));
+  DCHECK(zoom_in_button_);
+  zoom_in_button_->SetEnabled(
+      !blink::PageZoomValuesEqual(zoom_levels.back(), current_zoom_level));
 }
 
 void ZoomBubbleView::UpdateZoomIconVisibility() {
diff --git a/chrome/browser/ui/views/tab_search/tab_search_bubble_view.cc b/chrome/browser/ui/views/tab_search/tab_search_bubble_view.cc
index 75c19b1..bfb8ec7 100644
--- a/chrome/browser/ui/views/tab_search/tab_search_bubble_view.cc
+++ b/chrome/browser/ui/views/tab_search/tab_search_bubble_view.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/ui/views/tab_search/tab_search_bubble_view.h"
 
-#include "base/metrics/histogram_functions.h"
-#include "base/timer/elapsed_timer.h"
 #include "chrome/browser/ui/webui/tab_search/tab_search_ui.h"
 #include "chrome/common/webui_url_constants.h"
 #include "ui/views/controls/webview/webview.h"
@@ -33,12 +31,7 @@
                    TabSearchBubbleView* parent)
       : WebView(browser_context), parent_(parent) {}
 
-  ~TabSearchWebView() override {
-    if (timer_.has_value()) {
-      UmaHistogramMediumTimes("Tabs.TabSearch.WindowDisplayedDuration",
-                              timer_->Elapsed());
-    }
-  }
+  ~TabSearchWebView() override = default;
 
   // views::WebView:
   void PreferredSizeChanged() override {
@@ -63,9 +56,6 @@
   void DocumentOnLoadCompletedInMainFrame() override {
     GetWidget()->Show();
     GetWebContents()->Focus();
-
-    // Track window open times from when the bubble is first shown.
-    timer_ = base::ElapsedTimer();
   }
 
   void DidStopLoading() override {
@@ -81,9 +71,6 @@
 
   // What we should set the preferred width to once TabSearch has loaded.
   gfx::Size pending_preferred_size_;
-
-  // Time the Tab Search window has been open.
-  base::Optional<base::ElapsedTimer> timer_;
 };
 
 }  // namespace
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index c5aa13da..e23be20 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -1181,10 +1181,6 @@
     // Register a new group if necessary, so that the insertion index in the
     // tab strip can be calculated based on the group membership of tabs.
     if (header_drag_) {
-      // Rather than keep the old group ID, generate a new one. This helps with
-      // restore, and allowing broken-up groups to be restored across windows
-      // as separate group IDs.
-      group_ = tab_groups::TabGroupId::GenerateNew();
       attached_context_->GetTabStripModel()->group_model()->AddTabGroup(
           group_.value(),
           source_view_drag_data()->tab_group_data.value().group_visual_data);
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 89966f3..fe892a1 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -2114,7 +2114,7 @@
   EXPECT_EQ(1u, groups2.size());
   EXPECT_THAT(model2->group_model()->GetTabGroup(groups2[0])->ListTabs(),
               testing::ElementsAre(1, 2));
-  EXPECT_NE(groups2[0], group);
+  EXPECT_EQ(groups2[0], group);
   EXPECT_EQ(tab_strip2->GetGroupColorId(groups2[0]), group_color);
 }
 
@@ -2490,7 +2490,7 @@
       model2->group_model()->GetTabGroup(browser2_groups[0])->ListTabs(),
       testing::ElementsAre(1, 2));
   ASSERT_FALSE(tab_strip->controller()->IsGroupCollapsed(browser2_groups[0]));
-  EXPECT_NE(browser2_groups[0], group);
+  EXPECT_EQ(browser2_groups[0], group);
 }
 
 namespace {
diff --git a/chrome/browser/ui/webui/tab_search/BUILD.gn b/chrome/browser/ui/webui/tab_search/BUILD.gn
index 59b54f3..092303f 100644
--- a/chrome/browser/ui/webui/tab_search/BUILD.gn
+++ b/chrome/browser/ui/webui/tab_search/BUILD.gn
@@ -6,6 +6,4 @@
 
 mojom("mojo_bindings") {
   sources = [ "tab_search.mojom" ]
-
-  public_deps = [ "//mojo/public/mojom/base" ]
 }
diff --git a/chrome/browser/ui/webui/tab_search/tab_search.mojom b/chrome/browser/ui/webui/tab_search/tab_search.mojom
index 1baa596..c320367 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search.mojom
+++ b/chrome/browser/ui/webui/tab_search/tab_search.mojom
@@ -4,8 +4,6 @@
 
 module tab_search.mojom;
 
-import "mojo/public/mojom/base/time.mojom";
-
 // Collection of WindowTabs of a profile.
 struct ProfileTabs {
   array<WindowTabs> windows;
@@ -68,9 +66,6 @@
 
   // Switch to a specific tab.
   SwitchToTab(SwitchToTabInfo switch_to_tab_info);
-
-  // Records the time taken to render the initial list of tabs.
-  RecordInitialTabsRenderTime(mojo_base.mojom.TimeDelta render_time);
 };
 
 // WebUI-side handler for requests from the browser.
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
index f2a7108..b1aa4089 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "base/base64.h"
-#include "base/metrics/histogram_functions.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
@@ -116,11 +115,6 @@
   details.browser->window()->Activate();
 }
 
-void TabSearchPageHandler::RecordInitialTabsRenderTime(
-    base::TimeDelta render_time) {
-  UmaHistogramTimes("Tabs.TabSearch.WebUI.InitialTabsRenderTime", render_time);
-}
-
 tab_search::mojom::TabPtr TabSearchPageHandler::GetTabData(
     TabStripModel* tab_strip_model,
     content::WebContents* contents,
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
index 56d1180..3dc96b1 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h
@@ -39,7 +39,6 @@
   void GetTabGroups(GetTabGroupsCallback callback) override;
   void SwitchToTab(
       tab_search::mojom::SwitchToTabInfoPtr switch_to_tab_info) override;
-  void RecordInitialTabsRenderTime(base::TimeDelta render_time) override;
 
   // TabStripModelObserver:
   void OnTabStripModelChanged(
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
index 2390be7..228f2c1 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -28,10 +28,7 @@
 
 TabSearchUI::TabSearchUI(content::WebUI* web_ui)
     : ui::MojoWebUIController(web_ui,
-                              true /* Needed for webui browser tests */),
-      webui_load_timer_(web_ui->GetWebContents(),
-                        "Tabs.TabSearch.WebUI.LoadDocumentTime",
-                        "Tabs.TabSearch.WebUI.LoadCompletedTime") {
+                              true /* Needed for webui browser tests */) {
 #if BUILDFLAG(ENABLE_TAB_SEARCH)
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(chrome::kChromeUITabSearchHost);
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.h b/chrome/browser/ui/webui/tab_search/tab_search_ui.h
index 3b678f61..ba03a58 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.h
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.h
@@ -9,7 +9,6 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h"
-#include "chrome/browser/ui/webui/webui_load_timer.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -47,8 +46,6 @@
   mojo::Receiver<tab_search::mojom::PageHandlerFactory> page_factory_receiver_{
       this};
 
-  WebuiLoadTimer webui_load_timer_;
-
   WEB_UI_CONTROLLER_TYPE_DECL();
 };
 
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
index a9985b76..b716195 100644
--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
@@ -629,27 +629,18 @@
     return;
   }
 
-  // Create a new group and copy the visuals to it.
-  tab_groups::TabGroupId new_group_id = tab_groups::TabGroupId::GenerateNew();
-  browser_->tab_strip_model()->group_model()->AddTabGroup(
-      new_group_id,
+  target_browser->tab_strip_model()->group_model()->AddTabGroup(
+      group_id.value(),
       base::Optional<tab_groups::TabGroupVisualData>{*group->visual_data()});
 
-  // The front-end needs to understand that the tab group ID has changed so
-  // that when the tabs are moved into the new group, the new group ID is
-  // updated with the correct value.
-  FireWebUIListener("tab-group-id-replaced",
-                    base::Value(group->id().ToString()),
-                    base::Value(new_group_id.ToString()));
-
   std::vector<int> source_tab_indices = group->ListTabs();
   int tab_count = source_tab_indices.size();
   for (int i = 0; i < tab_count; i++) {
     // The index needs to account for the tabs being detached, as they will
     // cause the indices to shift.
     int from_index = source_tab_indices[i] - i;
-    tab_strip_ui::MoveTabAcrossWindows(
-        source_browser, from_index, target_browser, to_index + i, new_group_id);
+    tab_strip_ui::MoveTabAcrossWindows(source_browser, from_index,
+                                       target_browser, to_index + i, group_id);
   }
 }
 
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
index 34a12411..0828ca2 100644
--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
@@ -300,14 +300,6 @@
           ->visual_data();
   ASSERT_EQ(visual_data.title(), new_visual_data->title());
   ASSERT_EQ(visual_data.color(), new_visual_data->color());
-
-  // Test that a WebUI event for the ID change was sent first.
-  const content::TestWebUI::CallData& call_data =
-      *web_ui()->call_data().front();
-  EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
-  EXPECT_EQ("tab-group-id-replaced", call_data.arg1()->GetString());
-  EXPECT_EQ(group_id.ToString(), call_data.arg2()->GetString());
-  EXPECT_EQ(new_group_id.value().ToString(), call_data.arg3()->GetString());
 }
 
 TEST_F(TabStripUIHandlerTest, MoveGroupAcrossProfiles) {
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc
index 1f4b5460..df257b0 100644
--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc
+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc
@@ -123,7 +123,7 @@
 
   Browser* source_browser = nullptr;
   std::vector<int> tab_indices_to_move;
-  base::Optional<tab_groups::TabGroupId> target_group_id;
+  base::Optional<tab_groups::TabGroupId> source_group_id;
 
   // TODO(https://crbug.com/1069869): de-duplicate with
   // TabStripUIHandler::HandleMoveTab and
@@ -148,9 +148,8 @@
         GetBrowserWithGroupId(new_browser->profile(), group_id_utf8);
     if (!source_browser)
       return false;
-    base::Optional<tab_groups::TabGroupId> source_group_id =
-        GetTabGroupIdFromString(
-            source_browser->tab_strip_model()->group_model(), group_id_utf8);
+    source_group_id = GetTabGroupIdFromString(
+        source_browser->tab_strip_model()->group_model(), group_id_utf8);
     if (!source_group_id)
       return false;
 
@@ -159,16 +158,14 @@
             *source_group_id);
     tab_indices_to_move = source_group->ListTabs();
 
-    // Create a new group with the same visuals.
-    target_group_id = tab_groups::TabGroupId::GenerateNew();
     new_browser->tab_strip_model()->group_model()->AddTabGroup(
-        *target_group_id, *source_group->visual_data());
+        *source_group_id, *source_group->visual_data());
   }
 
   for (size_t i = 0; i < tab_indices_to_move.size(); ++i) {
     int source_index = tab_indices_to_move[i] - i;
     MoveTabAcrossWindows(source_browser, source_index, new_browser, i,
-                         target_group_id);
+                         source_group_id);
   }
   new_browser->tab_strip_model()->ActivateTabAt(0);
   return true;
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc
index f4fd4c1..6dab46a 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_impl.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_impl.cc
@@ -173,8 +173,8 @@
 
   // When testing, scale everything back so that a day passes in ten seconds.
   if (is_testing_) {
-    static constexpr int64_t scale_factor =
-        base::TimeDelta::FromDays(1) / base::TimeDelta::FromSeconds(10);
+    constexpr int64_t scale_factor =
+        base::TimeDelta::FromDays(1).IntDiv(base::TimeDelta::FromSeconds(10));
     for (auto& stage : stages_)
       stage /= scale_factor;
   }
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 416d8c42..05a4a36 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1596218359-82effd1166d6978a93311943498771c13a6160db.profdata
+chrome-mac-master-1596302245-695ebe4bcd9d65e6d10de8973a8cfa80d2288da6.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index d814639c3..c422af98 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1596214766-ef32b2ce97242365d96c5d969f5553eac2e23ec9.profdata
+chrome-win32-master-1596302245-7200f9e3b515c87353205d63e1689e3308ba5fbd.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 108ca52..51d4c3ef 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1596193635-02bce97a1becd63464acfea57c5b1e9a80097f4f.profdata
+chrome-win64-master-1596302245-ba2a3d88fb1e555e9ead57ee269f293e98e0f6ea.profdata
diff --git a/chrome/common/profiler/stack_sampling_configuration.cc b/chrome/common/profiler/stack_sampling_configuration.cc
index 0942eb8..eef4373 100644
--- a/chrome/common/profiler/stack_sampling_configuration.cc
+++ b/chrome/common/profiler/stack_sampling_configuration.cc
@@ -105,7 +105,7 @@
   const base::TimeDelta duration =
       base::TimeDelta::FromSeconds(IsBrowserTestModeEnabled() ? 1 : 30);
   params.sampling_interval = base::TimeDelta::FromMilliseconds(100);
-  params.samples_per_profile = duration / params.sampling_interval;
+  params.samples_per_profile = duration.IntDiv(params.sampling_interval);
 
   return params;
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 13f9995..54e41e45 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3411,7 +3411,6 @@
     "../browser/prerender/isolated/isolated_prerender_tab_helper_unittest.cc",
     "../browser/prerender/isolated/isolated_prerender_url_loader_interceptor_unittest.cc",
     "../browser/prerender/prerender_unittest.cc",
-    "../browser/prerender/prerender_util_unittest.cc",
     "../browser/previews/previews_content_util_unittest.cc",
     "../browser/previews/previews_https_notification_infobar_decider_unittest.cc",
     "../browser/previews/previews_lite_page_infobar_delegate_unittest.cc",
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/background_icon_100p_48.png b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_100p_48.png
new file mode 100644
index 0000000..eeca5e3
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_100p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/background_icon_100p_64.png b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_100p_64.png
new file mode 100644
index 0000000..5c67726
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_100p_64.png
Binary files differ
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/background_icon_200p_48.png b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_200p_48.png
new file mode 100644
index 0000000..123d5e4
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_200p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/background_icon_200p_64.png b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_200p_64.png
new file mode 100644
index 0000000..a8431bc
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/background_icon_200p_64.png
Binary files differ
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_100p_48.png b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_100p_48.png
new file mode 100644
index 0000000..eeca5e3
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_100p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_100p_64.png b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_100p_64.png
new file mode 100644
index 0000000..5c67726
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_100p_64.png
Binary files differ
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_200p_48.png b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_200p_48.png
new file mode 100644
index 0000000..123d5e4
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_200p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_200p_64.png b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_200p_64.png
new file mode 100644
index 0000000..a8431bc
--- /dev/null
+++ b/chrome/test/data/arc_board_default_apps/test_app2/foreground_icon_200p_64.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_32.png b/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_32.png
new file mode 100644
index 0000000..1ce8901
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_32.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_48.png b/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_48.png
new file mode 100644
index 0000000..8789a80
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_64.png b/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_64.png
new file mode 100644
index 0000000..b40f6a2
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/background_icon_100p_64.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_32.png b/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_32.png
new file mode 100644
index 0000000..b40f6a2
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_32.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_48.png b/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_48.png
new file mode 100644
index 0000000..938c8b65
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_64.png b/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_64.png
new file mode 100644
index 0000000..7af3d28
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/background_icon_200p_64.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_32.png b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_32.png
new file mode 100644
index 0000000..1ce8901
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_32.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_48.png b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_48.png
new file mode 100644
index 0000000..8789a80
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_64.png b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_64.png
new file mode 100644
index 0000000..b40f6a2
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_100p_64.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_32.png b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_32.png
new file mode 100644
index 0000000..b40f6a2
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_32.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_48.png b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_48.png
new file mode 100644
index 0000000..938c8b65
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_48.png
Binary files differ
diff --git a/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_64.png b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_64.png
new file mode 100644
index 0000000..7af3d28
--- /dev/null
+++ b/chrome/test/data/arc_default_apps/test_app1/foreground_icon_200p_64.png
Binary files differ
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/common.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/common.js
index 512fdd4..5bf6c19 100644
--- a/chrome/test/data/extensions/api_test/automation/tests/tabs/common.js
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/common.js
@@ -13,16 +13,6 @@
 var rootNode = null;
 var url = '';
 
-function createTabAndWaitUntilLoaded(url, callback) {
-  chrome.tabs.create({"url": url}, function(tab) {
-    chrome.tabs.onUpdated.addListener(function(tabId, changeInfo) {
-      if (tabId == tab.id && changeInfo.status == 'complete') {
-        callback(tab);
-      }
-    });
-  });
-}
-
 function listenOnce(node, eventType, callback, capture) {
   var innerCallback = function(evt) {
     node.removeEventListener(eventType, innerCallback, capture);
@@ -34,7 +24,8 @@
 function setUpAndRunTests(allTests, opt_path) {
   var path = opt_path || 'index.html';
   getUrlFromConfig(path, function(url) {
-    createTabAndWaitUntilLoaded(url, function(unused_tab) {
+    import('/_test_resources/test_util/tabs_util.js').then(async (tabUtil) => {
+      await tabUtil.openTab(url);
       chrome.automation.getTree(function (returnedRootNode) {
         rootNode = returnedRootNode;
         if (rootNode.docLoaded) {
diff --git a/chrome/test/data/extensions/api_test/debugger_file_access/background.js b/chrome/test/data/extensions/api_test/debugger_file_access/background.js
index 0d83d91..ddf0eee 100644
--- a/chrome/test/data/extensions/api_test/debugger_file_access/background.js
+++ b/chrome/test/data/extensions/api_test/debugger_file_access/background.js
@@ -2,22 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function openTab(url) {
-  return new Promise((resolve) => {
-    chrome.tabs.onUpdated.addListener(
-        function listener(tabId, changeInfo, tab) {
-      // Note: Use new URL(...).href to compare in order to normalize the URL,
-      // which is important if the path referenced a parent (as happens in the
-      // file urls).
-      if (changeInfo.status !== 'complete' ||
-          (new URL(tab.url)).href !== (new URL(url)).href) {
-        return;
-      }
-      chrome.tabs.onUpdated.removeListener(listener);
-      resolve(tab.id);
-    });
-    chrome.tabs.create({url: url});
-  });
+function checkUrlsEqual(expected, actual) {
+  // Note: Use new URL(...).href to compare in order to normalize the URL,
+  // which is important if the path referenced a parent (as happens in the
+  // file urls).
+  chrome.test.assertEq(new URL(expected).href,
+                       new URL(actual).href);
 }
 
 function runNotAllowedTest(method, params, expectAllowed) {
@@ -46,9 +36,13 @@
   });
 }
 
-chrome.test.getConfig((config) => {
+(async () => {
+  const config = await new Promise((resolve) => {
+                   chrome.test.getConfig(resolve)
+                 });
   const fileUrl = config.testDataDirectory + '/../body1.html';
   const expectFileAccess = !!config.customArg;
+  const { openTab } = await import('/_test_resources/test_util/tabs_util.js');
 
   console.log(fileUrl);
 
@@ -63,7 +57,9 @@
     },
 
     function testAttach() {
-      openTab(fileUrl).then((tabId) => {
+      openTab(fileUrl).then((tab) => {
+        checkUrlsEqual(fileUrl, tab.url);
+        const tabId = tab.id;
         chrome.debugger.attach({tabId: tabId}, '1.1', function() {
           if (expectFileAccess) {
             chrome.test.assertNoLastError();
@@ -80,7 +76,10 @@
     },
 
     function testAttachAndNavigate() {
-      openTab(chrome.runtime.getURL('dummy.html')).then((tabId) => {
+      const url = chrome.runtime.getURL('dummy.html');
+      openTab(url).then((tab) => {
+        checkUrlsEqual(url, tab.url);
+        const tabId = tab.id;
         chrome.debugger.attach({tabId: tabId}, '1.1', function() {
           chrome.test.assertNoLastError();
           let responded = false;
@@ -125,4 +124,4 @@
           expectFileAccess);
     },
   ]);
-});
+})();
diff --git a/chrome/test/data/extensions/api_test/messaging/connect/test.js b/chrome/test/data/extensions/api_test/messaging/connect/test.js
index d748c27..465e8fd 100644
--- a/chrome/test/data/extensions/api_test/messaging/connect/test.js
+++ b/chrome/test/data/extensions/api_test/messaging/connect/test.js
@@ -41,24 +41,15 @@
 }
 
 chrome.test.getConfig(function(config) {
+  const url =
+      `http://localhost:${config.testServer.port}/extensions/test_file.html`;
   chrome.test.runTests([
-    function setupTestTab() {
+    async function setupTestTab() {
       chrome.test.log("Creating tab...");
-      var newTab = null;
-      var doneListening = listenForever(chrome.tabs.onUpdated,
-        function(_, info, tab) {
-          if (newTab && tab.id == newTab.id && info.status == 'complete') {
-            chrome.test.log("Created tab: " + tab.url);
-            testTab = tab;
-            doneListening();
-          }
-        });
-      chrome.tabs.create({
-        url: "http://localhost:PORT/extensions/test_file.html"
-                 .replace(/PORT/, config.testServer.port)
-      }, function(tab) {
-        newTab = tab;
-      });
+      const {openTab} =
+          await import('/_test_resources/test_util/tabs_util.js');
+      testTab = await openTab(url);
+      chrome.test.succeed();
     },
 
     // Tests that postMessage to the tab and its response works.
diff --git a/chrome/test/data/extensions/test_util/tabs_util.js b/chrome/test/data/extensions/test_util/tabs_util.js
new file mode 100644
index 0000000..b20e9a5
--- /dev/null
+++ b/chrome/test/data/extensions/test_util/tabs_util.js
@@ -0,0 +1,42 @@
+// Copyright 2020 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.
+
+/**
+ * Opens a new tab and waits for it to finish loading.
+ * @param {string} url The url for the new tab to point to.
+ * @return {!Promise<tabs.Tab>} A promise that resolves when the tab has
+ *     finished loading, with the value of the tab.
+ */
+export function openTab(url) {
+  return new Promise((resolve) => {
+    let createdTabId;
+    let completedTabIds = [];
+    chrome.tabs.onUpdated.addListener(
+        function listener(tabId, changeInfo, tab) {
+      if (changeInfo.status !== 'complete')
+        return;  // Tab not done.
+
+      if (createdTabId === undefined) {
+        // A tab completed loading before the chrome.tabs.create callback was
+        // triggered; stash the ID for later comparison to see if it was our
+        // tab.
+        completedTabIds.push(tabId);
+        return;
+      }
+
+      if (tabId !== createdTabId)
+        return;  // Not our tab.
+
+      // It's ours!
+      chrome.tabs.onUpdated.removeListener(listener);
+      resolve(tab);
+    });
+    chrome.tabs.create({url: url}, (tab) => {
+      if (completedTabIds.includes(tab.id))
+        resolve(tab);
+      else
+        createdTabId = tab.id;
+    });
+  });
+}
diff --git a/chrome/test/data/pdf/annotations_feature_enabled_test.js b/chrome/test/data/pdf/annotations_feature_enabled_test.js
index 9faa2bef..d5a422d 100644
--- a/chrome/test/data/pdf/annotations_feature_enabled_test.js
+++ b/chrome/test/data/pdf/annotations_feature_enabled_test.js
@@ -379,4 +379,33 @@
       chrome.test.assertEq('EMBED', contentElement().tagName);
     });
   },
+  function testHidingAnnotationsExitsAnnotationsMode() {
+    testAsync(async () => {
+      const toolbar = document.createElement('viewer-pdf-toolbar-new');
+      document.body.appendChild(toolbar);
+      toolbar.toggleAnnotation();
+      chrome.test.assertTrue(toolbar.annotationMode);
+
+      await toolbar.addEventListener('display-annotations-changed', async e => {
+        chrome.test.assertFalse(e.detail);
+        await waitFor(() => toolbar.annotationMode === false);
+        chrome.test.succeed();
+      });
+      toolbar.shadowRoot.querySelector('#show-annotations-button').click();
+    });
+  },
+  function testEnteringAnnotationsModeShowsAnnotations() {
+    const toolbar = document.createElement('viewer-pdf-toolbar-new');
+    document.body.appendChild(toolbar);
+    chrome.test.assertFalse(toolbar.annotationMode);
+
+    // Hide annotations.
+    toolbar.shadowRoot.querySelector('#show-annotations-button').click();
+
+    toolbar.addEventListener('annotation-mode-toggled', e => {
+      chrome.test.assertTrue(e.detail);
+      chrome.test.succeed();
+    });
+    toolbar.toggleAnnotation();
+  }
 ]);
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index adbfb56..2884224 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -241,6 +241,7 @@
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/bluetooth_page_tests.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_bluetooth_private.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_bluetooth.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/localized_link_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/multidevice_page_tests.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/multidevice_subpage_tests.m.js",
@@ -249,9 +250,12 @@
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/multidevice_feature_toggle_tests.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/nearby_share_subpage_tests.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_reset_page_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_people_page_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/parental_controls_page_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/people_page_account_manager_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/people_page_change_picture_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/people_page_kerberos_accounts_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_os_sync_browser_proxy.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_os_reset_browser_proxy.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_os_lifetime_browser_proxy.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/test_multidevice_browser_proxy.m.js",
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index 858e538..078600d 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -37,6 +37,7 @@
     "fake_bluetooth_private.js",
     "fake_settings_search_handler.js",
     "fake_user_action_recorder.js",
+    "fake_quick_unlock_private.js",
     "localized_link_test.js",
     "multidevice_page_tests.js",
     "multidevice_subpage_tests.js",
@@ -45,6 +46,8 @@
     "multidevice_feature_toggle_tests.js",
     "nearby_share_subpage_tests.js",
     "os_reset_page_test.js",
+    "os_people_page_test.js",
+    "parental_controls_page_test.js",
     "people_page_account_manager_test.js",
     "people_page_change_picture_test.js",
     "people_page_kerberos_accounts_test.js",
@@ -53,6 +56,7 @@
     "test_os_lifetime_browser_proxy.js",
     "test_multidevice_browser_proxy.js",
     "test_wallpaper_browser_proxy.js",
+    "test_os_sync_browser_proxy.js",
   ]
   namespace_rewrites =
       os_settings_namespace_rewrites + os_test_namespace_rewrites
diff --git a/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js b/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js
index b9d0ee87..00ee665 100644
--- a/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js
+++ b/chrome/test/data/webui/settings/chromeos/fake_quick_unlock_private.js
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {FakeChromeEvent} from 'chrome://test/fake_chrome_event.m.js';
+
 /**
  * @fileoverview Fake implementation of chrome.quickUnlockPrivate for testing.
  */
@@ -20,7 +22,7 @@
    * @constructor
    * @implements {QuickUnlockPrivate}
    */
-  function FakeQuickUnlockPrivate() {
+  /* #export */ function FakeQuickUnlockPrivate() {
     /** @type {!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>} */
     this.availableModes = [chrome.quickUnlockPrivate.QuickUnlockMode.PIN];
     /** @type {!Array<!chrome.quickUnlockPrivate.QuickUnlockMode>} */
@@ -197,5 +199,6 @@
   /** @type {!ChromeEvent} */
   FakeQuickUnlockPrivate.prototype.onActiveModesChanged = new FakeChromeEvent();
 
+  // #cr_define_end
   return {FakeQuickUnlockPrivate: FakeQuickUnlockPrivate};
 });
diff --git a/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni b/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni
index 5d88e8b0..f7378e44 100644
--- a/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni
+++ b/chrome/test/data/webui/settings/chromeos/os_namespace_rewrites.gni
@@ -1,17 +1,18 @@
 import("//chrome/browser/resources/settings/chromeos/os_settings.gni")
 
-os_test_namespace_rewrites =
-    os_settings_namespace_rewrites + [
-      "multidevice.createFakePageContentData|createFakePageContentData",
-      "multidevice.TestMultideviceBrowserProxy|TestMultideviceBrowserProxy",
-      "multidevice.HOST_DEVICE|HOST_DEVICE",
-      "reset_page.TestOsResetBrowserProxy|TestOsResetBrowserProxy",
-      "settings.TestLifetimeBrowserProxy|TestLifetimeBrowserProxy",
-      "settings.FakeBluetooth|FakeBluetooth",
-      "settings.FakeBluetoothPrivate|FakeBluetoothPrivate",
-      "settings.MultiDeviceSettingsMode|MultiDeviceSettingsMode",
-      "test_util.flushTasks|flushTasks",
-      "test_util.eventToPromise|eventToPromise",
-      "test_util.waitAfterNextRender|waitAfterNextRender",
-      "settings.TestWallpaperBrowserProxy|TestWallpaperBrowserProxy",
-    ]
+os_test_namespace_rewrites = os_settings_namespace_rewrites + [
+                               "multidevice.createFakePageContentData|createFakePageContentData",
+                               "multidevice.TestMultideviceBrowserProxy|TestMultideviceBrowserProxy",
+                               "multidevice.HOST_DEVICE|HOST_DEVICE",
+                               "reset_page.TestOsResetBrowserProxy|TestOsResetBrowserProxy",
+                               "settings.TestLifetimeBrowserProxy|TestLifetimeBrowserProxy",
+                               "settings.FakeBluetooth|FakeBluetooth",
+                               "settings.FakeBluetoothPrivate|FakeBluetoothPrivate",
+                               "settings.MultiDeviceSettingsMode|MultiDeviceSettingsMode",
+                               "test_util.flushTasks|flushTasks",
+                               "test_util.eventToPromise|eventToPromise",
+                               "test_util.waitAfterNextRender|waitAfterNextRender",
+                               "settings.TestWallpaperBrowserProxy|TestWallpaperBrowserProxy",
+                               "parental_controls.ParentalControlsBrowserProxy|ParentalControlsBrowserProxy",
+                               "settings.FakeQuickUnlockPrivate|FakeQuickUnlockPrivate",
+                             ]
diff --git a/chrome/test/data/webui/settings/chromeos/os_people_page_test.js b/chrome/test/data/webui/settings/chromeos/os_people_page_test.js
index 262b7396..0a6a1cb 100644
--- a/chrome/test/data/webui/settings/chromeos/os_people_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/os_people_page_test.js
@@ -2,7 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {TestBrowserProxy} from '../../test_browser_proxy.m.js';
+// #import {Router, pageVisibility, routes, AccountManagerBrowserProxyImpl, SyncBrowserProxyImpl, ProfileInfoBrowserProxyImpl, ProfileInfoBrowserProxy} from 'chrome://os-settings/chromeos/os_settings.js';
+// #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// #import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.m.js';
+// #import {TestSyncBrowserProxy} from './test_os_sync_browser_proxy.m.js';
+// #import {FakeQuickUnlockPrivate} from './fake_quick_unlock_private.m.js';
+
+// clang-format on
+
 cr.define('settings_people_page', function() {
+  let quickUnlockPrivateApi = null;
+
   /** @implements {settings.AccountManagerBrowserProxy} */
   class TestAccountManagerBrowserProxy extends TestBrowserProxy {
     constructor() {
@@ -258,4 +274,7 @@
       assertTrue(peoplePage.showPasswordPromptDialog_);
     });
   });
+
+  // #cr_define_end
+  return {};
 });
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
index 6782559..ee5f895 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -47,6 +47,8 @@
  ['MultideviceSmartLockSubPage', 'multidevice_smartlock_subpage_test.m.js'],
  ['MultideviceFeatureItem', 'multidevice_feature_item_tests.m.js'],
  ['MultideviceFeatureToggle', 'multidevice_feature_toggle_tests.m.js'],
+ ['ParentalControlsPage','parental_controls_page_test.m.js'],
+ ['PeoplePage', 'os_people_page_test.m.js'],
  ['PersonalizationPage', 'personalization_page_test.m.js'],
  ['PeoplePageAccountManager', 'people_page_account_manager_test.m.js'],
  ['PeoplePageChangePicture', 'people_page_change_picture_test.m.js'],
diff --git a/chrome/test/data/webui/settings/chromeos/parental_controls_page_test.js b/chrome/test/data/webui/settings/chromeos/parental_controls_page_test.js
index 8ef0d5b..0346d57b 100644
--- a/chrome/test/data/webui/settings/chromeos/parental_controls_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/parental_controls_page_test.js
@@ -2,6 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+// #import {pageVisibility, ParentalControlsBrowserProxyImpl, ParentalControlsBrowserProxy} from 'chrome://os-settings/chromeos/os_settings.js';
+// #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// #import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
+// clang-format on
+
 /** @implements {parental_controls.ParentalControlsBrowserProxy} */
 class TestParentalControlsBrowserProxy extends TestBrowserProxy {
   constructor() {
@@ -38,7 +49,7 @@
 
   setup(function() {
     parentalControlsBrowserProxy = new TestParentalControlsBrowserProxy();
-    parental_controls.BrowserProxyImpl.instance_ = parentalControlsBrowserProxy;
+    parental_controls.ParentalControlsBrowserProxyImpl.instance_ = parentalControlsBrowserProxy;
 
     PolymerTest.clearBody();
     parentalControlsPage =
@@ -116,7 +127,7 @@
 
   setup(async function() {
     parentalControlsBrowserProxy = new TestParentalControlsBrowserProxy();
-    parental_controls.BrowserProxyImpl.instance_ = parentalControlsBrowserProxy;
+    parental_controls.ParentalControlsBrowserProxyImpl.instance_ = parentalControlsBrowserProxy;
 
     PolymerTest.clearBody();
     parentalControlsPage =
diff --git a/chrome/test/data/webui/settings/chromeos/test_os_sync_browser_proxy.js b/chrome/test/data/webui/settings/chromeos/test_os_sync_browser_proxy.js
new file mode 100644
index 0000000..b30928b
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/test_os_sync_browser_proxy.js
@@ -0,0 +1,140 @@
+// 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.
+
+// clang-format off
+// #import {PageStatus, StoredAccount, SyncBrowserProxy, SyncStatus} from 'chrome://os-settings/chromeos/os_settings.js';
+// #import {TestBrowserProxy} from '../../test_browser_proxy.m.js';
+// #import {isChromeOS} from 'chrome://resources/js/cr.m.js';
+// clang-format on
+
+/** @implements {settings.SyncBrowserProxy} */
+/* #export */ class TestSyncBrowserProxy extends TestBrowserProxy {
+  constructor() {
+    const methodNames = [
+      'didNavigateAwayFromSyncPage',
+      'didNavigateToSyncPage',
+      'getPromoImpressionCount',
+      'getStoredAccounts',
+      'getSyncStatus',
+      'incrementPromoImpressionCount',
+      'setSyncDatatypes',
+      'setSyncEncryption',
+      'signOut',
+      'pauseSync',
+      'sendSyncPrefsChanged',
+      'startSignIn',
+      'startSyncingWithEmail',
+      'turnOnSync',
+      'turnOffSync',
+    ];
+
+    super(methodNames);
+
+    /** @private {number} */
+    this.impressionCount_ = 0;
+
+    // Settable fake data.
+    /** @type {!settings.PageStatus} */
+    this.encryptionResponse = settings.PageStatus.CONFIGURE;
+    /** @type {!Array<!settings.StoredAccount>} */
+    this.storedAccounts = [];
+    /** @type {!settings.SyncStatus} */
+    this.syncStatus = /** @type {!settings.SyncStatus} */ (
+        {signedIn: true, signedInUsername: 'fakeUsername'});
+  }
+
+
+  /** @override */
+  getSyncStatus() {
+    this.methodCalled('getSyncStatus');
+    return Promise.resolve(this.syncStatus);
+  }
+
+  /** @override */
+  getStoredAccounts() {
+    this.methodCalled('getStoredAccounts');
+    return Promise.resolve(this.storedAccounts);
+  }
+
+  /** @override */
+  signOut(deleteProfile) {
+    this.methodCalled('signOut', deleteProfile);
+  }
+
+  /** @override */
+  pauseSync() {
+    this.methodCalled('pauseSync');
+  }
+
+  /** @override */
+  startSignIn() {
+    this.methodCalled('startSignIn');
+  }
+
+  /** @override */
+  startSyncingWithEmail(email, isDefaultPromoAccount) {
+    this.methodCalled('startSyncingWithEmail', [email, isDefaultPromoAccount]);
+  }
+
+  setImpressionCount(count) {
+    this.impressionCount_ = count;
+  }
+
+  /** @override */
+  turnOnSync() {
+    this.methodCalled('turnOnSync');
+  }
+
+  /** @override */
+  turnOffSync() {
+    this.methodCalled('turnOffSync');
+  }
+
+  /** @override */
+  getPromoImpressionCount() {
+    this.methodCalled('getPromoImpressionCount');
+    return this.impressionCount_;
+  }
+
+  /** @override */
+  incrementPromoImpressionCount() {
+    this.methodCalled('incrementPromoImpressionCount');
+  }
+
+  /** @override */
+  didNavigateToSyncPage() {
+    this.methodCalled('didNavigateToSyncPage');
+  }
+
+  /** @override */
+  didNavigateAwayFromSyncPage(abort) {
+    this.methodCalled('didNavigateAwayFromSyncPage', abort);
+  }
+
+  /** @override */
+  setSyncDatatypes(syncPrefs) {
+    this.methodCalled('setSyncDatatypes', syncPrefs);
+    return Promise.resolve(settings.PageStatus.CONFIGURE);
+  }
+
+  /** @override */
+  setSyncEncryption(syncPrefs) {
+    this.methodCalled('setSyncEncryption', syncPrefs);
+    return Promise.resolve(this.encryptionResponse);
+  }
+
+  /** @override */
+  sendSyncPrefsChanged() {
+    this.methodCalled('sendSyncPrefsChanged');
+  }
+
+  /** @override */
+  attemptUserExit() {}
+
+  /** @override */
+  openActivityControlsUrl() {}
+
+  /** @override */
+  startKeyRetrieval() {}
+}
\ No newline at end of file
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.js b/chrome/test/data/webui/tab_strip/tab_list_test.js
index 752a1b1..311b8bb 100644
--- a/chrome/test/data/webui/tab_strip/tab_list_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_list_test.js
@@ -620,16 +620,6 @@
     assertEquals(tabGroup.children[1].tab.id, originalTabInGroup.id);
   });
 
-  test('HandleReplacedGroupId', () => {
-    webUIListenerCallback(
-        'tab-group-state-changed', tabs[1].id, tabs[1].index, 'oldGroupId');
-    const group = getTabGroups()[0];
-    assertEquals('oldGroupId', group.dataset.groupId);
-
-    webUIListenerCallback('tab-group-id-replaced', 'oldGroupId', 'newGroupId');
-    assertEquals('newGroupId', group.dataset.groupId);
-  });
-
   test('removes a tab when tab is removed from current window', async () => {
     const tabToRemove = tabs[0];
     webUIListenerCallback('tab-removed', tabToRemove.id);
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_test_basic_hittest_results_availability.html b/chrome/test/data/xr/e2e_test_files/html/webxr_test_basic_hittest_results_availability.html
new file mode 100644
index 0000000..4a9cab02
--- /dev/null
+++ b/chrome/test/data/xr/e2e_test_files/html/webxr_test_basic_hittest_results_availability.html
@@ -0,0 +1,104 @@
+<!--
+Tests that AR hit test results are available in rAF as soon as hit test source is available.
+-->
+<html>
+  <head>
+    <link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css">
+  </head>
+  <body>
+    <canvas id="webgl-canvas"></canvas>
+    <script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script>
+    <script src="../resources/webxr_e2e.js"></script>
+    <script>var shouldAutoCreateNonImmersiveSession = false;</script>
+    <script src="../resources/webxr_boilerplate.js"></script>
+    <script>
+      setup({single_test: true});
+
+
+      const TestState = Object.freeze({
+        "Initial":  0,
+        "RequestHitTestSource": 1,
+        "HitTestSourceRequested": 2,
+        "HitTestSourceAvailable": 3,  // hitTestSource variable is guaranteed to be non-null in this state
+        "Done": 4,
+        });
+
+      let testState = null;
+
+      let hitTestSource = null;
+
+      function stepStartHitTesting() {
+        const sessionInfo = sessionInfos[sessionTypes.AR];
+        const referenceSpace = sessionInfo.currentRefSpace;
+
+        testState = TestState.Initial;
+
+        // There is no way we can guarantee that the recording starts with a plane detected - the
+        // recording only contains sensors stream and camera images, not the ARCore session state
+        // itself. ARCore should work in exactly the same way as if it is a brand new session, so
+        // it will go through "camera not tracking" state at the beginning, on to detecting some
+        // feature points, and then to actually finding the plane. Given that, we should allow
+        // for retry logic in the test - the initial hit tests may return empty results until
+        // ARCore detects a plane.
+        let retries_left = 30;
+
+        onARFrameCallback = (session, frame) => {
+          switch(testState) {
+
+            case TestState.Initial: {
+              const pose = frame.getViewerPose(referenceSpace);
+              if(!pose || pose.emulatedPosition) {
+                // Wait for session to stabilize.
+                return;
+              }
+
+              testState = TestState.RequestHitTestSource;
+              return;
+            }
+            case TestState.RequestHitTestSource: {
+              // Try to create a hit test source from within a frame.
+              sessionInfo.currentSession.requestHitTestSource({
+                space: referenceSpace,
+                offsetRay: new XRRay()
+              }).then((hts) => {
+                hitTestSource = hts;
+                testState = TestState.HitTestSourceAvailable;
+              }).catch((err) => {
+                assert_unreached("XRSession.requestHitTestSource() promise rejected.");
+                testState = TestState.Done;
+              });
+
+              testState = TestState.HitTestSourceRequested;
+
+              return;
+            }
+            case TestState.HitTestSourceAvailable: {
+              const results = frame.getHitTestResults(hitTestSource);
+              if(results.length) {
+                testState = TestState.Done;
+                done();
+              } else {
+                --retries_left;
+                if(retries_left > 0) {
+                  // Retry.
+                  testState = TestState.RequestHitTestSource;
+                } else {
+                  assert_unreached("Hit test results were not available right after the hit test source was created.");
+                  testState = TestState.Done;
+                }
+              }
+
+              // Irrespective of the results, we won't need this hit test source anymore.
+              hitTestSource.cancel();
+              hitTestSource = null;
+
+              return;
+            }
+            default:
+              return;
+          }
+        };
+      }
+    </script>
+  </body>
+</html>
diff --git a/components/arc/mojom/payment_app.mojom b/components/arc/mojom/payment_app.mojom
index f830478..b46a1b5 100644
--- a/components/arc/mojom/payment_app.mojom
+++ b/components/arc/mojom/payment_app.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Next MinVersion: 1
+// Next MinVersion: 2
 
 module arc.mojom;
 
@@ -29,6 +29,62 @@
   string error;
 };
 
+// The common payment parameters for the browser to pass to ARC in both
+// PaymentAppInstance.IsReadyToPayService() and
+// PaymentAppInstance.InvokePaymentApp() Mojo methods. ARC will forward this
+// data to either WebPaymentIntentHelper.createIsReadyToPayIntent() or
+// WebPaymentIntentHelper.createPayIntent(), depending on which method of
+// PaymentApp Mojo IPC service was invoked.
+//
+// WebPaymentIntentHelper in ARC should be used only with the
+// "https://play.google.com/billing" payment method identifier at this time.
+struct PaymentParameters {
+  // The TWA package name, e.g., "com.example.app". This is the "String
+  // packageName" parameter to createIsReadyToPayIntent() and createPayIntent()
+  // methods.
+  string package_name;
+
+  // The name of the IS_READY_TO_PAY service to query or PAY activity to invoke,
+  // depending on whether this struct is passed into IsReadyToPay() or
+  // InvokePaymentApp() method. For example,
+  // "com.example.app.IsReadyToPayService" or "com.example.app.PaymentActivity".
+  // This is the "String serviceName" parameter to createIsReadyToPayIntent() or
+  // "String activityName" parameter to createPayIntent().
+  string activity_or_service_name;
+
+  // The JSON serialization of the JavaScript object "data" in the
+  // PaymentRequest API. For example:
+  //
+  //  {"productId": "test_product_id"}
+  //
+  // This string is serialized in Blink and is parsed in the TWA. The browser
+  // does not parse this string. This string goes into the value of the
+  // "methodDataMap" parameter of createIsReadyToPayIntent() and
+  // createPayIntent() methods, i.e.:
+  //
+  //  methodDataMap.put("https://play.google.com/billing",
+  //                    new PaymentMethodData("https://play.google.com/billing",
+  //                                          stringified_method_data));
+  string stringified_method_data;
+
+  // (Host, optional port) tuple that cannot be an opaque origin. For example:
+  // "shop.com". This is the "String schemelessOrigin" parameter to
+  // createIsReadyToPayIntent() and createPayIntent() methods.
+  string top_level_origin;
+
+  // (Host, optional port) tuple that cannot be an opaque origin. For
+  // example: "payment-service-provider.com". This is the "String
+  // schemelessIframeOrigin" parameter to createIsReadyToPayIntent() and
+  // createPayIntent() methods.
+  string payment_request_origin;
+};
+
+// After the browser calls IsReadyToPay(), ARC sends this back in response.
+union IsReadyToPayResult {
+  bool response;
+  string error;
+};
+
 // The service that runs in ARC and allows the browser to invoke the TWA payment
 // app that is installed in ARC, if it implements payment intents as described
 // in https://web.dev/android-payment-apps-overview/. At first, only
@@ -43,7 +99,7 @@
 // |                  |      |                                                |
 // --------------------      --------------------------------------------------
 //
-// Next method ID: 1
+// Next method ID: 2
 interface PaymentAppInstance {
   // Called by the browser to check whether the TWA with |package_name| (e.g.,
   // "com.example.app") in ARC has intent filters for
@@ -59,4 +115,12 @@
   // incognito mode or guest mode.
   IsPaymentImplemented@0(string package_name)
       => (IsPaymentImplementedResult response);
+
+  // Forwards the request to IsReadyToPayServiceHelper.query(), which queries
+  // the payment app. The payment app should return true if payments can be
+  // made. This should not be invoked when off the record, e.g., incognito mode
+  // or guest mode.
+  [MinVersion=1]
+  IsReadyToPay@1(PaymentParameters parameters)
+      => (IsReadyToPayResult result);
 };
diff --git a/components/arc/pay/arc_payment_app_bridge.cc b/components/arc/pay/arc_payment_app_bridge.cc
index c6dffd31..535fbcb 100644
--- a/components/arc/pay/arc_payment_app_bridge.cc
+++ b/components/arc/pay/arc_payment_app_bridge.cc
@@ -73,4 +73,17 @@
   payment_app->IsPaymentImplemented(package_name, std::move(callback));
 }
 
+void ArcPaymentAppBridge::IsReadyToPay(mojom::PaymentParametersPtr parameters,
+                                       IsReadyToPayCallback callback) {
+  mojom::PaymentAppInstance* payment_app = ARC_GET_INSTANCE_FOR_METHOD(
+      arc_bridge_service_->payment_app(), IsReadyToPay);
+  if (!payment_app) {
+    std::move(callback).Run(
+        mojom::IsReadyToPayResult::NewError(kUnableToConnectErrorMessage));
+    return;
+  }
+
+  payment_app->IsReadyToPay(std::move(parameters), std::move(callback));
+}
+
 }  // namespace arc
diff --git a/components/arc/pay/arc_payment_app_bridge.h b/components/arc/pay/arc_payment_app_bridge.h
index 961e0bf..710135d 100644
--- a/components/arc/pay/arc_payment_app_bridge.h
+++ b/components/arc/pay/arc_payment_app_bridge.h
@@ -24,6 +24,8 @@
  public:
   using IsPaymentImplementedCallback =
       base::OnceCallback<void(mojom::IsPaymentImplementedResultPtr)>;
+  using IsReadyToPayCallback =
+      base::OnceCallback<void(mojom::IsReadyToPayResultPtr)>;
 
   // Returns the instance owned by the given BrowserContext, or nullptr if the
   // browser |context| is not allowed to use ARC.
@@ -47,6 +49,11 @@
   void IsPaymentImplemented(const std::string& package_name,
                             IsPaymentImplementedCallback callback);
 
+  // Queries the TWA payment app whether it is able to perform a payment. Should
+  // not be invoked when off the record, e.g., incognito mode or guest mode.
+  void IsReadyToPay(mojom::PaymentParametersPtr parameters,
+                    IsReadyToPayCallback callback);
+
  private:
   ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager.
 };
diff --git a/components/arc/pay/arc_payment_app_bridge_unittest.cc b/components/arc/pay/arc_payment_app_bridge_unittest.cc
index 3cc35612..2a44b65 100644
--- a/components/arc/pay/arc_payment_app_bridge_unittest.cc
+++ b/components/arc/pay/arc_payment_app_bridge_unittest.cc
@@ -22,6 +22,9 @@
       IsPaymentImplemented,
       void(const std::string& package_name,
            ArcPaymentAppBridge::IsPaymentImplementedCallback callback));
+  MOCK_METHOD2(IsReadyToPay,
+               void(mojom::PaymentParametersPtr,
+                    ArcPaymentAppBridge::IsReadyToPayCallback));
 };
 
 class ArcPaymentAppBridgeTest : public testing::Test {
@@ -38,6 +41,10 @@
     is_implemented_ = std::move(response);
   }
 
+  void OnIsReadyToPayResponse(mojom::IsReadyToPayResultPtr response) {
+    is_ready_to_pay_ = std::move(response);
+  }
+
   // The |manager_| must be used on the same thread as where it was created, so
   // create it in the test instead of using ArcServiceManager::Get().
   ArcServiceManager manager_;
@@ -51,6 +58,7 @@
   TestBrowserContext context_;
 
   mojom::IsPaymentImplementedResultPtr is_implemented_;
+  mojom::IsReadyToPayResultPtr is_ready_to_pay_;
 };
 
 class ScopedSetInstance {
@@ -165,5 +173,65 @@
   EXPECT_EQ("Error message.", is_implemented_->get_error());
 }
 
+TEST_F(ArcPaymentAppBridgeTest, UnableToConnectInIsReadyToPay) {
+  // Intentionally do not set an instance.
+
+  EXPECT_CALL(instance_, IsReadyToPay(testing::_, testing::_)).Times(0);
+
+  ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_)->IsReadyToPay(
+      mojom::PaymentParameters::New(),
+      base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse,
+                     base::Unretained(this)));
+
+  ASSERT_FALSE(is_ready_to_pay_.is_null());
+  EXPECT_FALSE(is_ready_to_pay_->is_response());
+  ASSERT_TRUE(is_ready_to_pay_->is_error());
+  EXPECT_EQ("Unable to invoke Android apps.", is_ready_to_pay_->get_error());
+}
+
+TEST_F(ArcPaymentAppBridgeTest, IsReadyToPay) {
+  ScopedSetInstance scoped_set_instance(&manager_, &instance_);
+
+  EXPECT_CALL(instance_, IsReadyToPay(testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [](mojom::PaymentParametersPtr parameters,
+             ArcPaymentAppBridge::IsReadyToPayCallback callback) {
+            std::move(callback).Run(
+                mojom::IsReadyToPayResult::NewResponse(true));
+          }));
+
+  ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_)->IsReadyToPay(
+      mojom::PaymentParameters::New(),
+      base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse,
+                     base::Unretained(this)));
+
+  ASSERT_FALSE(is_ready_to_pay_.is_null());
+  EXPECT_FALSE(is_ready_to_pay_->is_error());
+  ASSERT_TRUE(is_ready_to_pay_->is_response());
+  EXPECT_TRUE(is_ready_to_pay_->get_response());
+}
+
+TEST_F(ArcPaymentAppBridgeTest, IsNotReadyToPay) {
+  ScopedSetInstance scoped_set_instance(&manager_, &instance_);
+
+  EXPECT_CALL(instance_, IsReadyToPay(testing::_, testing::_))
+      .WillOnce(testing::Invoke(
+          [](mojom::PaymentParametersPtr parameters,
+             ArcPaymentAppBridge::IsReadyToPayCallback callback) {
+            std::move(callback).Run(
+                mojom::IsReadyToPayResult::NewResponse(false));
+          }));
+
+  ArcPaymentAppBridge::GetForBrowserContextForTesting(&context_)->IsReadyToPay(
+      mojom::PaymentParameters::New(),
+      base::BindOnce(&ArcPaymentAppBridgeTest::OnIsReadyToPayResponse,
+                     base::Unretained(this)));
+
+  ASSERT_FALSE(is_ready_to_pay_.is_null());
+  EXPECT_FALSE(is_ready_to_pay_->is_error());
+  ASSERT_TRUE(is_ready_to_pay_->is_response());
+  EXPECT_FALSE(is_ready_to_pay_->get_response());
+}
+
 }  // namespace
 }  // namespace arc
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc
index d9c71a9..517d7448 100644
--- a/components/autofill/core/common/autofill_payments_features.cc
+++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -31,7 +31,7 @@
 // If enabled, when a server card is unmasked, its info will be cached until
 // page navigation to simplify consecutive fills on the same page.
 const base::Feature kAutofillCacheServerCardInfo{
-    "AutofillCacheServerCardInfo", base::FEATURE_DISABLED_BY_DEFAULT};
+    "AutofillCacheServerCardInfo", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kAutofillCreditCardAblationExperiment{
     "AutofillCreditCardAblationExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/autofill_assistant/browser/retry_timer.cc b/components/autofill_assistant/browser/retry_timer.cc
index 482a4d7..1e0cd04 100644
--- a/components/autofill_assistant/browser/retry_timer.cc
+++ b/components/autofill_assistant/browser/retry_timer.cc
@@ -25,7 +25,7 @@
   task_ = std::move(task);
   on_done_ = std::move(on_done);
   remaining_attempts_ =
-      base::ClampAdd(1, std::max(int64_t{0}, max_wait_time / period_));
+      base::ClampAdd(1, std::max(int64_t{0}, max_wait_time.IntDiv(period_)));
   RunTask();
 }
 
diff --git a/components/history/core/browser/expire_history_backend.cc b/components/history/core/browser/expire_history_backend.cc
index 222ad98..80f5458 100644
--- a/components/history/core/browser/expire_history_backend.cc
+++ b/components/history/core/browser/expire_history_backend.cc
@@ -318,7 +318,7 @@
   if (!expire_visits_time.is_zero()) {
     UMA_HISTOGRAM_PERCENTAGE(
         "History.ExpireVisits.GetRedirectsDurationPercentage",
-        get_redirects_time * 100 / expire_visits_time);
+        (get_redirects_time * 100).IntDiv(expire_visits_time));
   }
 }
 
diff --git a/components/ntp_snippets/category_rankers/click_based_category_ranker.cc b/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
index e1e84b0..f6708c6 100644
--- a/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
+++ b/components/ntp_snippets/category_rankers/click_based_category_ranker.cc
@@ -455,7 +455,7 @@
   }
   DCHECK_LE(last_decay, now);
 
-  int num_pending_decays = (now - last_decay) / kTimeBetweenDecays;
+  int num_pending_decays = (now - last_decay).IntDiv(kTimeBetweenDecays);
   int executed_decays = 0;
   while (executed_decays < num_pending_decays && IsEnoughClicksToDecay()) {
     for (RankedCategory& ranked_category : ordered_categories_) {
diff --git a/components/offline_pages/core/prefetch/store/prefetch_downloader_quota.cc b/components/offline_pages/core/prefetch/store/prefetch_downloader_quota.cc
index 46f2c6fd6..043cc85 100644
--- a/components/offline_pages/core/prefetch/store/prefetch_downloader_quota.cc
+++ b/components/offline_pages/core/prefetch/store/prefetch_downloader_quota.cc
@@ -85,9 +85,9 @@
       store_utils::FromDatabaseTime(statement.ColumnInt64(0));
   int64_t available_quota = statement.ColumnInt64(1);
 
-  int64_t remaining_quota =
-      available_quota +
-      (GetMaxDailyQuotaBytes() * (clock_->Now() - update_time)) / kQuotaPeriod;
+  int64_t remaining_quota = available_quota + (GetMaxDailyQuotaBytes() *
+                                               (clock_->Now() - update_time))
+                                                  .IntDiv(kQuotaPeriod);
 
   if (remaining_quota < 0)
     SetAvailableQuotaBytes(0);
diff --git a/components/prerender/browser/BUILD.gn b/components/prerender/browser/BUILD.gn
index 049f2e5..d28b73c 100644
--- a/components/prerender/browser/BUILD.gn
+++ b/components/prerender/browser/BUILD.gn
@@ -10,6 +10,8 @@
     "prerender_histograms.h",
     "prerender_history.cc",
     "prerender_history.h",
+    "prerender_util.cc",
+    "prerender_util.h",
   ]
 
   deps = [
@@ -18,12 +20,17 @@
     "//components/prerender/common:mojo_bindings",
     "//net",
     "//ui/gfx/geometry",
+    "//ui/gfx/image/mojom:mojom_traits",
+    "//url",
   ]
 }
 
 source_set("unit_tests") {
   testonly = true
-  sources = [ "prerender_history_unittest.cc" ]
+  sources = [
+    "prerender_history_unittest.cc",
+    "prerender_util_unittest.cc",
+  ]
 
   deps = [
     ":browser",
@@ -31,5 +38,6 @@
     "//base/test:test_support",
     "//google_apis:google_apis",
     "//testing/gtest",
+    "//url:url",
   ]
 }
diff --git a/chrome/browser/prerender/prerender_util.cc b/components/prerender/browser/prerender_util.cc
similarity index 77%
rename from chrome/browser/prerender/prerender_util.cc
rename to components/prerender/browser/prerender_util.cc
index 93ac2a0..51c8cf8 100644
--- a/chrome/browser/prerender/prerender_util.cc
+++ b/components/prerender/browser/prerender_util.cc
@@ -2,19 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prerender/prerender_util.h"
+#include "components/prerender/browser/prerender_util.h"
 
 #include "base/metrics/histogram_macros.h"
 #include "components/google/core/common/google_util.h"
-#include "content/public/common/url_constants.h"
-#include "extensions/buildflags/buildflags.h"
 #include "url/gurl.h"
 #include "url/url_constants.h"
 
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-#include "extensions/common/constants.h"
-#endif
-
 namespace prerender {
 
 bool IsGoogleOriginURL(const GURL& origin_url) {
diff --git a/chrome/browser/prerender/prerender_util.h b/components/prerender/browser/prerender_util.h
similarity index 76%
rename from chrome/browser/prerender/prerender_util.h
rename to components/prerender/browser/prerender_util.h
index bf7dd9d..2acd6d4 100644
--- a/chrome/browser/prerender/prerender_util.h
+++ b/components/prerender/browser/prerender_util.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_UTIL_H_
-#define CHROME_BROWSER_PRERENDER_PRERENDER_UTIL_H_
+#ifndef COMPONENTS_PRERENDER_BROWSER_PRERENDER_UTIL_H_
+#define COMPONENTS_PRERENDER_BROWSER_PRERENDER_UTIL_H_
 
 class GURL;
 
@@ -20,4 +20,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_BROWSER_PRERENDER_PRERENDER_UTIL_H_
+#endif  // COMPONENTS_PRERENDER_BROWSER_PRERENDER_UTIL_H_
diff --git a/chrome/browser/prerender/prerender_util_unittest.cc b/components/prerender/browser/prerender_util_unittest.cc
similarity index 95%
rename from chrome/browser/prerender/prerender_util_unittest.cc
rename to components/prerender/browser/prerender_util_unittest.cc
index 3cba3ee..9cfc4df 100644
--- a/chrome/browser/prerender/prerender_util_unittest.cc
+++ b/components/prerender/browser/prerender_util_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/prerender/prerender_util.h"
+#include "components/prerender/browser/prerender_util.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
diff --git a/components/sessions/core/tab_restore_service_client.h b/components/sessions/core/tab_restore_service_client.h
index 0b39b19e..5cc2fa3 100644
--- a/components/sessions/core/tab_restore_service_client.h
+++ b/components/sessions/core/tab_restore_service_client.h
@@ -19,6 +19,10 @@
 class Rect;
 }
 
+namespace tab_groups {
+class TabGroupId;
+}
+
 namespace sessions {
 
 class LiveTab;
@@ -54,6 +58,11 @@
   // or null if there is no such instance.
   virtual LiveTabContext* FindLiveTabContextWithID(SessionID desired_id) = 0;
 
+  // Returns the LiveTabContext instance that contains the group with ID
+  // |group|, or null if there is no such instance.
+  virtual LiveTabContext* FindLiveTabContextWithGroup(
+      tab_groups::TabGroupId group) = 0;
+
   // Returns whether a given URL should be tracked for restoring.
   virtual bool ShouldTrackURLForRestore(const GURL& url) = 0;
 
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc
index 40a8726..097d63c 100644
--- a/components/sessions/core/tab_restore_service_helper.cc
+++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -620,9 +620,21 @@
         tab.user_agent_override);
   } else {
     // We only respect the tab's original browser if there's no disposition.
-    if (disposition == WindowOpenDisposition::UNKNOWN && tab.browser_id) {
-      context = client_->FindLiveTabContextWithID(
-          SessionID::FromSerializedValue(tab.browser_id));
+    if (disposition == WindowOpenDisposition::UNKNOWN) {
+      if (tab.browser_id) {
+        context = client_->FindLiveTabContextWithID(
+            SessionID::FromSerializedValue(tab.browser_id));
+      }
+
+      // Restore a grouped tab into its original group, even if the group has
+      // since been moved to a different context. If the original group doesn't
+      // exist any more, fall back to using the tab's original browser.
+      if (tab.group.has_value()) {
+        LiveTabContext* group_context =
+            client_->FindLiveTabContextWithGroup(tab.group.value());
+        if (group_context)
+          context = group_context;
+      }
     }
 
     int tab_index = -1;
diff --git a/components/viz/common/frame_sinks/begin_frame_source.cc b/components/viz/common/frame_sinks/begin_frame_source.cc
index e3bd48a..a9ac4739 100644
--- a/components/viz/common/frame_sinks/begin_frame_source.cc
+++ b/components/viz/common/frame_sinks/begin_frame_source.cc
@@ -132,7 +132,8 @@
   constexpr double kErrorMarginIntervalPct = 0.05;
   base::TimeDelta error_margin = vsync_interval * kErrorMarginIntervalPct;
   int ticks_since_estimated_frame_time =
-      (frame_time + error_margin - next_expected_frame_time) / vsync_interval;
+      (frame_time + error_margin - next_expected_frame_time)
+          .IntDiv(vsync_interval);
   return std::max(0, ticks_since_estimated_frame_time);
 }
 
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 40eb566..14a7bad 100644
--- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
+#include "build/chromecast_buildflags.h"
 #include "content/browser/accessibility/browser_accessibility.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -1062,6 +1063,7 @@
   const char url_str[] =
       R"HTML(data:text/html,<!DOCTYPE html>
         <html>
+          <div style="margin-top: 100px;"></div>
           <input type="datetime-local" aria-label="datetime"
                  aria-controls="button1">
           <button id="button1">button</button>
@@ -1126,6 +1128,13 @@
         manager->GetFromID(controls_ids[1]);
     ASSERT_NE(nullptr, popup_area);
     EXPECT_EQ(ax::mojom::Role::kRootWebArea, popup_area->GetRole());
+
+#if !BUILDFLAG(IS_CHROMECAST)
+    // Ensure that the bounding box of the popup area is at least 100
+    // pixels down the page.
+    gfx::Rect popup_bounds = popup_area->GetUnclippedRootFrameBoundsRect();
+    EXPECT_GT(popup_bounds.y(), 100);
+#endif
   }
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 9b0365f..3add8324 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -632,6 +632,14 @@
   }
 }
 
+// Returns the crash key string used for logging BeginNavigation calls'
+// initiators.
+base::debug::CrashKeyString* GetBeginNavigationInitiatorCrashKeyString() {
+  static auto* initiator_key_string = base::debug::AllocateCrashKeyString(
+      "begin_navigation_initiator", base::debug::CrashKeySize::Size256);
+  return initiator_key_string;
+}
+
 }  // namespace
 
 bool ShouldCreateNewHostForCrashedFrame() {
@@ -5014,6 +5022,14 @@
                "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
                common_params->url.possibly_invalid_spec());
 
+  // TODO(crbug.com/1111735): Temporary debugging aids; remove after
+  // investigating the crash described in this bug.
+  ScopedActiveURL scoped_active_url(common_params->url,
+                                    frame_tree()->root()->current_origin());
+  url::debug::ScopedOriginCrashKey begin_navigation_initiator_key(
+      GetBeginNavigationInitiatorCrashKeyString(),
+      base::OptionalOrNullptr(common_params->initiator_origin));
+
   DCHECK(navigation_client.is_valid());
 
   mojom::CommonNavigationParamsPtr validated_params = common_params.Clone();
@@ -5033,6 +5049,24 @@
     RenderFrameHostImpl* parent = GetParent();
     if (!parent->IsFeatureEnabled(
             blink::mojom::FeaturePolicyFeature::kTrustTokenRedemption)) {
+      // Temporary debugging aid for crbug.com/1111735, where it seems the
+      // renderer containing the iframe prompting the navigation sometimes does
+      // have a feature policy but |parent| does not have the feature policy:
+      static auto* parent_and_initiator_are_same_crash_key_string =
+          base::debug::AllocateCrashKeyString(
+              "parent_and_initiator_are_same",
+              base::debug::CrashKeySize::Size32);
+
+      // (This frame should have the same process ID as the source of the
+      // BeginNavigation.)
+      bool parent_and_initiator_are_same =
+          (parent->GetRoutingID() == begin_params->initiator_routing_id) &&
+          (parent->GetProcess()->GetID() == GetProcess()->GetID());
+
+      base::debug::ScopedCrashKeyString parent_and_initiator_are_same_key(
+          parent_and_initiator_are_same_crash_key_string,
+          parent_and_initiator_are_same ? "true" : "false");
+
       mojo::ReportBadMessage(
           "RFHI: Mandatory Trust Tokens Feature Policy feature is absent");
       return;
diff --git a/content/browser/renderer_host/frame_token_message_queue.cc b/content/browser/renderer_host/frame_token_message_queue.cc
index 72f07c45..5bb83c8 100644
--- a/content/browser/renderer_host/frame_token_message_queue.cc
+++ b/content/browser/renderer_host/frame_token_message_queue.cc
@@ -5,7 +5,6 @@
 #include "content/browser/renderer_host/frame_token_message_queue.h"
 
 #include "base/bind.h"
-#include "ipc/ipc_message.h"
 
 namespace content {
 
@@ -63,27 +62,10 @@
   callback_map_.insert(std::make_pair(frame_token, std::move(callback)));
 }
 
-void FrameTokenMessageQueue::OnFrameSwapMessagesReceived(
-    uint32_t frame_token,
-    std::vector<IPC::Message> messages) {
-  EnqueueOrRunFrameTokenCallback(
-      frame_token, base::BindOnce(&FrameTokenMessageQueue::ProcessSwapMessages,
-                                  base::Unretained(this), std::move(messages)));
-}
-
 void FrameTokenMessageQueue::Reset() {
   last_received_frame_token_reset_ = last_received_frame_token_;
   last_received_frame_token_ = 0;
   callback_map_.clear();
 }
 
-void FrameTokenMessageQueue::ProcessSwapMessages(
-    std::vector<IPC::Message> messages) {
-  for (const IPC::Message& i : messages) {
-    client_->OnProcessSwapMessage(i);
-    if (i.dispatch_error())
-      client_->OnMessageDispatchError(i);
-  }
-}
-
 }  // namespace content
diff --git a/content/browser/renderer_host/frame_token_message_queue.h b/content/browser/renderer_host/frame_token_message_queue.h
index e8b256d..166ccd0 100644
--- a/content/browser/renderer_host/frame_token_message_queue.h
+++ b/content/browser/renderer_host/frame_token_message_queue.h
@@ -12,10 +12,6 @@
 #include "base/macros.h"
 #include "content/common/content_export.h"
 
-namespace IPC {
-class Message;
-}  // namespace IPC
-
 namespace content {
 
 // The Renderer sends various messages which are not to be processed until after
@@ -25,29 +21,19 @@
 // Viz processes the frames, after which it notifies the Browser of which
 // FrameToken has completed processing.
 //
-// This enqueues all IPC::Messages associated with a FrameToken.
+// Non-IPC callbacks can be enqueued with EnqueueOrRunFrameTokenCallback.
 //
-// Additionally other callbacks can be enqueued with
-// EnqueueOrRunFrameTokenCallback.
-//
-// Upon receipt of DidProcessFrame all IPC::Messages associated with the
-// provided FrameToken are then dispatched, and all enqueued callbacks are ran.
+// Upon receipt of DidProcessFrame all Messages associated with the provided
+// FrameToken are then dispatched, and all enqueued callbacks are ran.
 class CONTENT_EXPORT FrameTokenMessageQueue {
  public:
-  // Notified of errors in processing messages, as well as of the actual
-  // enqueued IPC::Messages which need processing.
+  // Notified of errors in processing messages.
   class Client {
    public:
     ~Client() {}
 
     // Notified when an invalid frame token was received.
     virtual void OnInvalidFrameToken(uint32_t frame_token) = 0;
-
-    // Called when there are dispatching errors in OnMessageReceived().
-    virtual void OnMessageDispatchError(const IPC::Message& message) = 0;
-
-    // Process the enqueued message.
-    virtual void OnProcessSwapMessage(const IPC::Message& message) = 0;
   };
   FrameTokenMessageQueue();
   virtual ~FrameTokenMessageQueue();
@@ -66,21 +52,12 @@
   void EnqueueOrRunFrameTokenCallback(uint32_t frame_token,
                                       base::OnceClosure callback);
 
-  // Enqueues the swap messages.
-  void OnFrameSwapMessagesReceived(uint32_t frame_token,
-                                   std::vector<IPC::Message> messages);
-
   // Called when the renderer process is gone. This will reset our state to be
   // consistent incase a new renderer is created.
   void Reset();
 
   size_t size() const { return callback_map_.size(); }
 
- protected:
-  // Once both the frame and its swap messages arrive, we call this method to
-  // process the messages. Virtual for tests.
-  virtual void ProcessSwapMessages(std::vector<IPC::Message> messages);
-
  private:
   // Not owned.
   Client* client_ = nullptr;
diff --git a/content/browser/renderer_host/frame_token_message_queue_unittest.cc b/content/browser/renderer_host/frame_token_message_queue_unittest.cc
index da59028c..7943ecf9 100644
--- a/content/browser/renderer_host/frame_token_message_queue_unittest.cc
+++ b/content/browser/renderer_host/frame_token_message_queue_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "ipc/ipc_message.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
@@ -25,46 +24,23 @@
   // Resets all method counters.
   void Reset();
 
-  // All subsequent IPC::Messages received in OnProcessSwapMessage will be
-  // marked as having a dispatch error.
-  void SetErrorOnMessageProcess();
-
   // FrameTokenMessageQueue::Client:
   void OnInvalidFrameToken(uint32_t frame_token) override;
-  void OnMessageDispatchError(const IPC::Message& message) override;
-  void OnProcessSwapMessage(const IPC::Message& message) override;
 
   bool invalid_frame_token_called() const {
     return invalid_frame_token_called_;
   }
   uint32_t invalid_frame_token() const { return invalid_frame_token_; }
-  int on_message_dispatch_error_count() const {
-    return on_message_dispatch_error_count_;
-  }
-  int on_process_swap_message_count() const {
-    return on_process_swap_message_count_;
-  }
 
  private:
-  // If true the each IPC::Message received will be marked as having a dispatch
-  // error.
-  bool set_error_on_process_ = false;
   bool invalid_frame_token_called_ = false;
   uint32_t invalid_frame_token_ = 0u;
-  int on_message_dispatch_error_count_ = 0;
-  int on_process_swap_message_count_ = 0;
   DISALLOW_COPY_AND_ASSIGN(TestFrameTokenMessageQueueClient);
 };
 
 void TestFrameTokenMessageQueueClient::Reset() {
   invalid_frame_token_called_ = false;
   invalid_frame_token_ = 0u;
-  on_message_dispatch_error_count_ = 0;
-  on_process_swap_message_count_ = 0;
-}
-
-void TestFrameTokenMessageQueueClient::SetErrorOnMessageProcess() {
-  set_error_on_process_ = true;
 }
 
 void TestFrameTokenMessageQueueClient::OnInvalidFrameToken(
@@ -73,18 +49,6 @@
   invalid_frame_token_ = frame_token;
 }
 
-void TestFrameTokenMessageQueueClient::OnMessageDispatchError(
-    const IPC::Message& message) {
-  ++on_message_dispatch_error_count_;
-}
-
-void TestFrameTokenMessageQueueClient::OnProcessSwapMessage(
-    const IPC::Message& message) {
-  if (set_error_on_process_)
-    message.set_dispatch_error();
-  ++on_process_swap_message_count_;
-}
-
 // Test class which provides FrameTokenCallback() to be used as a closure when
 // enqueueing non-IPC callbacks. This only tracks if the callback was called.
 class TestNonIPCMessageEnqueuer {
@@ -133,124 +97,6 @@
   frame_token_message_queue_.Init(&test_client_);
 }
 
-// Tests that if a valid IPC::Message is enqueued, that it is processed when its
-// matching frame token arrives.
-TEST_F(FrameTokenMessageQueueTest, OnlyIPCMessageCorrectFrameToken) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  // Adding to the queue with a new frame token should not cause processing.
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  queue->DidProcessFrame(frame_token);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-}
-
-// Tests that if a valid IPC::Message is enqueued after its frame token has
-// arrived that it is processed immediately.
-TEST_F(FrameTokenMessageQueueTest, EnqueueAfterFrameTokenProcesses) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  queue->DidProcessFrame(frame_token);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-
-  // Enqueuing after frame token arrival should immediately process.
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-}
-
-// Tests that if a valid IPC::Message is enqueued and that subsequently a
-// non-IPC callback is enqueued, that both get called once the frame token
-// arrives.
-TEST_F(FrameTokenMessageQueueTest, EnqueueBothIPCMessageAndNonIPCCallback) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  TestNonIPCMessageEnqueuer* enqueuer = test_non_ipc_enqueuer();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  // Adding to the queue with a new frame token should not cause processing.
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  queue->EnqueueOrRunFrameTokenCallback(
-      frame_token,
-      base::BindOnce(&TestNonIPCMessageEnqueuer::FrameTokenCallback,
-                     base::Unretained(enqueuer)));
-  EXPECT_FALSE(enqueuer->frame_token_callback_called());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-
-  queue->DidProcessFrame(frame_token);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-  EXPECT_TRUE(enqueuer->frame_token_callback_called());
-}
-
-// Tests that if a valid non-IPC callback is enqueued before an IPC::Message,
-// that both get called once the frame token arrives.
-TEST_F(FrameTokenMessageQueueTest, EnqueueNonIPCCallbackFirst) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  TestNonIPCMessageEnqueuer* enqueuer = test_non_ipc_enqueuer();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  queue->EnqueueOrRunFrameTokenCallback(
-      frame_token,
-      base::BindOnce(&TestNonIPCMessageEnqueuer::FrameTokenCallback,
-                     base::Unretained(enqueuer)));
-  EXPECT_FALSE(enqueuer->frame_token_callback_called());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  // We should be able to enqueue even though it is for the same frame token.
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(2u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-
-  queue->DidProcessFrame(frame_token);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-  EXPECT_TRUE(enqueuer->frame_token_callback_called());
-}
-
 // Tests that if we only have a non-IPC callback enqueued that it is called once
 // the frame token arrive.
 TEST_F(FrameTokenMessageQueueTest, EnqueueOnlyNonIPC) {
@@ -264,80 +110,16 @@
       frame_token,
       base::BindOnce(&TestNonIPCMessageEnqueuer::FrameTokenCallback,
                      base::Unretained(enqueuer)));
-  EXPECT_FALSE(enqueuer->frame_token_callback_called());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
   EXPECT_EQ(1u, queue->size());
+  EXPECT_FALSE(enqueuer->frame_token_callback_called());
+  EXPECT_FALSE(client->invalid_frame_token_called());
 
   queue->DidProcessFrame(frame_token);
   EXPECT_EQ(0u, queue->size());
   EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
   EXPECT_TRUE(enqueuer->frame_token_callback_called());
 }
 
-// Tests that if we have messages enqueued, and receive a frame token that is
-// larger, that we still process the messages.
-TEST_F(FrameTokenMessageQueueTest, MessagesWhereFrameTokenSkipped) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  TestNonIPCMessageEnqueuer* enqueuer = test_non_ipc_enqueuer();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  queue->EnqueueOrRunFrameTokenCallback(
-      frame_token,
-      base::BindOnce(&TestNonIPCMessageEnqueuer::FrameTokenCallback,
-                     base::Unretained(enqueuer)));
-  EXPECT_FALSE(enqueuer->frame_token_callback_called());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  // We should be able to enqueue even though it is for the same frame token.
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(2u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-
-  const uint32_t larger_frame_token = 1337;
-  queue->DidProcessFrame(larger_frame_token);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-  EXPECT_TRUE(enqueuer->frame_token_callback_called());
-}
-
-// Verifies that if there are multiple IPC::Messages that they are all
-// processed.
-TEST_F(FrameTokenMessageQueueTest, MultipleIPCMessages) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token = 42;
-  IPC::Message msg1(0, 1, IPC::Message::PRIORITY_NORMAL);
-  IPC::Message msg2(1, 2, IPC::Message::PRIORITY_LOW);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg1);
-  messages.push_back(msg2);
-
-  // Adding to the queue with a new frame token should not cause processing.
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  // All IPCs are enqueued as one.
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  queue->DidProcessFrame(frame_token);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(2, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-}
-
 // Verifies that if there are multiple non-IPC messages enqueued that they are
 // all called.
 TEST_F(FrameTokenMessageQueueTest, MultipleNonIPCMessages) {
@@ -393,52 +175,6 @@
   EXPECT_TRUE(enqueuer->frame_token_callback_called());
 }
 
-// Tests that if IPC::Messages are enqueued for different frame tokens, that
-// we only process the messages associated with the arriving token, and keep the
-// others enqueued.
-TEST_F(FrameTokenMessageQueueTest, DifferentFrameTokensEnqueuedIPC) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token_1 = 42;
-  IPC::Message msg1(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages_1;
-  messages_1.push_back(msg1);
-
-  queue->OnFrameSwapMessagesReceived(frame_token_1, std::move(messages_1));
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  const uint32_t frame_token_2 = 1337;
-  IPC::Message msg2(1, 2, IPC::Message::PRIORITY_LOW);
-  std::vector<IPC::Message> messages_2;
-  messages_2.push_back(msg2);
-
-  queue->OnFrameSwapMessagesReceived(frame_token_2, std::move(messages_2));
-  // With no frame token yet the second set of IPC::Messages should be enqueud
-  // separately.
-  EXPECT_EQ(2u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  // We should only process the first IPC::Message.
-  queue->DidProcessFrame(frame_token_1);
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-
-  // Clear the counts from the first token.
-  client->Reset();
-
-  // The second IPC::Message should be processed.
-  queue->DidProcessFrame(frame_token_2);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
-}
-
 // Test that if non-IPC callbacks are enqueued for different frame tokens, that
 // we only process the messages associated with the arriving token, and keep the
 // others enqueued.
@@ -476,37 +212,6 @@
   EXPECT_TRUE(second_enqueuer.frame_token_callback_called());
 }
 
-
-// Tests that when adding an IPC::Message for an earlier frame token, that it is
-// enqueued.
-TEST_F(FrameTokenMessageQueueTest, EarlierTokenForIPCMessageIsNotRejected) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t valid_frame_token = 42;
-  IPC::Message msg1(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages_1;
-  messages_1.push_back(msg1);
-
-  // Adding to the queue with a new frame token should not cause processing.
-  queue->OnFrameSwapMessagesReceived(valid_frame_token, std::move(messages_1));
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  const uint32_t earlier_frame_token = 1;
-  IPC::Message msg2(1, 2, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages_2;
-  messages_2.push_back(msg1);
-
-  // Adding an earlier frame token should be enqueued.
-  queue->OnFrameSwapMessagesReceived(earlier_frame_token,
-                                     std::move(messages_2));
-  EXPECT_EQ(2u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-}
-
 // Tests that if DidProcessFrame is called with an invalid token, that it is
 // rejected, and that no callbacks are processed.
 TEST_F(FrameTokenMessageQueueTest, InvalidDidProcessFrameTokenNotProcessed) {
@@ -516,14 +221,6 @@
   ASSERT_EQ(0u, queue->size());
 
   const uint32_t frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
   queue->EnqueueOrRunFrameTokenCallback(
       frame_token,
       base::BindOnce(&TestNonIPCMessageEnqueuer::FrameTokenCallback,
@@ -534,11 +231,9 @@
   // Empty token should be invalid even with no process frames processed.
   const uint32_t invalid_frame_token = 0;
   queue->DidProcessFrame(invalid_frame_token);
-  EXPECT_EQ(2u, queue->size());
+  EXPECT_EQ(1u, queue->size());
   EXPECT_TRUE(client->invalid_frame_token_called());
   EXPECT_EQ(invalid_frame_token, client->invalid_frame_token());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
   EXPECT_FALSE(enqueuer->frame_token_callback_called());
 }
 
@@ -555,58 +250,24 @@
   queue->DidProcessFrame(earlier_frame_token);
 
   const uint32_t frame_token = 1337;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
   queue->EnqueueOrRunFrameTokenCallback(
       frame_token,
       base::BindOnce(&TestNonIPCMessageEnqueuer::FrameTokenCallback,
                      base::Unretained(enqueuer)));
   EXPECT_FALSE(enqueuer->frame_token_callback_called());
   EXPECT_FALSE(client->invalid_frame_token_called());
+  EXPECT_EQ(1u, queue->size());
 
   // Using a frame token that is earlier than the last received should be
   // rejected.
   const uint32_t invalid_frame_token = earlier_frame_token - 1;
   queue->DidProcessFrame(invalid_frame_token);
-  EXPECT_EQ(2u, queue->size());
+  EXPECT_EQ(1u, queue->size());
   EXPECT_TRUE(client->invalid_frame_token_called());
   EXPECT_EQ(invalid_frame_token, client->invalid_frame_token());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
   EXPECT_FALSE(enqueuer->frame_token_callback_called());
 }
 
-// Tests that if an IPC::Message has a dispatch error that the client is
-// notified.
-TEST_F(FrameTokenMessageQueueTest, DispatchError) {
-  FrameTokenMessageQueue* queue = frame_token_message_queue();
-  TestFrameTokenMessageQueueClient* client = test_client();
-  ASSERT_EQ(0u, queue->size());
-
-  const uint32_t frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  queue->OnFrameSwapMessagesReceived(frame_token, std::move(messages));
-  EXPECT_EQ(1u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
-  // Dispatch error should be notified during processing.
-  client->SetErrorOnMessageProcess();
-  queue->DidProcessFrame(frame_token);
-  EXPECT_EQ(0u, queue->size());
-  EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(1, client->on_message_dispatch_error_count());
-}
-
 // Tests that if we have already enqueued a callback for a frame token, that if
 // a request for an earlier frame token arrives, that it is still enqueued. Then
 // once the large frame token arrives, both are processed.
@@ -625,23 +286,10 @@
   EXPECT_FALSE(enqueuer->frame_token_callback_called());
   EXPECT_FALSE(client->invalid_frame_token_called());
 
-  const uint32_t smaller_frame_token = 42;
-  IPC::Message msg(0, 1, IPC::Message::PRIORITY_NORMAL);
-  std::vector<IPC::Message> messages;
-  messages.push_back(msg);
-
-  // Enqueuing for a smaller token, which has not yet arrived, should still
-  // enqueue.
-  queue->OnFrameSwapMessagesReceived(smaller_frame_token, std::move(messages));
-  EXPECT_EQ(2u, queue->size());
-  EXPECT_EQ(0, client->on_process_swap_message_count());
-
   // Process both with the larger frame token arriving.
   queue->DidProcessFrame(larger_frame_token);
   EXPECT_EQ(0u, queue->size());
   EXPECT_FALSE(client->invalid_frame_token_called());
-  EXPECT_EQ(1, client->on_process_swap_message_count());
-  EXPECT_EQ(0, client->on_message_dispatch_error_count());
   EXPECT_TRUE(enqueuer->frame_token_callback_called());
 }
 
diff --git a/content/browser/renderer_host/mock_render_widget_host.cc b/content/browser/renderer_host/mock_render_widget_host.cc
index fb78b02..cd0b249 100644
--- a/content/browser/renderer_host/mock_render_widget_host.cc
+++ b/content/browser/renderer_host/mock_render_widget_host.cc
@@ -7,28 +7,6 @@
 #include "components/viz/test/mock_compositor_frame_sink_client.h"
 #include "content/browser/renderer_host/frame_token_message_queue.h"
 
-namespace {
-class TestFrameTokenMessageQueue : public content::FrameTokenMessageQueue {
- public:
-  TestFrameTokenMessageQueue() = default;
-  ~TestFrameTokenMessageQueue() override = default;
-
-  uint32_t processed_frame_messages_count() {
-    return processed_frame_messages_count_;
-  }
-
- protected:
-  void ProcessSwapMessages(std::vector<IPC::Message> messages) override {
-    processed_frame_messages_count_++;
-  }
-
- private:
-  uint32_t processed_frame_messages_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(TestFrameTokenMessageQueue);
-};
-}  // namespace
-
 namespace content {
 
 MockRenderWidgetHost::~MockRenderWidgetHost() {}
@@ -59,13 +37,6 @@
   input_router_.reset(new MockInputRouter(this));
 }
 
-uint32_t MockRenderWidgetHost::processed_frame_messages_count() {
-  CHECK(frame_token_message_queue_);
-  return static_cast<TestFrameTokenMessageQueue*>(
-             frame_token_message_queue_.get())
-      ->processed_frame_messages_count();
-}
-
 // static
 MockRenderWidgetHost* MockRenderWidgetHost::Create(
     RenderWidgetHostDelegate* delegate,
@@ -106,7 +77,7 @@
                            process,
                            routing_id,
                            /*hidden=*/false,
-                           std::make_unique<TestFrameTokenMessageQueue>()),
+                           std::make_unique<FrameTokenMessageQueue>()),
       new_content_rendering_timeout_fired_(false),
       fling_scheduler_(std::make_unique<FlingScheduler>(this)) {
   acked_touch_event_type_ = blink::WebInputEvent::Type::kUndefined;
diff --git a/content/browser/renderer_host/mock_render_widget_host.h b/content/browser/renderer_host/mock_render_widget_host.h
index 8e65251..c0ac15d 100644
--- a/content/browser/renderer_host/mock_render_widget_host.h
+++ b/content/browser/renderer_host/mock_render_widget_host.h
@@ -58,8 +58,6 @@
 
   InputRouter* input_router() { return input_router_.get(); }
 
-  uint32_t processed_frame_messages_count();
-
   static MockRenderWidgetHost* Create(RenderWidgetHostDelegate* delegate,
                                       RenderProcessHost* process,
                                       int32_t routing_id);
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 35da14e..bb3479c 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -331,10 +331,10 @@
   DCHECK(GetProcess()->GetBrowserContext());
 
   // Exactly one of main_frame_routing_id_ or proxy_route_id should be set.
-  CHECK((main_frame_routing_id_ != MSG_ROUTING_NONE &&
-         proxy_route_id == MSG_ROUTING_NONE) ||
-        (main_frame_routing_id_ == MSG_ROUTING_NONE &&
-         proxy_route_id != MSG_ROUTING_NONE));
+  CHECK(!(main_frame_routing_id_ != MSG_ROUTING_NONE &&
+          proxy_route_id != MSG_ROUTING_NONE));
+  CHECK(!(main_frame_routing_id_ == MSG_ROUTING_NONE &&
+          proxy_route_id == MSG_ROUTING_NONE));
 
   RenderFrameHostImpl* main_rfh = nullptr;
   RenderFrameProxyHost* main_rfph = nullptr;
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 4de45c4..ab5991c 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -704,8 +704,6 @@
     IPC_MESSAGE_HANDLER(WidgetHostMsg_RequestSetBounds, OnRequestSetBounds)
     IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
     IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
-    IPC_MESSAGE_HANDLER(WidgetHostMsg_FrameSwapMessages,
-                        OnFrameSwapMessagesReceived)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -2044,13 +2042,6 @@
     view->UpdateDragCursor(current_op);
 }
 
-void RenderWidgetHostImpl::OnFrameSwapMessagesReceived(
-    uint32_t frame_token,
-    std::vector<IPC::Message> messages) {
-  frame_token_message_queue_->OnFrameSwapMessagesReceived(frame_token,
-                                                          std::move(messages));
-}
-
 void RenderWidgetHostImpl::RendererExited() {
   if (!renderer_initialized_)
     return;
@@ -2716,16 +2707,6 @@
                                   bad_message::RWH_INVALID_FRAME_TOKEN);
 }
 
-void RenderWidgetHostImpl::OnMessageDispatchError(const IPC::Message& message) {
-  RenderProcessHost* rph = GetProcess();
-  rph->OnBadMessageReceived(message);
-}
-
-void RenderWidgetHostImpl::OnProcessSwapMessage(const IPC::Message& message) {
-  RenderProcessHost* rph = GetProcess();
-  rph->OnMessageReceived(message);
-}
-
 bool RenderWidgetHostImpl::RequestKeyboardLock(
     base::Optional<base::flat_set<ui::DomCode>> codes) {
   if (!delegate_) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index ec4696ba..cbd65d4 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -728,8 +728,6 @@
 
   // FrameTokenMessageQueue::Client:
   void OnInvalidFrameToken(uint32_t frame_token) override;
-  void OnMessageDispatchError(const IPC::Message& message) override;
-  void OnProcessSwapMessage(const IPC::Message& message) override;
 
   void ProgressFlingIfNeeded(base::TimeTicks current_time);
   void StopFling();
@@ -919,8 +917,6 @@
                        const gfx::Vector2d& bitmap_offset_in_dip,
                        const DragEventSourceInfo& event_info);
   void OnUpdateDragCursor(blink::WebDragOperation current_op);
-  void OnFrameSwapMessagesReceived(uint32_t frame_token,
-                                   std::vector<IPC::Message> messages);
 
   // blink::mojom::FrameWidgetHost overrides.
   void AnimateDoubleTapZoomInMainFrame(const gfx::Point& tap_point,
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index be9220a..e91f614 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -2060,137 +2060,6 @@
   ASSERT_FALSE(host_->input_router()->HasPendingEvents());
 }
 
-// Check that if messages of a frame arrive earlier than the frame itself, we
-// queue the messages until the frame arrives and then process them.
-TEST_F(RenderWidgetHostTest, FrameToken_MessageThenFrame) {
-  constexpr uint32_t frame_token = 1;
-  std::vector<IPC::Message> messages;
-  messages.push_back(WidgetHostMsg_Close(5));
-
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token, messages));
-  EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  view_->OnFrameTokenChanged(frame_token);
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(1u, host_->processed_frame_messages_count());
-}
-
-// Check that if a frame arrives earlier than its messages, we process the
-// messages immedtiately.
-TEST_F(RenderWidgetHostTest, FrameToken_FrameThenMessage) {
-  constexpr uint32_t frame_token = 1;
-  std::vector<IPC::Message> messages;
-  messages.push_back(WidgetHostMsg_Close(5));
-
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  view_->OnFrameTokenChanged(frame_token);
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token, messages));
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(1u, host_->processed_frame_messages_count());
-}
-
-// Check that if messages of multiple frames arrive before the frames, we
-// process each message once it frame arrives.
-TEST_F(RenderWidgetHostTest, FrameToken_MultipleMessagesThenTokens) {
-  constexpr uint32_t frame_token1 = 1;
-  constexpr uint32_t frame_token2 = 2;
-  std::vector<IPC::Message> messages1;
-  std::vector<IPC::Message> messages2;
-  messages1.push_back(WidgetHostMsg_Close(5));
-  messages2.push_back(WidgetHostMsg_Close(6));
-
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
-  EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token2, messages2));
-  EXPECT_EQ(2u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  view_->OnFrameTokenChanged(frame_token1);
-  EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(1u, host_->processed_frame_messages_count());
-  view_->OnFrameTokenChanged(frame_token2);
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(2u, host_->processed_frame_messages_count());
-}
-
-// Check that if multiple frames arrive before their messages, each message is
-// processed immediately as soon as it arrives.
-TEST_F(RenderWidgetHostTest, FrameToken_MultipleTokensThenMessages) {
-  constexpr uint32_t frame_token1 = 1;
-  constexpr uint32_t frame_token2 = 2;
-  std::vector<IPC::Message> messages1;
-  std::vector<IPC::Message> messages2;
-  messages1.push_back(WidgetHostMsg_Close(5));
-  messages2.push_back(WidgetHostMsg_Close(6));
-
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  view_->OnFrameTokenChanged(frame_token1);
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  view_->OnFrameTokenChanged(frame_token2);
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(1u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token2, messages2));
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(2u, host_->processed_frame_messages_count());
-}
-
-// Check that if one frame is lost but its messages arrive, we process the
-// messages on the arrival of the next frame.
-TEST_F(RenderWidgetHostTest, FrameToken_DroppedFrame) {
-  constexpr uint32_t frame_token1 = 1;
-  constexpr uint32_t frame_token2 = 2;
-  std::vector<IPC::Message> messages1;
-  std::vector<IPC::Message> messages2;
-  messages1.push_back(WidgetHostMsg_Close(5));
-  messages2.push_back(WidgetHostMsg_Close(6));
-
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token1, messages1));
-  EXPECT_EQ(1u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  host_->OnMessageReceived(
-      WidgetHostMsg_FrameSwapMessages(0, frame_token2, messages2));
-  EXPECT_EQ(2u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(0u, host_->processed_frame_messages_count());
-
-  view_->OnFrameTokenChanged(frame_token2);
-  EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
-  EXPECT_EQ(2u, host_->processed_frame_messages_count());
-}
-
 // If a navigation happens while the widget is hidden, we shouldn't show
 // contents of the previous page when we become visible.
 TEST_F(RenderWidgetHostTest, NavigateInBackgroundShowsBlank) {
diff --git a/content/browser/scheduler/responsiveness/calculator.cc b/content/browser/scheduler/responsiveness/calculator.cc
index 72da57e..02d8708 100644
--- a/content/browser/scheduler/responsiveness/calculator.cc
+++ b/content/browser/scheduler/responsiveness/calculator.cc
@@ -48,7 +48,7 @@
   // Find each janky slice, and add it to |janky_slices|.
   while (jank_start < jank_end) {
     // Convert |jank_start| to a slice label.
-    int64_t label = (jank_start - start_time) / kJankThreshold;
+    int64_t label = (jank_start - start_time).IntDiv(kJankThreshold);
     janky_slices->insert(label);
 
     jank_start += kJankThreshold;
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h
index 43dd821..e8a1e83 100644
--- a/content/common/widget_messages.h
+++ b/content/common/widget_messages.h
@@ -71,12 +71,6 @@
 IPC_MESSAGE_ROUTED1(WidgetMsg_SetViewportIntersection,
                     blink::ViewportIntersectionState /* intersection_state */)
 
-
-// Sent by the browser to synchronize with the next compositor frame by
-// requesting an ACK be queued. Used only for tests.
-IPC_MESSAGE_ROUTED1(WidgetMsg_WaitForNextFrameForTests,
-                    int /* main_frame_thread_observer_routing_id */)
-
 //
 // Renderer -> Browser Messages.
 //
@@ -92,20 +86,8 @@
 // APIs, and the browser may ignore this message.
 IPC_MESSAGE_ROUTED1(WidgetHostMsg_RequestSetBounds, gfx::Rect /* bounds */)
 
-// Sends a set of queued messages that were being held until the next
-// CompositorFrame is being submitted from the renderer. These messages are
-// sent before the OnRenderFrameMetadataChanged message is sent (via mojo) and
-// before the CompositorFrame is sent to the viz service. The |frame_token|
-// will match the token in the about-to-be-submitted CompositorFrame.
-IPC_MESSAGE_ROUTED2(WidgetHostMsg_FrameSwapMessages,
-                    uint32_t /* frame_token */,
-                    std::vector<IPC::Message> /* messages */)
-
 // Indicates that the render widget has been closed in response to a
 // Close message.
 IPC_MESSAGE_CONTROL1(WidgetHostMsg_Close_ACK, int /* old_route_id */)
 
-// Sent in reply to WidgetMsg_WaitForNextFrameForTests.
-IPC_MESSAGE_ROUTED0(WidgetHostMsg_WaitForNextFrameForTests_ACK)
-
 #endif  //  CONTENT_COMMON_WIDGET_MESSAGES_H_
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index b8d0ab4..d377d21 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -2635,40 +2635,25 @@
 MainThreadFrameObserver::MainThreadFrameObserver(
     RenderWidgetHost* render_widget_host)
     : render_widget_host_(render_widget_host),
-      routing_id_(render_widget_host_->GetProcess()->GetNextRoutingID()) {
-  // TODO(lfg): We should look into adding a way to observe RenderWidgetHost
-  // messages similarly to what WebContentsObserver can do with RFH and RVW.
-  render_widget_host_->GetProcess()->AddRoute(routing_id_, this);
-}
+      routing_id_(render_widget_host_->GetProcess()->GetNextRoutingID()) {}
 
-MainThreadFrameObserver::~MainThreadFrameObserver() {
-  render_widget_host_->GetProcess()->RemoveRoute(routing_id_);
-}
+MainThreadFrameObserver::~MainThreadFrameObserver() = default;
 
 void MainThreadFrameObserver::Wait() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  render_widget_host_->Send(new WidgetMsg_WaitForNextFrameForTests(
-      render_widget_host_->GetRoutingID(), routing_id_));
+  static_cast<RenderWidgetHostImpl*>(render_widget_host_)
+      ->InsertVisualStateCallback(base::BindOnce(&MainThreadFrameObserver::Quit,
+                                                 base::Unretained(this)));
   base::RunLoop run_loop;
   quit_closure_ = run_loop.QuitClosure();
   run_loop.Run();
 }
 
-void MainThreadFrameObserver::Quit() {
+void MainThreadFrameObserver::Quit(bool) {
   if (quit_closure_)
     std::move(quit_closure_).Run();
 }
 
-bool MainThreadFrameObserver::OnMessageReceived(const IPC::Message& msg) {
-  if (msg.type() == WidgetHostMsg_WaitForNextFrameForTests_ACK::ID &&
-      msg.routing_id() == routing_id_) {
-    GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&MainThreadFrameObserver::Quit, base::Unretained(this)));
-  }
-  return true;
-}
-
 InputMsgWatcher::InputMsgWatcher(RenderWidgetHost* render_widget_host,
                                  blink::WebInputEvent::Type type)
     : render_widget_host_(render_widget_host),
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index 49ef8c989..2ef08b4 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -1308,20 +1308,17 @@
 // So while the ACK can arrive before a CompositorFrame submission occurs. The
 // processing does not occur until after the FrameToken for that frame
 // submission arrives to the main thread.
-class MainThreadFrameObserver : public IPC::Listener {
+class MainThreadFrameObserver {
  public:
   explicit MainThreadFrameObserver(RenderWidgetHost* render_widget_host);
-  ~MainThreadFrameObserver() override;
+  ~MainThreadFrameObserver();
 
   // Synchronizes the browser main thread with the renderer main thread and impl
   // thread.
   void Wait();
 
-  // Overridden IPC::Listener methods.
-  bool OnMessageReceived(const IPC::Message& msg) override;
-
  private:
-  void Quit();
+  void Quit(bool);
 
   RenderWidgetHost* render_widget_host_;
   base::OnceClosure quit_closure_;
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 484b5e0..fe96c236 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -74,8 +74,6 @@
     "frame_blame_context.h",
     "frame_owner_properties_converter.cc",
     "frame_owner_properties_converter.h",
-    "frame_swap_message_queue.cc",
-    "frame_swap_message_queue.h",
     "gpu_benchmarking_extension.cc",
     "gpu_benchmarking_extension.h",
     "history_entry.cc",
@@ -193,8 +191,6 @@
     "performance_manager/v8_per_frame_memory_reporter_impl.h",
     "peripheral_content_heuristic.cc",
     "peripheral_content_heuristic.h",
-    "queue_message_swap_promise.cc",
-    "queue_message_swap_promise.h",
     "render_frame_impl.cc",
     "render_frame_impl.h",
     "render_frame_metadata_observer_impl.cc",
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink_impl.cc b/content/renderer/android/synchronous_layer_tree_frame_sink_impl.cc
index 2883b6e..e84687d4 100644
--- a/content/renderer/android/synchronous_layer_tree_frame_sink_impl.cc
+++ b/content/renderer/android/synchronous_layer_tree_frame_sink_impl.cc
@@ -34,7 +34,6 @@
 #include "content/common/android/sync_compositor_statics.h"
 #include "content/common/view_messages.h"
 #include "content/public/common/content_switches.h"
-#include "content/renderer/frame_swap_message_queue.h"
 #include "content/renderer/render_thread_impl.h"
 #include "gpu/command_buffer/client/context_support.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -154,7 +153,6 @@
     uint32_t layer_tree_frame_sink_id,
     std::unique_ptr<viz::BeginFrameSource> synthetic_begin_frame_source,
     blink::SynchronousCompositorRegistry* registry,
-    scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
     mojo::PendingRemote<viz::mojom::CompositorFrameSink>
         compositor_frame_sink_remote,
     mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
@@ -167,7 +165,6 @@
       registry_(registry),
       sender_(sender),
       memory_policy_(0u),
-      frame_swap_message_queue_(frame_swap_message_queue),
       unbound_compositor_frame_sink_(std::move(compositor_frame_sink_remote)),
       unbound_client_(std::move(client_receiver)),
       synthetic_begin_frame_source_(std::move(synthetic_begin_frame_source)),
@@ -555,17 +552,6 @@
   DCHECK(CalledOnValidThread());
   if (sync_client_)
     sync_client_->DidActivatePendingTree();
-  DeliverMessages();
-}
-
-void SynchronousLayerTreeFrameSinkImpl::DeliverMessages() {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  std::unique_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
-      frame_swap_message_queue_->AcquireSendMessageScope();
-  frame_swap_message_queue_->DrainMessages(&messages);
-  for (auto& msg : messages) {
-    Send(msg.release());
-  }
 }
 
 bool SynchronousLayerTreeFrameSinkImpl::Send(IPC::Message* message) {
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink_impl.h b/content/renderer/android/synchronous_layer_tree_frame_sink_impl.h
index f640c139..cae9af0e 100644
--- a/content/renderer/android/synchronous_layer_tree_frame_sink_impl.h
+++ b/content/renderer/android/synchronous_layer_tree_frame_sink_impl.h
@@ -54,8 +54,6 @@
 
 namespace content {
 
-class FrameSwapMessageQueue;
-
 // Specialization of the output surface that adapts it to implement the
 // content::SynchronousCompositor public API. This class effects an "inversion
 // of control" - enabling drawing to be  orchestrated by the embedding
@@ -78,7 +76,6 @@
       uint32_t layer_tree_frame_sink_id,
       std::unique_ptr<viz::BeginFrameSource> begin_frame_source,
       blink::SynchronousCompositorRegistry* registry,
-      scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
       mojo::PendingRemote<viz::mojom::CompositorFrameSink>
           compositor_frame_sink_remote,
       mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
@@ -157,7 +154,6 @@
   cc::ManagedMemoryPolicy memory_policy_;
   bool in_software_draw_ = false;
   bool did_submit_frame_ = false;
-  scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
 
   mojo::PendingRemote<viz::mojom::CompositorFrameSink>
       unbound_compositor_frame_sink_;
diff --git a/content/renderer/compositor/compositor_dependencies.h b/content/renderer/compositor/compositor_dependencies.h
index c820413..766f795 100644
--- a/content/renderer/compositor/compositor_dependencies.h
+++ b/content/renderer/compositor/compositor_dependencies.h
@@ -35,7 +35,6 @@
 }  // namespace blink
 
 namespace content {
-class FrameSwapMessageQueue;
 class RenderWidget;
 
 class CONTENT_EXPORT CompositorDependencies {
@@ -57,7 +56,6 @@
       std::unique_ptr<cc::RenderFrameMetadataObserver>)>;
   virtual void RequestNewLayerTreeFrameSink(
       RenderWidget* render_widget,
-      scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
       const GURL& url,
       LayerTreeFrameSinkCallback callback,
       const char* client_name) = 0;
diff --git a/content/renderer/frame_swap_message_queue.cc b/content/renderer/frame_swap_message_queue.cc
deleted file mode 100644
index d85fe70..0000000
--- a/content/renderer/frame_swap_message_queue.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/frame_swap_message_queue.h"
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <utility>
-
-#include "base/check.h"
-#include "base/macros.h"
-#include "base/stl_util.h"
-#include "ipc/ipc_message.h"
-
-namespace content {
-
-class FrameSwapMessageSubQueue {
- public:
-  FrameSwapMessageSubQueue() {}
-  virtual ~FrameSwapMessageSubQueue() {}
-  virtual bool Empty() const = 0;
-  virtual void QueueMessage(int source_frame_number,
-                            std::unique_ptr<IPC::Message> msg,
-                            bool* is_first) = 0;
-  virtual void DrainMessages(
-      int source_frame_number,
-      std::vector<std::unique_ptr<IPC::Message>>* messages) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(FrameSwapMessageSubQueue);
-};
-
-namespace {
-
-class SendMessageScopeImpl : public FrameSwapMessageQueue::SendMessageScope {
- public:
-  SendMessageScopeImpl(base::Lock* lock) : auto_lock_(*lock) {}
-  ~SendMessageScopeImpl() override {}
-
- private:
-  base::AutoLock auto_lock_;
-};
-
-class VisualStateQueue : public FrameSwapMessageSubQueue {
- public:
-  VisualStateQueue() = default;
-
-  ~VisualStateQueue() override = default;
-
-  bool Empty() const override { return queue_.empty(); }
-
-  void QueueMessage(int source_frame_number,
-                    std::unique_ptr<IPC::Message> msg,
-                    bool* is_first) override {
-    if (is_first)
-      *is_first = (queue_.count(source_frame_number) == 0);
-
-    queue_[source_frame_number].push_back(std::move(msg));
-  }
-
-  void DrainMessages(
-      int source_frame_number,
-      std::vector<std::unique_ptr<IPC::Message>>* messages) override {
-    auto end = queue_.upper_bound(source_frame_number);
-    for (auto i = queue_.begin(); i != end; i++) {
-      DCHECK(i->first <= source_frame_number);
-      std::move(i->second.begin(), i->second.end(),
-                std::back_inserter(*messages));
-    }
-    queue_.erase(queue_.begin(), end);
-  }
-
- private:
-  std::map<int, std::vector<std::unique_ptr<IPC::Message>>> queue_;
-
-  DISALLOW_COPY_AND_ASSIGN(VisualStateQueue);
-};
-
-}  // namespace
-
-FrameSwapMessageQueue::FrameSwapMessageQueue(int32_t routing_id)
-    : visual_state_queue_(new VisualStateQueue()), routing_id_(routing_id) {
-  DETACH_FROM_THREAD(impl_thread_checker_);
-}
-
-FrameSwapMessageQueue::~FrameSwapMessageQueue() {}
-
-bool FrameSwapMessageQueue::Empty() const {
-  base::AutoLock lock(lock_);
-  return next_drain_messages_.empty() && visual_state_queue_->Empty();
-}
-
-void FrameSwapMessageQueue::QueueMessageForFrame(
-    int source_frame_number,
-    std::unique_ptr<IPC::Message> msg,
-    bool* is_first) {
-  base::AutoLock lock(lock_);
-  visual_state_queue_->QueueMessage(source_frame_number, std::move(msg),
-                                    is_first);
-}
-
-void FrameSwapMessageQueue::DidActivate(int source_frame_number) {
-  base::AutoLock lock(lock_);
-  visual_state_queue_->DrainMessages(source_frame_number,
-                                     &next_drain_messages_);
-}
-
-void FrameSwapMessageQueue::DidSwap(int source_frame_number) {}
-
-cc::SwapPromise::DidNotSwapAction FrameSwapMessageQueue::DidNotSwap(
-    int source_frame_number,
-    cc::SwapPromise::DidNotSwapReason reason,
-    std::vector<std::unique_ptr<IPC::Message>>* messages) {
-  base::AutoLock lock(lock_);
-  switch (reason) {
-    case cc::SwapPromise::SWAP_FAILS:
-    case cc::SwapPromise::COMMIT_NO_UPDATE:
-      DrainMessages(messages);
-      visual_state_queue_->DrainMessages(source_frame_number, messages);
-      return cc::SwapPromise::DidNotSwapAction::BREAK_PROMISE;
-    case cc::SwapPromise::COMMIT_FAILS:
-      return cc::SwapPromise::DidNotSwapAction::KEEP_ACTIVE;
-    case cc::SwapPromise::ACTIVATION_FAILS:
-      // Do not queue any responses or return KEEP_ALIVE here. If
-      // ACTIVATION_FAILS the renderer is shutting down, which will result
-      // in the RenderFrameHostImpl destructor firing the remaining
-      // response callbacks itself.
-      return cc::SwapPromise::DidNotSwapAction::BREAK_PROMISE;
-  }
-}
-
-void FrameSwapMessageQueue::DrainMessages(
-    std::vector<std::unique_ptr<IPC::Message>>* messages) {
-  lock_.AssertAcquired();
-  std::move(next_drain_messages_.begin(), next_drain_messages_.end(),
-            std::back_inserter(*messages));
-  next_drain_messages_.clear();
-}
-
-std::unique_ptr<FrameSwapMessageQueue::SendMessageScope>
-FrameSwapMessageQueue::AcquireSendMessageScope() {
-  return std::make_unique<SendMessageScopeImpl>(&lock_);
-}
-
-// static
-void FrameSwapMessageQueue::TransferMessages(
-    std::vector<std::unique_ptr<IPC::Message>>* source,
-    std::vector<IPC::Message>* dest) {
-  for (const auto& msg : *source) {
-    dest->push_back(*msg.get());
-  }
-  source->clear();
-}
-
-}  // namespace content
diff --git a/content/renderer/frame_swap_message_queue.h b/content/renderer/frame_swap_message_queue.h
deleted file mode 100644
index 3220f22..0000000
--- a/content/renderer/frame_swap_message_queue.h
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_FRAME_SWAP_MESSAGE_QUEUE_H_
-#define CONTENT_RENDERER_FRAME_SWAP_MESSAGE_QUEUE_H_
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/auto_reset.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
-#include "cc/trees/swap_promise.h"
-#include "content/common/content_export.h"
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-
-class FrameSwapMessageSubQueue;
-
-// Queue used to keep track of which IPC::Messages should be sent after a
-// particular compositor frame swap. The messages are guaranteed to be processed
-// after the frame is processed, but there is no guarantee that nothing else
-// happens between processing the frame and processing the messages.
-class CONTENT_EXPORT FrameSwapMessageQueue
-    : public base::RefCountedThreadSafe<FrameSwapMessageQueue> {
- public:
-  class CONTENT_EXPORT SendMessageScope {
-   public:
-    virtual ~SendMessageScope() {}
-  };
-
-  explicit FrameSwapMessageQueue(int32_t routing_id);
-
-  // Queues message to be returned on a matching DrainMessages call.
-  //
-  // |source_frame_number| frame number to queue |msg| for.
-  // |msg| - message to queue. The method takes ownership of |msg|.
-  // |is_first| - output parameter. Set to true if this was the first message
-  //              enqueued for the given source_frame_number.
-  void QueueMessageForFrame(int source_frame_number,
-                            std::unique_ptr<IPC::Message> msg,
-                            bool* is_first);
-
-  // Returns true if there are no messages in the queue.
-  bool Empty() const;
-
-  // Should be called when a successful activation occurs. The messages for
-  // that activation can be obtained by calling DrainMessages.
-  //
-  // |source_frame_number| frame number for which the activate occurred.
-  void DidActivate(int source_frame_number);
-
-  // Should be called when a successful swap occurs. The messages for that
-  // swap can be obtained by calling DrainMessages.
-  //
-  // |source_frame_number| frame number for which the swap occurred.
-  void DidSwap(int source_frame_number);
-
-  // Should be called when we know a swap will not occur.
-  //
-  // |source_frame_number| frame number for which the swap will not occur.
-  // |reason| reason for the which the swap will not occur.
-  // |messages| depending on |reason| it may make sense to deliver certain
-  //            messages asynchronously. This vector will contain those
-  //            messages.
-  cc::SwapPromise::DidNotSwapAction DidNotSwap(
-      int source_frame_number,
-      cc::SwapPromise::DidNotSwapReason reason,
-      std::vector<std::unique_ptr<IPC::Message>>* messages);
-
-  // A SendMessageScope object must be held by the caller when this method is
-  // called.
-  //
-  // |messages| vector to store messages, it's not cleared, only appended to.
-  //            The method will append messages queued for frame numbers lower
-  //            or equal to |source_frame_number|
-  void DrainMessages(std::vector<std::unique_ptr<IPC::Message>>* messages);
-
-  // SendMessageScope is used to make sure that messages sent from different
-  // threads (impl/main) are scheduled in the right order on the IO threads.
-  //
-  // Returns an object that must be kept in scope till an IPC message containing
-  // |messages| is sent.
-  std::unique_ptr<SendMessageScope> AcquireSendMessageScope();
-
-  static void TransferMessages(
-      std::vector<std::unique_ptr<IPC::Message>>* source,
-      std::vector<IPC::Message>* dest);
-
-  int32_t routing_id() const { return routing_id_; }
-
- private:
-  friend class base::RefCountedThreadSafe<FrameSwapMessageQueue>;
-
-  ~FrameSwapMessageQueue();
-
-  mutable base::Lock lock_;
-  std::unique_ptr<FrameSwapMessageSubQueue> visual_state_queue_;
-  std::vector<std::unique_ptr<IPC::Message>> next_drain_messages_;
-  int32_t routing_id_ = 0;
-  THREAD_CHECKER(impl_thread_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(FrameSwapMessageQueue);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_FRAME_SWAP_MESSAGE_QUEUE_H_
diff --git a/content/renderer/frame_swap_message_queue_unittest.cc b/content/renderer/frame_swap_message_queue_unittest.cc
deleted file mode 100644
index 0282e46..0000000
--- a/content/renderer/frame_swap_message_queue_unittest.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/frame_swap_message_queue.h"
-
-#include <utility>
-
-#include "ipc/ipc_message.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class FrameSwapMessageQueueTest : public testing::Test {
- public:
-  FrameSwapMessageQueueTest()
-      : first_message_(41, 1, IPC::Message::PRIORITY_NORMAL),
-        second_message_(42, 2, IPC::Message::PRIORITY_NORMAL),
-        third_message_(43, 3, IPC::Message::PRIORITY_NORMAL),
-        queue_(new FrameSwapMessageQueue(0)) {}
-
- protected:
-  void QueueNextSwapMessage(std::unique_ptr<IPC::Message> msg) {
-    queue_->QueueMessageForFrame(0, std::move(msg), nullptr);
-  }
-
-  void QueueNextSwapMessage(std::unique_ptr<IPC::Message> msg, bool* first) {
-    queue_->QueueMessageForFrame(0, std::move(msg), first);
-  }
-
-  void QueueVisualStateMessage(int source_frame_number,
-                               std::unique_ptr<IPC::Message> msg) {
-    queue_->QueueMessageForFrame(source_frame_number, std::move(msg), nullptr);
-  }
-
-  void QueueVisualStateMessage(int source_frame_number,
-                               std::unique_ptr<IPC::Message> msg,
-                               bool* first) {
-    queue_->QueueMessageForFrame(source_frame_number, std::move(msg), first);
-  }
-
-  void DrainMessages(int source_frame_number,
-                     std::vector<std::unique_ptr<IPC::Message>>* messages) {
-    messages->clear();
-    queue_->DidActivate(source_frame_number);
-    queue_->DidSwap(source_frame_number);
-    std::unique_ptr<FrameSwapMessageQueue::SendMessageScope>
-        send_message_scope = queue_->AcquireSendMessageScope();
-    queue_->DrainMessages(messages);
-  }
-
-  bool HasMessageForId(
-      const std::vector<std::unique_ptr<IPC::Message>>& messages,
-      int routing_id) {
-    for (const auto& msg : messages) {
-      if (msg->routing_id() == routing_id)
-        return true;
-    }
-    return false;
-  }
-
-  std::unique_ptr<IPC::Message> CloneMessage(const IPC::Message& other) {
-    return std::make_unique<IPC::Message>(other);
-  }
-
-  void TestDidNotSwap(cc::SwapPromise::DidNotSwapReason reason);
-
-  IPC::Message first_message_;
-  IPC::Message second_message_;
-  IPC::Message third_message_;
-  scoped_refptr<FrameSwapMessageQueue> queue_;
-};
-
-TEST_F(FrameSwapMessageQueueTest, TestEmptyQueueDrain) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-
-  DrainMessages(0, &messages);
-  ASSERT_TRUE(messages.empty());
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestEmpty) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  ASSERT_TRUE(queue_->Empty());
-  QueueNextSwapMessage(CloneMessage(first_message_));
-  ASSERT_FALSE(queue_->Empty());
-  DrainMessages(0, &messages);
-  ASSERT_TRUE(queue_->Empty());
-  QueueVisualStateMessage(1, CloneMessage(first_message_));
-  ASSERT_FALSE(queue_->Empty());
-  queue_->DidActivate(1);
-  queue_->DidSwap(1);
-  ASSERT_FALSE(queue_->Empty());
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestQueueMessageFirst) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  bool visual_state_first = false;
-  bool next_swap_first = false;
-
-  // Queuing the first time should result in true.
-  QueueVisualStateMessage(1, CloneMessage(first_message_), &visual_state_first);
-  ASSERT_TRUE(visual_state_first);
-  // Queuing the second time should result in true.
-  QueueVisualStateMessage(1, CloneMessage(second_message_),
-                          &visual_state_first);
-  ASSERT_FALSE(visual_state_first);
-  // Queuing for a different frame should result in true.
-  QueueVisualStateMessage(2, CloneMessage(first_message_), &visual_state_first);
-  ASSERT_TRUE(visual_state_first);
-
-  // Queuing for a different policy should result in true.
-  QueueNextSwapMessage(CloneMessage(first_message_), &next_swap_first);
-  ASSERT_TRUE(next_swap_first);
-  // Second time for the same policy is still false.
-  QueueNextSwapMessage(CloneMessage(first_message_), &next_swap_first);
-  ASSERT_FALSE(next_swap_first);
-
-  DrainMessages(4, &messages);
-  // Queuing after all messages are drained is a true again.
-  QueueVisualStateMessage(4, CloneMessage(first_message_), &visual_state_first);
-  ASSERT_TRUE(visual_state_first);
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestNextSwapMessageSentWithNextFrame) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-
-  DrainMessages(1, &messages);
-  QueueNextSwapMessage(CloneMessage(first_message_));
-  DrainMessages(2, &messages);
-  ASSERT_EQ(1u, messages.size());
-  ASSERT_EQ(first_message_.routing_id(), messages.front()->routing_id());
-  messages.clear();
-
-  DrainMessages(2, &messages);
-  ASSERT_TRUE(messages.empty());
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestNextSwapMessageSentWithCurrentFrame) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-
-  DrainMessages(1, &messages);
-  QueueNextSwapMessage(CloneMessage(first_message_));
-  DrainMessages(1, &messages);
-  ASSERT_EQ(1u, messages.size());
-  ASSERT_EQ(first_message_.routing_id(), messages.front()->routing_id());
-  messages.clear();
-
-  DrainMessages(1, &messages);
-  ASSERT_TRUE(messages.empty());
-}
-
-TEST_F(FrameSwapMessageQueueTest,
-       TestDrainsVisualStateMessagesForCorrespondingFrames) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-
-  QueueVisualStateMessage(1, CloneMessage(first_message_));
-  QueueVisualStateMessage(2, CloneMessage(second_message_));
-  QueueVisualStateMessage(3, CloneMessage(third_message_));
-  DrainMessages(0, &messages);
-  ASSERT_TRUE(messages.empty());
-
-  DrainMessages(2, &messages);
-  ASSERT_EQ(2u, messages.size());
-  ASSERT_TRUE(HasMessageForId(messages, first_message_.routing_id()));
-  ASSERT_TRUE(HasMessageForId(messages, second_message_.routing_id()));
-  messages.clear();
-
-  DrainMessages(2, &messages);
-  ASSERT_TRUE(messages.empty());
-
-  DrainMessages(5, &messages);
-  ASSERT_EQ(1u, messages.size());
-  ASSERT_EQ(third_message_.routing_id(), messages.front()->routing_id());
-}
-
-TEST_F(FrameSwapMessageQueueTest,
-       TestQueueNextSwapMessagePreservesFifoOrdering) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-
-  QueueNextSwapMessage(CloneMessage(first_message_));
-  QueueNextSwapMessage(CloneMessage(second_message_));
-  DrainMessages(1, &messages);
-  ASSERT_EQ(2u, messages.size());
-  ASSERT_EQ(first_message_.routing_id(), messages[0]->routing_id());
-  ASSERT_EQ(second_message_.routing_id(), messages[1]->routing_id());
-}
-
-TEST_F(FrameSwapMessageQueueTest,
-       TestQueueVisualStateMessagePreservesFifoOrdering) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-
-  QueueVisualStateMessage(1, CloneMessage(first_message_));
-  QueueVisualStateMessage(1, CloneMessage(second_message_));
-  DrainMessages(1, &messages);
-  ASSERT_EQ(2u, messages.size());
-  ASSERT_EQ(first_message_.routing_id(), messages[0]->routing_id());
-  ASSERT_EQ(second_message_.routing_id(), messages[1]->routing_id());
-}
-
-void FrameSwapMessageQueueTest::TestDidNotSwap(
-    cc::SwapPromise::DidNotSwapReason reason) {
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-
-  QueueNextSwapMessage(CloneMessage(first_message_));
-  QueueVisualStateMessage(2, CloneMessage(second_message_));
-  QueueVisualStateMessage(3, CloneMessage(third_message_));
-  const int rid[] = {first_message_.routing_id(), second_message_.routing_id(),
-                     third_message_.routing_id()};
-
-  bool msg_delivered = reason != cc::SwapPromise::COMMIT_FAILS &&
-                       reason != cc::SwapPromise::ACTIVATION_FAILS;
-
-  queue_->DidNotSwap(2, reason, &messages);
-  ASSERT_TRUE(msg_delivered == HasMessageForId(messages, rid[0]));
-  ASSERT_TRUE(msg_delivered == HasMessageForId(messages, rid[1]));
-  ASSERT_FALSE(HasMessageForId(messages, rid[2]));
-  messages.clear();
-
-  queue_->DidNotSwap(3, reason, &messages);
-  ASSERT_FALSE(HasMessageForId(messages, rid[0]));
-  ASSERT_FALSE(HasMessageForId(messages, rid[1]));
-  ASSERT_TRUE(msg_delivered == HasMessageForId(messages, rid[2]));
-  messages.clear();
-
-  // all undelivered messages should still be available for RenderFrameHostImpl
-  // to deliver.
-  DrainMessages(3, &messages);
-  ASSERT_TRUE(msg_delivered != HasMessageForId(messages, rid[0]));
-  ASSERT_TRUE(msg_delivered != HasMessageForId(messages, rid[1]));
-  ASSERT_TRUE(msg_delivered != HasMessageForId(messages, rid[2]));
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestDidNotSwapNoUpdate) {
-  TestDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestDidNotSwapSwapFails) {
-  TestDidNotSwap(cc::SwapPromise::SWAP_FAILS);
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestDidNotSwapCommitFails) {
-  TestDidNotSwap(cc::SwapPromise::COMMIT_FAILS);
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestDidNotSwapActivationFails) {
-  TestDidNotSwap(cc::SwapPromise::ACTIVATION_FAILS);
-}
-
-class NotifiesDeletionMessage : public IPC::Message {
- public:
-  NotifiesDeletionMessage(bool* deleted, const IPC::Message& other)
-      : IPC::Message(other), deleted_(deleted) {}
-  ~NotifiesDeletionMessage() override { *deleted_ = true; }
-
- private:
-  bool* deleted_;
-};
-
-TEST_F(FrameSwapMessageQueueTest, TestDeletesNextSwapMessage) {
-  bool message_deleted = false;
-  QueueNextSwapMessage(std::make_unique<NotifiesDeletionMessage>(
-      &message_deleted, first_message_));
-  queue_ = nullptr;
-  ASSERT_TRUE(message_deleted);
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestDeletesVisualStateMessage) {
-  bool message_deleted = false;
-  QueueVisualStateMessage(1, std::make_unique<NotifiesDeletionMessage>(
-                                 &message_deleted, first_message_));
-  queue_ = nullptr;
-  ASSERT_TRUE(message_deleted);
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestDeletesQueuedVisualStateMessage) {
-  bool message_deleted = false;
-  QueueVisualStateMessage(1, std::make_unique<NotifiesDeletionMessage>(
-                                 &message_deleted, first_message_));
-  queue_->DidActivate(1);
-  queue_->DidSwap(1);
-  queue_ = nullptr;
-  ASSERT_TRUE(message_deleted);
-}
-
-TEST_F(FrameSwapMessageQueueTest, TestDrainsMessageOnActivationThanDidNotSwap) {
-  const int frame = 6;
-  std::unique_ptr<IPC::Message> msg = CloneMessage(first_message_);
-  IPC::Message* msgSent = msg.get();
-  QueueVisualStateMessage(frame, std::move(msg));
-  queue_->DidActivate(frame);
-  EXPECT_TRUE(!queue_->Empty());
-
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  queue_->DidNotSwap(frame, cc::SwapPromise::SWAP_FAILS, &messages);
-  CHECK_EQ(1UL, messages.size());
-  EXPECT_EQ(messages[0].get(), msgSent);
-  msgSent = nullptr;
-
-  queue_ = nullptr;
-}
-
-}  // namespace content
diff --git a/content/renderer/queue_message_swap_promise.cc b/content/renderer/queue_message_swap_promise.cc
deleted file mode 100644
index ccf8d41..0000000
--- a/content/renderer/queue_message_swap_promise.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/queue_message_swap_promise.h"
-
-#include <memory>
-
-#include "base/command_line.h"
-#include "content/common/widget_messages.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/renderer/render_thread.h"
-#include "content/renderer/frame_swap_message_queue.h"
-#include "ipc/ipc_sync_message_filter.h"
-
-namespace content {
-
-QueueMessageSwapPromise::QueueMessageSwapPromise(
-    scoped_refptr<IPC::SyncMessageFilter> message_sender,
-    scoped_refptr<content::FrameSwapMessageQueue> message_queue,
-    int source_frame_number)
-    : message_sender_(message_sender),
-      message_queue_(message_queue),
-      source_frame_number_(source_frame_number)
-{
-  DCHECK(message_sender_.get());
-  DCHECK(message_queue_.get());
-}
-
-QueueMessageSwapPromise::~QueueMessageSwapPromise() {
-}
-
-void QueueMessageSwapPromise::DidActivate() {
-  message_queue_->DidActivate(source_frame_number_);
-  // The OutputSurface will take care of the Drain+Send.
-}
-
-void QueueMessageSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) {
-  message_queue_->DidSwap(source_frame_number_);
-
-  std::unique_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
-      message_queue_->AcquireSendMessageScope();
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  message_queue_->DrainMessages(&messages);
-
-  std::vector<IPC::Message> messages_to_send;
-  FrameSwapMessageQueue::TransferMessages(&messages, &messages_to_send);
-  if (!messages_to_send.empty()) {
-    metadata->send_frame_token_to_embedder = true;
-    message_sender_->Send(new WidgetHostMsg_FrameSwapMessages(
-        message_queue_->routing_id(), metadata->frame_token, messages_to_send));
-  }
-}
-
-void QueueMessageSwapPromise::DidSwap() {}
-
-cc::SwapPromise::DidNotSwapAction QueueMessageSwapPromise::DidNotSwap(
-    DidNotSwapReason reason) {
-  // TODO(eseckler): Deliver messages with the next swap instead of sending
-  // them here directly.
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  cc::SwapPromise::DidNotSwapAction action =
-      message_queue_->DidNotSwap(source_frame_number_, reason, &messages);
-  for (auto& msg : messages) {
-    message_sender_->Send(msg.release());
-  }
-  return action;
-}
-
-int64_t QueueMessageSwapPromise::TraceId() const {
-  return 0;
-}
-
-}  // namespace content
diff --git a/content/renderer/queue_message_swap_promise.h b/content/renderer/queue_message_swap_promise.h
deleted file mode 100644
index 2c31b90..0000000
--- a/content/renderer/queue_message_swap_promise.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_QUEUE_MESSAGE_SWAP_PROMISE_H_
-#define CONTENT_RENDERER_QUEUE_MESSAGE_SWAP_PROMISE_H_
-
-#include <stdint.h>
-
-#include "base/memory/ref_counted.h"
-#include "cc/trees/swap_promise.h"
-
-namespace IPC {
-class SyncMessageFilter;
-}
-
-namespace content {
-
-class FrameSwapMessageQueue;
-
-class QueueMessageSwapPromise : public cc::SwapPromise {
- public:
-  QueueMessageSwapPromise(scoped_refptr<IPC::SyncMessageFilter> message_sender,
-                          scoped_refptr<FrameSwapMessageQueue> message_queue,
-                          int source_frame_number);
-
-  ~QueueMessageSwapPromise() override;
-
-  void DidActivate() override;
-  void WillSwap(viz::CompositorFrameMetadata* metadata) override;
-  void DidSwap() override;
-  DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override;
-
-  int64_t TraceId() const override;
-
- private:
-  scoped_refptr<IPC::SyncMessageFilter> message_sender_;
-  scoped_refptr<content::FrameSwapMessageQueue> message_queue_;
-  int source_frame_number_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_QUEUE_MESSAGE_SWAP_PROMISE_H_
diff --git a/content/renderer/queue_message_swap_promise_unittest.cc b/content/renderer/queue_message_swap_promise_unittest.cc
deleted file mode 100644
index f9cb7f1..0000000
--- a/content/renderer/queue_message_swap_promise_unittest.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/queue_message_swap_promise.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/test/task_environment.h"
-#include "cc/trees/swap_promise.h"
-#include "content/common/render_frame_metadata.mojom.h"
-#include "content/common/widget_messages.h"
-#include "content/renderer/frame_swap_message_queue.h"
-#include "content/renderer/render_widget.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_sync_message_filter.h"
-#include "ipc/ipc_test_sink.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class TestSyncMessageFilter : public IPC::SyncMessageFilter {
- public:
-  TestSyncMessageFilter() : IPC::SyncMessageFilter(nullptr) {}
-
-  bool Send(IPC::Message* message) override {
-    if (message->type() == WidgetHostMsg_FrameSwapMessages::ID) {
-      WidgetHostMsg_FrameSwapMessages::Param param;
-      WidgetHostMsg_FrameSwapMessages::Read(message, &param);
-      std::vector<IPC::Message> messages = std::get<1>(param);
-      last_swap_messages_.clear();
-      for (const IPC::Message& message : messages) {
-        last_swap_messages_.push_back(std::make_unique<IPC::Message>(message));
-      }
-      delete message;
-    } else {
-      direct_send_messages_.push_back(base::WrapUnique(message));
-    }
-    return true;
-  }
-
-  std::vector<std::unique_ptr<IPC::Message>>& last_swap_messages() {
-    return last_swap_messages_;
-  }
-
-  const std::vector<std::unique_ptr<IPC::Message>>& direct_send_messages() {
-    return direct_send_messages_;
-  }
-
- private:
-  ~TestSyncMessageFilter() override {}
-
-  std::vector<std::unique_ptr<IPC::Message>> direct_send_messages_;
-  std::vector<std::unique_ptr<IPC::Message>> last_swap_messages_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSyncMessageFilter);
-};
-
-class QueueMessageSwapPromiseTest : public testing::Test {
- public:
-  QueueMessageSwapPromiseTest()
-      : frame_swap_message_queue_(new FrameSwapMessageQueue(0)),
-        sync_message_filter_(new TestSyncMessageFilter()) {}
-
-  ~QueueMessageSwapPromiseTest() override {}
-
-  std::unique_ptr<cc::SwapPromise> QueueMessageImpl(
-      std::unique_ptr<IPC::Message> msg,
-      int source_frame_number) {
-    return RenderWidget::QueueMessageImpl(
-        std::move(msg), frame_swap_message_queue_.get(), sync_message_filter_,
-        source_frame_number);
-  }
-
-  const std::vector<std::unique_ptr<IPC::Message>>& DirectSendMessages() {
-    return sync_message_filter_->direct_send_messages();
-  }
-
-  std::vector<std::unique_ptr<IPC::Message>>& LastSwapMessages() {
-    return sync_message_filter_->last_swap_messages();
-  }
-
-  std::vector<std::unique_ptr<IPC::Message>>& NextSwapMessages() {
-    next_swap_messages_.clear();
-    std::unique_ptr<FrameSwapMessageQueue::SendMessageScope>
-        send_message_scope =
-            frame_swap_message_queue_->AcquireSendMessageScope();
-    frame_swap_message_queue_->DrainMessages(&next_swap_messages_);
-    return next_swap_messages_;
-  }
-
-  bool ContainsMessage(
-      const std::vector<std::unique_ptr<IPC::Message>>& messages,
-      const IPC::Message& message) {
-    if (messages.empty())
-      return false;
-    for (const auto& msg : messages) {
-      if (msg->type() == message.type())
-        return true;
-    }
-    return false;
-  }
-
-  bool LastSwapHasMessage(const IPC::Message& message) {
-    return ContainsMessage(LastSwapMessages(), message);
-  }
-
-  bool NextSwapHasMessage(const IPC::Message& message) {
-    return ContainsMessage(NextSwapMessages(), message);
-  }
-
-  void QueueMessages(int source_frame_numbers[], size_t count) {
-    for (size_t i = 0; i < count; ++i) {
-      messages_.push_back(
-          IPC::Message(0, i + 1, IPC::Message::PRIORITY_NORMAL));
-      promises_.push_back(
-          QueueMessageImpl(std::make_unique<IPC::Message>(messages_[i]),
-                           source_frame_numbers[i]));
-    }
-  }
-
-  void CleanupPromises() {
-    for (const auto& promise : promises_) {
-      if (promise.get()) {
-        promise->DidActivate();
-        promise->WillSwap(&dummy_metadata_);
-        promise->DidSwap();
-      }
-    }
-  }
-
- protected:
-  void VisualStateSwapPromiseDidNotSwap(
-      cc::SwapPromise::DidNotSwapReason reason);
-
-  base::test::TaskEnvironment task_environment_;
-  scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
-  scoped_refptr<TestSyncMessageFilter> sync_message_filter_;
-  std::vector<IPC::Message> messages_;
-  std::vector<std::unique_ptr<cc::SwapPromise>> promises_;
-  viz::CompositorFrameMetadata dummy_metadata_;
-  cc::RenderFrameMetadata dummy_render_frame_metadata_;
-
- private:
-  std::vector<std::unique_ptr<IPC::Message>> next_swap_messages_;
-
-  DISALLOW_COPY_AND_ASSIGN(QueueMessageSwapPromiseTest);
-};
-
-TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySchedulesMessageForNextSwap) {
-  int source_frame_numbers[] = {1};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  ASSERT_TRUE(promises_[0].get());
-  promises_[0]->DidActivate();
-  promises_[0]->WillSwap(&dummy_metadata_);
-  promises_[0]->DidSwap();
-
-  EXPECT_TRUE(DirectSendMessages().empty());
-  EXPECT_TRUE(frame_swap_message_queue_->Empty());
-  EXPECT_TRUE(LastSwapHasMessage(messages_[0]));
-}
-
-TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicyNeedsAtMostOnePromise) {
-  int source_frame_numbers[] = {1, 1};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  ASSERT_TRUE(promises_[0].get());
-  ASSERT_FALSE(promises_[1].get());
-
-  CleanupPromises();
-}
-
-TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnNoUpdate) {
-  int source_frame_numbers[] = {1};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
-  EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
-  EXPECT_TRUE(LastSwapMessages().empty());
-  EXPECT_TRUE(frame_swap_message_queue_->Empty());
-}
-
-TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySendsMessageOnSwapFails) {
-  int source_frame_numbers[] = {1};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  promises_[0]->DidNotSwap(cc::SwapPromise::SWAP_FAILS);
-  EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[0]));
-  EXPECT_TRUE(LastSwapMessages().empty());
-  EXPECT_TRUE(frame_swap_message_queue_->Empty());
-}
-
-TEST_F(QueueMessageSwapPromiseTest,
-       NextActivatePolicyRetainsMessageOnCommitFails) {
-  int source_frame_numbers[] = {1};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  promises_[0]->DidNotSwap(cc::SwapPromise::COMMIT_FAILS);
-  EXPECT_TRUE(DirectSendMessages().empty());
-  EXPECT_TRUE(LastSwapMessages().empty());
-  EXPECT_FALSE(frame_swap_message_queue_->Empty());
-  frame_swap_message_queue_->DidActivate(2);
-  EXPECT_TRUE(NextSwapHasMessage(messages_[0]));
-}
-
-TEST_F(QueueMessageSwapPromiseTest,
-       VisualStateQueuesMessageWhenCommitRequested) {
-  int source_frame_numbers[] = {1};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  ASSERT_TRUE(promises_[0].get());
-  EXPECT_TRUE(DirectSendMessages().empty());
-  EXPECT_FALSE(frame_swap_message_queue_->Empty());
-  EXPECT_TRUE(NextSwapMessages().empty());
-
-  CleanupPromises();
-}
-
-TEST_F(QueueMessageSwapPromiseTest,
-       VisualStateQueuesMessageWhenOtherMessageAlreadyQueued) {
-  int source_frame_numbers[] = {1, 1};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  EXPECT_TRUE(DirectSendMessages().empty());
-  EXPECT_FALSE(frame_swap_message_queue_->Empty());
-  EXPECT_FALSE(NextSwapHasMessage(messages_[1]));
-
-  CleanupPromises();
-}
-
-TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidActivate) {
-  int source_frame_numbers[] = {1, 1, 2};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  promises_[0]->DidActivate();
-  promises_[0]->WillSwap(&dummy_metadata_);
-  promises_[0]->DidSwap();
-  ASSERT_FALSE(promises_[1].get());
-  std::vector<std::unique_ptr<IPC::Message>> messages;
-  messages.swap(LastSwapMessages());
-  EXPECT_EQ(2u, messages.size());
-  EXPECT_TRUE(ContainsMessage(messages, messages_[0]));
-  EXPECT_TRUE(ContainsMessage(messages, messages_[1]));
-  EXPECT_FALSE(ContainsMessage(messages, messages_[2]));
-
-  promises_[2]->DidActivate();
-  promises_[2]->DidNotSwap(cc::SwapPromise::SWAP_FAILS);
-  messages.swap(NextSwapMessages());
-  EXPECT_TRUE(messages.empty());
-
-  EXPECT_EQ(1u, DirectSendMessages().size());
-  EXPECT_TRUE(ContainsMessage(DirectSendMessages(), messages_[2]));
-
-  EXPECT_TRUE(NextSwapMessages().empty());
-  EXPECT_TRUE(frame_swap_message_queue_->Empty());
-}
-
-void QueueMessageSwapPromiseTest::VisualStateSwapPromiseDidNotSwap(
-    cc::SwapPromise::DidNotSwapReason reason) {
-  int source_frame_numbers[] = {1, 1, 2};
-  QueueMessages(source_frame_numbers, base::size(source_frame_numbers));
-
-  // If we fail to swap with COMMIT_FAILS or ACTIVATE_FAILS, then
-  // messages are delivered by the RenderFrameHostImpl destructor,
-  // rather than directly by the swap promise.
-  bool msg_delivered = reason != cc::SwapPromise::COMMIT_FAILS &&
-                       reason != cc::SwapPromise::ACTIVATION_FAILS;
-
-  promises_[0]->DidNotSwap(reason);
-  ASSERT_FALSE(promises_[1].get());
-  EXPECT_TRUE(NextSwapMessages().empty());
-  EXPECT_EQ(msg_delivered, ContainsMessage(DirectSendMessages(), messages_[0]));
-  EXPECT_EQ(msg_delivered, ContainsMessage(DirectSendMessages(), messages_[1]));
-  EXPECT_FALSE(ContainsMessage(DirectSendMessages(), messages_[2]));
-
-  promises_[2]->DidNotSwap(reason);
-  EXPECT_TRUE(NextSwapMessages().empty());
-  EXPECT_EQ(msg_delivered, ContainsMessage(DirectSendMessages(), messages_[2]));
-
-  EXPECT_TRUE(NextSwapMessages().empty());
-  EXPECT_EQ(msg_delivered, frame_swap_message_queue_->Empty());
-}
-
-TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidNotSwapNoUpdate) {
-  VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_NO_UPDATE);
-}
-
-TEST_F(QueueMessageSwapPromiseTest,
-       VisualStateSwapPromiseDidNotSwapCommitFails) {
-  VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::COMMIT_FAILS);
-}
-
-TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidNotSwapSwapFails) {
-  VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::SWAP_FAILS);
-}
-
-TEST_F(QueueMessageSwapPromiseTest,
-       VisualStateSwapPromiseDidNotSwapActivationFails) {
-  VisualStateSwapPromiseDidNotSwap(cc::SwapPromise::ACTIVATION_FAILS);
-}
-
-}  // namespace content
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 07c7e50..ea3acb0 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -77,7 +77,6 @@
 #include "content/renderer/browser_exposed_renderer_interfaces.h"
 #include "content/renderer/categorized_worker_pool.h"
 #include "content/renderer/effective_connection_type_helper.h"
-#include "content/renderer/frame_swap_message_queue.h"
 #include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/media/audio/audio_renderer_mixer_manager.h"
 #include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h"
@@ -1634,7 +1633,6 @@
 
 void RenderThreadImpl::RequestNewLayerTreeFrameSink(
     RenderWidget* render_widget,
-    scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
     const GURL& url,
     LayerTreeFrameSinkCallback callback,
     const char* client_name) {
@@ -1778,7 +1776,6 @@
             sync_message_filter(), g_next_layer_tree_frame_sink_id++,
             std::move(params.synthetic_begin_frame_source),
             render_widget->GetWebWidget()->GetSynchronousCompositorRegistry(),
-            std::move(frame_swap_message_queue),
             std::move(params.pipes.compositor_frame_sink_remote),
             std::move(params.pipes.client_receiver)),
         std::move(render_frame_metadata_observer));
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index f1b5dcc..6721d865 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -201,7 +201,6 @@
   std::unique_ptr<cc::UkmRecorderFactory> CreateUkmRecorderFactory() override;
   void RequestNewLayerTreeFrameSink(
       RenderWidget* render_widget,
-      scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
       const GURL& url,
       LayerTreeFrameSinkCallback callback,
       const char* client_name) override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 31e8817..d5228c7b 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -55,9 +55,7 @@
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/drop_data_builder.h"
-#include "content/renderer/frame_swap_message_queue.h"
 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
-#include "content/renderer/queue_message_swap_promise.h"
 #include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_frame_proxy.h"
 #include "content/renderer/render_process.h"
@@ -68,8 +66,6 @@
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/config/gpu_finch_features.h"
 #include "ipc/ipc_message_start.h"
-#include "ipc/ipc_sync_message.h"
-#include "ipc/ipc_sync_message_filter.h"
 #include "media/base/media_switches.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "ppapi/buildflags/buildflags.h"
@@ -325,8 +321,7 @@
     : routing_id_(widget_routing_id),
       compositor_deps_(compositor_deps),
       is_hidden_(hidden),
-      never_composited_(never_composited),
-      frame_swap_message_queue_(new FrameSwapMessageQueue(routing_id_)) {
+      never_composited_(never_composited) {
   DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
   DCHECK(RenderThread::IsMainThread());
   DCHECK(compositor_deps_);
@@ -435,8 +430,6 @@
     IPC_MESSAGE_HANDLER(WidgetMsg_SetBounds_ACK, OnRequestSetBoundsAck)
     IPC_MESSAGE_HANDLER(WidgetMsg_SetViewportIntersection,
                         OnSetViewportIntersection)
-    IPC_MESSAGE_HANDLER(WidgetMsg_WaitForNextFrameForTests,
-                        OnWaitNextFrameForTests)
     IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
@@ -831,8 +824,7 @@
   // would also be used for other widgets such as popups.
   const char* client_name = for_child_local_root_frame_ ? kOOPIF : kRenderer;
   compositor_deps_->RequestNewLayerTreeFrameSink(
-      this, frame_swap_message_queue_, std::move(url), std::move(callback),
-      client_name);
+      this, std::move(url), std::move(callback), client_name);
 }
 
 void RenderWidget::DidCommitAndDrawCompositorFrame() {
@@ -1050,48 +1042,10 @@
     observer.DidMeaningfulLayout(layout_type);
 }
 
-// static
-std::unique_ptr<cc::SwapPromise> RenderWidget::QueueMessageImpl(
-    std::unique_ptr<IPC::Message> msg,
-    FrameSwapMessageQueue* frame_swap_message_queue,
-    scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
-    int source_frame_number) {
-  bool first_message_for_frame = false;
-  frame_swap_message_queue->QueueMessageForFrame(
-      source_frame_number, std::move(msg), &first_message_for_frame);
-  if (!first_message_for_frame)
-    return nullptr;
-  return std::make_unique<QueueMessageSwapPromise>(
-      sync_message_filter, frame_swap_message_queue, source_frame_number);
-}
-
 void RenderWidget::SetHandlingInputEvent(bool handling_input_event) {
   GetWebWidget()->SetHandlingInputEvent(handling_input_event);
 }
 
-void RenderWidget::QueueMessage(std::unique_ptr<IPC::Message> msg) {
-  // RenderThreadImpl::current() is NULL in some tests.
-  if (!RenderThreadImpl::current()) {
-    Send(msg.release());
-    return;
-  }
-
-  std::unique_ptr<cc::SwapPromise> swap_promise =
-      QueueMessageImpl(std::move(msg), frame_swap_message_queue_.get(),
-                       RenderThreadImpl::current()->sync_message_filter(),
-                       layer_tree_host_->SourceFrameNumber());
-  if (swap_promise) {
-    layer_tree_host_->QueueSwapPromise(std::move(swap_promise));
-
-    // Request a main frame if one is not already in progress. This might either
-    // A) request a commit ahead of time or B) request a commit which is not
-    // needed because there are not pending updates. If B) then the frame will
-    // be aborted early and the swap promises will be broken (see
-    // EarlyOut_NoUpdates).
-    layer_tree_host_->SetNeedsAnimateIfNotInsideMainFrame();
-  }
-}
-
 // We are supposed to get a single call to Show for a newly created RenderWidget
 // that was created via RenderWidget::CreateWebView.  So, we wait until this
 // point to dispatch the ShowWidget message.
@@ -1651,13 +1605,6 @@
   render_frames_.RemoveObserver(frame);
 }
 
-void RenderWidget::OnWaitNextFrameForTests(
-    int main_frame_thread_observer_routing_id) {
-  // Sends an ACK to the browser process during the next compositor frame.
-  QueueMessage(std::make_unique<WidgetHostMsg_WaitForNextFrameForTests_ACK>(
-      main_frame_thread_observer_routing_id));
-}
-
 const blink::ScreenInfo& RenderWidget::GetOriginalScreenInfo() const {
   if (device_emulator_)
     return device_emulator_->original_screen_info();
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index bf205cf..7fa2482 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -66,10 +66,6 @@
 #include "ui/gfx/range/range.h"
 #include "ui/surface/transport_dib.h"
 
-namespace IPC {
-class SyncMessageFilter;
-}
-
 namespace blink {
 struct VisualProperties;
 struct DeviceEmulationParams;
@@ -81,10 +77,6 @@
 class WebPagePopup;
 }  // namespace blink
 
-namespace cc {
-class SwapPromise;
-}
-
 namespace gfx {
 class ColorSpace;
 struct PresentationFeedback;
@@ -93,7 +85,6 @@
 
 namespace content {
 class CompositorDependencies;
-class FrameSwapMessageQueue;
 class PepperPluginInstanceImpl;
 class RenderFrameImpl;
 class RenderFrameProxy;
@@ -341,17 +332,6 @@
   cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_; }
   void SetHandlingInputEvent(bool handling_input_event);
 
-  // Queues the IPC |message| to be sent to the browser, delaying sending until
-  // the next compositor frame submission. At that time they will be sent before
-  // any message from the compositor as part of submitting its frame. This is
-  // used for messages that need synchronization with the compositor, but in
-  // general you should use Send().
-  //
-  // This mechanism is not a drop-in replacement for IPC: messages sent this way
-  // will not be automatically available to BrowserMessageFilter, for example.
-  // FIFO ordering is preserved between messages enqueued.
-  void QueueMessage(std::unique_ptr<IPC::Message> msg);
-
   // Checks if the selection bounds have been changed. If they are changed,
   // the new value will be sent to the browser process.
   void UpdateSelectionBounds();
@@ -423,7 +403,6 @@
   // For unit tests.
   friend class InteractiveRenderWidget;
   friend class PopupRenderWidget;
-  friend class QueueMessageSwapPromiseTest;
   friend class RenderWidgetTest;
   friend class RenderViewImplTest;
 
@@ -479,7 +458,6 @@
                          const gfx::PointF& screen_point,
                          blink::WebDragOperation drag_operation);
   void OnOrientationChange();
-  void OnWaitNextFrameForTests(int routing_id);
 
   // Sets the "hidden" state of this widget.  All modification of is_hidden_
   // should use this method so that we can properly inform the RenderThread of
@@ -491,14 +469,6 @@
   // constrained to limit overdraw.
   gfx::Rect ViewportVisibleRect();
 
-  // QueueMessage implementation extracted into a static method for easy
-  // testing.
-  static std::unique_ptr<cc::SwapPromise> QueueMessageImpl(
-      std::unique_ptr<IPC::Message> msg,
-      FrameSwapMessageQueue* frame_swap_message_queue,
-      scoped_refptr<IPC::SyncMessageFilter> sync_message_filter,
-      int source_frame_number);
-
   // Set the pending window rect.
   // Because the real render_widget is hosted in another process, there is
   // a time period where we may have set a new window rect which has not yet
@@ -651,8 +621,6 @@
   // The time spent in input handlers this frame. Used to throttle input acks.
   base::TimeDelta total_input_handling_time_this_frame_;
 
-  scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
-
   // Lists of RenderFrameProxy objects for which this RenderWidget is their
   // local root. Each of these represents a child local root RenderWidget in
   // another RenderView frame tree. For values that are propagated from
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 2c853b5..921e9a4 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -2025,7 +2025,6 @@
     "../renderer/accessibility/ax_image_stopwords_unittest.cc",
     "../renderer/categorized_worker_pool_unittest.cc",
     "../renderer/child_frame_compositing_helper_unittest.cc",
-    "../renderer/frame_swap_message_queue_unittest.cc",
     "../renderer/loader/navigation_body_loader_unittest.cc",
     "../renderer/loader/resource_dispatcher_unittest.cc",
     "../renderer/loader/sync_load_context_unittest.cc",
@@ -2045,7 +2044,6 @@
     "../renderer/media/power_status_helper_impl_unittest.cc",
     "../renderer/media/renderer_webaudiodevice_impl_unittest.cc",
     "../renderer/peripheral_content_heuristic_unittest.cc",
-    "../renderer/queue_message_swap_promise_unittest.cc",
     "../renderer/render_frame_metadata_observer_impl_unittest.cc",
     "../renderer/render_thread_impl_unittest.cc",
     "../renderer/render_widget_unittest.cc",
diff --git a/content/test/fake_compositor_dependencies.cc b/content/test/fake_compositor_dependencies.cc
index 143fe975..3d1abaf6 100644
--- a/content/test/fake_compositor_dependencies.cc
+++ b/content/test/fake_compositor_dependencies.cc
@@ -11,7 +11,6 @@
 #include "cc/test/fake_layer_tree_frame_sink.h"
 #include "cc/test/test_ukm_recorder_factory.h"
 #include "cc/trees/render_frame_metadata_observer.h"
-#include "content/renderer/frame_swap_message_queue.h"
 #include "third_party/khronos/GLES2/gl2.h"
 #include "ui/gfx/buffer_types.h"
 
@@ -65,7 +64,6 @@
 
 void FakeCompositorDependencies::RequestNewLayerTreeFrameSink(
     RenderWidget* render_widget,
-    scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
     const GURL& url,
     LayerTreeFrameSinkCallback callback,
     const char* client_name) {
diff --git a/content/test/fake_compositor_dependencies.h b/content/test/fake_compositor_dependencies.h
index 8507857..01dc408 100644
--- a/content/test/fake_compositor_dependencies.h
+++ b/content/test/fake_compositor_dependencies.h
@@ -36,7 +36,6 @@
   std::unique_ptr<cc::UkmRecorderFactory> CreateUkmRecorderFactory() override;
   void RequestNewLayerTreeFrameSink(
       RenderWidget* render_widget,
-      scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
       const GURL& url,
       LayerTreeFrameSinkCallback callback,
       const char* client_name) override;
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 079e2b5..3682dfac 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -380,8 +380,7 @@
 crbug.com/angleproject/4286 [ win amd vulkan passthrough ] conformance/rendering/out-of-bounds-array-buffers.html [ Failure ]
 
 # Vulkan / Win10 / Intel / Passthrough
-# Flaking since an identified Angle roll.
-crbug.com/1111652 [ win10 intel vulkan passthrough ] conformance/context/context-size-change.html [ RetryOnFailure ]
+crbug.com/1111652 [ win10 intel vulkan passthrough ] conformance/context/context-size-change.html [ Failure ]
 
 ####################
 # Mac failures     #
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 044e350..2c87eac1 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -12162,6 +12162,137 @@
   return max_vertex_accessed;
 }
 
+namespace {
+// Copied from angle/src/libANGLE/validationES2.cpp
+// As we removed shader source string validation in blink level.
+// Addressing http://crbug.com/1108588
+
+// Return true if a character belongs to the ASCII subset as defined in GLSL
+// ES 1.0 spec section 3.1.
+bool IsValidESSLCharacter(unsigned char c) {
+  // Printing characters are valid except " $ ` @ \ ' DEL.
+  if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' &&
+      c != '\\' && c != '\'') {
+    return true;
+  }
+
+  // Horizontal tab, line feed, vertical tab, form feed, carriage return are
+  // also valid.
+  if (c >= 9 && c <= 13) {
+    return true;
+  }
+
+  return false;
+}
+
+bool IsValidESSLShaderSourceString(const char* str,
+                                   size_t len,
+                                   bool lineContinuationAllowed) {
+  enum class ParseState {
+    // Have not seen an ASCII non-whitespace character yet on
+    // this line. Possible that we might see a preprocessor
+    // directive.
+    BEGINING_OF_LINE,
+
+    // Have seen at least one ASCII non-whitespace character
+    // on this line.
+    MIDDLE_OF_LINE,
+
+    // Handling a preprocessor directive. Passes through all
+    // characters up to the end of the line. Disables comment
+    // processing.
+    IN_PREPROCESSOR_DIRECTIVE,
+
+    // Handling a single-line comment. The comment text is
+    // replaced with a single space.
+    IN_SINGLE_LINE_COMMENT,
+
+    // Handling a multi-line comment. Newlines are passed
+    // through to preserve line numbers.
+    IN_MULTI_LINE_COMMENT
+  };
+
+  ParseState state = ParseState::BEGINING_OF_LINE;
+  size_t pos = 0;
+
+  while (pos < len) {
+    char c = str[pos];
+    char next = pos + 1 < len ? str[pos + 1] : 0;
+
+    // Check for newlines
+    if (c == '\n' || c == '\r') {
+      if (state != ParseState::IN_MULTI_LINE_COMMENT) {
+        state = ParseState::BEGINING_OF_LINE;
+      }
+
+      pos++;
+      continue;
+    }
+
+    switch (state) {
+      case ParseState::BEGINING_OF_LINE:
+        if (c == ' ') {
+          // Maintain the BEGINING_OF_LINE state until a non-space is seen
+          pos++;
+        } else if (c == '#') {
+          state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
+          pos++;
+        } else {
+          // Don't advance, re-process this character with the MIDDLE_OF_LINE
+          // state
+          state = ParseState::MIDDLE_OF_LINE;
+        }
+        break;
+
+      case ParseState::MIDDLE_OF_LINE:
+        if (c == '/' && next == '/') {
+          state = ParseState::IN_SINGLE_LINE_COMMENT;
+          pos++;
+        } else if (c == '/' && next == '*') {
+          state = ParseState::IN_MULTI_LINE_COMMENT;
+          pos++;
+        } else if (lineContinuationAllowed && c == '\\' &&
+                   (next == '\n' || next == '\r')) {
+          // Skip line continuation characters
+        } else if (!IsValidESSLCharacter(c)) {
+          return false;
+        }
+        pos++;
+        break;
+
+      case ParseState::IN_PREPROCESSOR_DIRECTIVE:
+        // Line-continuation characters may not be permitted.
+        // Otherwise, just pass it through. Do not parse comments in this state.
+        if (!lineContinuationAllowed && c == '\\') {
+          return false;
+        }
+        pos++;
+        break;
+
+      case ParseState::IN_SINGLE_LINE_COMMENT:
+        // Line-continuation characters are processed before comment processing.
+        // Advance string if a new line character is immediately behind
+        // line-continuation character.
+        if (c == '\\' && (next == '\n' || next == '\r')) {
+          pos++;
+        }
+        pos++;
+        break;
+
+      case ParseState::IN_MULTI_LINE_COMMENT:
+        if (c == '*' && next == '/') {
+          state = ParseState::MIDDLE_OF_LINE;
+          pos++;
+        }
+        pos++;
+        break;
+    }
+  }
+
+  return true;
+}
+}  // namespace
+
 void GLES2DecoderImpl::DoShaderSource(
     GLuint client_id, GLsizei count, const char** data, const GLint* length) {
   std::string str;
@@ -12171,6 +12302,19 @@
     else
       str.append(data[ii]);
   }
+  size_t len = str.size();
+  // Accommodate gles2_conform_tests
+  // where there are '\0' at the end of the shaders
+  while (len > 0 && str[len - 1] == '\0') {
+    len -= 1;
+  }
+  if (!IsValidESSLShaderSourceString(
+          str.data(), len, feature_info_->IsWebGL2OrES3OrHigherContext())) {
+    const char* func_name = "glShaderSource";
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name,
+                       "Shader source contains invalid characters.");
+    return;
+  }
   Shader* shader = GetShaderInfoNotProgram(client_id, "glShaderSource");
   if (!shader) {
     return;
diff --git a/gpu/ipc/service/gpu_watchdog_thread_v2.cc b/gpu/ipc/service/gpu_watchdog_thread_v2.cc
index 64be2e2..063c5817 100644
--- a/gpu/ipc/service/gpu_watchdog_thread_v2.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread_v2.cc
@@ -849,12 +849,12 @@
 }
 
 bool GpuWatchdogThreadImplV2::WithinOneMinFromPowerResumed() {
-  size_t count = base::TimeDelta::FromSeconds(60) / watchdog_timeout_;
+  size_t count = base::TimeDelta::FromMinutes(1).IntDiv(watchdog_timeout_);
   return power_resumed_event_ && num_of_timeout_after_power_resume_ <= count;
 }
 
 bool GpuWatchdogThreadImplV2::WithinOneMinFromForegrounded() {
-  size_t count = base::TimeDelta::FromSeconds(60) / watchdog_timeout_;
+  size_t count = base::TimeDelta::FromMinutes(1).IntDiv(watchdog_timeout_);
   return foregrounded_event_ && num_of_timeout_after_foregrounded_ <= count;
 }
 
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
index 8561aa0..17e0342 100644
--- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
@@ -29,6 +29,8 @@
       const sessions::LiveTab* tab) override;
   sessions::LiveTabContext* FindLiveTabContextWithID(
       SessionID desired_id) override;
+  sessions::LiveTabContext* FindLiveTabContextWithGroup(
+      tab_groups::TabGroupId group) override;
   bool ShouldTrackURLForRestore(const GURL& url) override;
   std::string GetExtensionAppIDForTab(sessions::LiveTab* tab) override;
   base::FilePath GetPathToSaveTo() override;
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
index ad273a0..f58f66d4 100644
--- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "components/sessions/ios/ios_live_tab.h"
+#include "components/tab_groups/tab_group_id.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h"
@@ -99,6 +100,12 @@
       desired_id));
 }
 
+sessions::LiveTabContext*
+IOSChromeTabRestoreServiceClient::FindLiveTabContextWithGroup(
+    tab_groups::TabGroupId group) {
+  return nullptr;
+}
+
 bool IOSChromeTabRestoreServiceClient::ShouldTrackURLForRestore(
     const GURL& url) {
   // NOTE: In the //chrome client, chrome://quit and chrome://restart are
diff --git a/media/base/android/media_service_throttler_unittest.cc b/media/base/android/media_service_throttler_unittest.cc
index 69f6c89..78a9dcb 100644
--- a/media/base/android/media_service_throttler_unittest.cc
+++ b/media/base/android/media_service_throttler_unittest.cc
@@ -139,7 +139,7 @@
 // reset.
 TEST_F(MediaServiceThrottlerTest, NoCrash_LongInactivity_ShouldReset) {
   // Schedule two minutes' worth of clients.
-  SimulateClientCreations(base::TimeDelta::FromMinutes(2) / base_delay_);
+  SimulateClientCreations(base::TimeDelta::FromMinutes(2).IntDiv(base_delay_));
 
   // Advance the time so the scheduler perceived a full minute of inactivity.
   clock_.Advance(base::TimeDelta::FromSeconds(61));
@@ -263,7 +263,7 @@
   // Schedule many minutes worth of clients. This is to prove that the
   // MediaServerCrashListener's clean up happens after lack of requests, as
   // opposed to lack of actually scheduled clients.
-  SimulateClientCreations(base::TimeDelta::FromMinutes(3) / base_delay_);
+  SimulateClientCreations(base::TimeDelta::FromMinutes(3).IntDiv(base_delay_));
 
   // The MediaServerCrashListener should be alive, with 1s second to spare.
   clock_.Advance(base::TimeDelta::FromSeconds(59));
@@ -292,7 +292,7 @@
   // Schedule many minutes worth of clients. This is to prove that the
   // MediaServerCrashListener's clean up happens after lack of requests, as
   // opposed to lack of actually scheduled clients.
-  SimulateClientCreations(base::TimeDelta::FromMinutes(3) / base_delay_);
+  SimulateClientCreations(base::TimeDelta::FromMinutes(3).IntDiv(base_delay_));
 
   // The MediaServerCrashListener should be alive, with 1s second to spare.
   clock_.Advance(base::TimeDelta::FromSeconds(59));
diff --git a/media/base/stream_parser_buffer.h b/media/base/stream_parser_buffer.h
index 3800e17..3ff7e8c 100644
--- a/media/base/stream_parser_buffer.h
+++ b/media/base/stream_parser_buffer.h
@@ -62,7 +62,8 @@
     return DecodeTimestamp(ts_ - rhs);
   }
 
-  int64_t operator/(base::TimeDelta rhs) const { return ts_ / rhs; }
+  int64_t operator/(base::TimeDelta rhs) const = delete;
+  int64_t IntDiv(base::TimeDelta rhs) const { return ts_.IntDiv(rhs); }
 
   static DecodeTimestamp FromSecondsD(double seconds) {
     return DecodeTimestamp(base::TimeDelta::FromSecondsD(seconds));
diff --git a/media/capture/content/animated_content_sampler.cc b/media/capture/content/animated_content_sampler.cc
index 0c2fd5b..c533123 100644
--- a/media/capture/content/animated_content_sampler.cc
+++ b/media/capture/content/animated_content_sampler.cc
@@ -250,7 +250,8 @@
   // TODO(miu): This is similar to the ClockSmoother in
   // media/base/audio_shifter.cc.  Consider refactor-and-reuse here.
   const base::TimeDelta drift = ideal_timestamp - event_time;
-  const int64_t correct_over_num_frames = kDriftCorrection / sampling_period_;
+  const int64_t correct_over_num_frames =
+      kDriftCorrection.IntDiv(sampling_period_);
   DCHECK_GT(correct_over_num_frames, 0);
 
   return ideal_timestamp - drift / correct_over_num_frames;
@@ -275,7 +276,7 @@
   // 42/3 = 14, and so on.  Of these candidates, 21 FPS is closest to 30.
   base::TimeDelta sampling_period;
   if (animation_period < target_sampling_period) {
-    const int64_t ratio = target_sampling_period / animation_period;
+    const int64_t ratio = target_sampling_period.IntDiv(animation_period);
     const double target_fps = 1.0 / target_sampling_period.InSecondsF();
     const double animation_fps = 1.0 / animation_period.InSecondsF();
     if (std::abs(animation_fps / ratio - target_fps) <
diff --git a/media/capture/content/animated_content_sampler_unittest.cc b/media/capture/content/animated_content_sampler_unittest.cc
index 7716699..ef17134 100644
--- a/media/capture/content/animated_content_sampler_unittest.cc
+++ b/media/capture/content/animated_content_sampler_unittest.cc
@@ -606,13 +606,13 @@
   // display_counts[2] == 10.  Quit early if any one frame was obviously
   // repeated too many times.
   const int64_t max_expected_repeats_per_frame =
-      1 + ComputeExpectedSamplingPeriod() / GetParam().vsync_interval;
+      1 + ComputeExpectedSamplingPeriod().IntDiv(GetParam().vsync_interval);
   std::vector<size_t> display_counts(max_expected_repeats_per_frame + 1, 0);
   base::TimeTicks last_present_time = frame_timestamps.front();
   for (Timestamps::const_iterator i = frame_timestamps.begin() + 1;
        i != frame_timestamps.end(); ++i) {
     const size_t num_vsync_intervals = static_cast<size_t>(
-        (*i - last_present_time) / GetParam().vsync_interval);
+        (*i - last_present_time).IntDiv(GetParam().vsync_interval));
     ASSERT_LT(0u, num_vsync_intervals);
     ASSERT_GT(display_counts.size(), num_vsync_intervals);  // Quit early.
     ++display_counts[num_vsync_intervals];
diff --git a/media/cast/sender/audio_encoder.cc b/media/cast/sender/audio_encoder.cc
index 0ebc95e..fc29102 100644
--- a/media/cast/sender/audio_encoder.cc
+++ b/media/cast/sender/audio_encoder.cc
@@ -104,7 +104,7 @@
     if (!frame_capture_time_.is_null()) {
       const base::TimeDelta amount_ahead_by =
           recorded_time - (frame_capture_time_ + buffer_fill_duration);
-      const int64_t num_frames_missed = amount_ahead_by / frame_duration_;
+      const int64_t num_frames_missed = amount_ahead_by.IntDiv(frame_duration_);
       if (num_frames_missed > kUnderrunSkipThreshold) {
         samples_dropped_from_buffer_ += buffer_fill_end_;
         buffer_fill_end_ = 0;
diff --git a/media/cast/sender/frame_sender.cc b/media/cast/sender/frame_sender.cc
index 775688a..88a8a0a 100644
--- a/media/cast/sender/frame_sender.cc
+++ b/media/cast/sender/frame_sender.cc
@@ -463,7 +463,7 @@
   if (VLOG_IS_ON(1)) {
     const int64_t percent =
         allowed_in_flight > base::TimeDelta()
-            ? 100 * duration_would_be_in_flight / allowed_in_flight
+            ? (100 * duration_would_be_in_flight).IntDiv(allowed_in_flight)
             : std::numeric_limits<int64_t>::max();
     VLOG_IF(1, percent > 50)
         << SENDER_SSRC
diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
index 6ae21d2..d2374c7 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -206,8 +206,8 @@
     std::stringstream ss;
     ss << "{ ";
     for (size_t i = 0; i < r.size(); ++i) {
-      int64_t start = (r.start(i) / frame_duration_);
-      int64_t end = (r.end(i) / frame_duration_) - 1;
+      int64_t start = r.start(i).IntDiv(frame_duration_);
+      int64_t end = r.end(i).IntDiv(frame_duration_) - 1;
       ss << "[" << start << "," << end << ") ";
     }
     ss << "}";
@@ -305,7 +305,7 @@
         }
       }
 
-      EXPECT_EQ(buffer->GetDecodeTimestamp() / frame_duration_,
+      EXPECT_EQ(buffer->GetDecodeTimestamp().IntDiv(frame_duration_),
                 current_position);
     }
 
diff --git a/media/filters/video_cadence_estimator_unittest.cc b/media/filters/video_cadence_estimator_unittest.cc
index 0ce77a0..9e76b1a 100644
--- a/media/filters/video_cadence_estimator_unittest.cc
+++ b/media/filters/video_cadence_estimator_unittest.cc
@@ -307,7 +307,7 @@
   const base::TimeDelta acceptable_drift =
       frame_interval < render_interval ? render_interval : frame_interval;
   const base::TimeDelta test_runtime = base::TimeDelta::FromSeconds(10 * 60);
-  const int test_frames = test_runtime / frame_interval;
+  const int test_frames = test_runtime.IntDiv(frame_interval);
 
   estimator->Reset();
   EXPECT_TRUE(estimator->UpdateCadenceEstimate(
diff --git a/media/filters/video_renderer_algorithm.cc b/media/filters/video_renderer_algorithm.cc
index afc59900..08a95cb 100644
--- a/media/filters/video_renderer_algorithm.cc
+++ b/media/filters/video_renderer_algorithm.cc
@@ -442,7 +442,7 @@
 
   DCHECK_GT(render_interval_, base::TimeDelta());
   const int64_t render_cycle_count =
-      (deadline_min - last_deadline_max_) / render_interval_;
+      (deadline_min - last_deadline_max_).IntDiv(render_interval_);
 
   // In the ideal case this value will be zero.
   if (!render_cycle_count)
diff --git a/mojo/public/cpp/bindings/lib/message_quota_checker.cc b/mojo/public/cpp/bindings/lib/message_quota_checker.cc
index 1ba74fd..6088dafe 100644
--- a/mojo/public/cpp/bindings/lib/message_quota_checker.cc
+++ b/mojo/public/cpp/bindings/lib/message_quota_checker.cc
@@ -99,8 +99,8 @@
 }
 
 int64_t ToSamplingInterval(base::TimeTicks when) {
-  return (when - base::TimeTicks::UnixEpoch()) /
-         MessageQuotaChecker::DecayingRateAverage::kSamplingInterval;
+  return (when - base::TimeTicks::UnixEpoch())
+      .IntDiv(MessageQuotaChecker::DecayingRateAverage::kSamplingInterval);
 }
 
 base::TimeTicks FromSamplingInterval(int64_t sampling_interval) {
diff --git a/net/cert/cert_verify_proc_builtin_unittest.cc b/net/cert/cert_verify_proc_builtin_unittest.cc
index 4153212..7b67087 100644
--- a/net/cert/cert_verify_proc_builtin_unittest.cc
+++ b/net/cert/cert_verify_proc_builtin_unittest.cc
@@ -176,7 +176,8 @@
       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
       base::TimeDelta::FromMilliseconds(1);
   const int expected_request_count =
-      GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
+      GetCertVerifyProcBuiltinTimeLimitForTesting().IntDiv(timeout_increment) +
+      1;
 
   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
   ASSERT_TRUE(test_server.InitializeAndListen());
@@ -247,7 +248,8 @@
       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
       base::TimeDelta::FromMilliseconds(1);
   const int expected_request_count =
-      GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
+      GetCertVerifyProcBuiltinTimeLimitForTesting().IntDiv(timeout_increment) +
+      1;
 
   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
   ASSERT_TRUE(test_server.InitializeAndListen());
@@ -324,7 +326,8 @@
       CertNetFetcherURLRequest::GetDefaultTimeoutForTesting() +
       base::TimeDelta::FromMilliseconds(1);
   const int expected_request_count =
-      GetCertVerifyProcBuiltinTimeLimitForTesting() / timeout_increment + 1;
+      GetCertVerifyProcBuiltinTimeLimitForTesting().IntDiv(timeout_increment) +
+      1;
 
   EmbeddedTestServer test_server(EmbeddedTestServer::TYPE_HTTP);
   ASSERT_TRUE(test_server.InitializeAndListen());
diff --git a/net/dns/httpssvc_metrics.cc b/net/dns/httpssvc_metrics.cc
index 84228add3..a9fd81a7 100644
--- a/net/dns/httpssvc_metrics.cc
+++ b/net/dns/httpssvc_metrics.cc
@@ -204,7 +204,7 @@
   // will crash if the system clock leaps forward several hundred millennia
   // (numeric_limits<int64_t>::max() microseconds ~= 292,000 years).
   const int64_t resolve_time_percent =
-      (100 * *integrity_resolve_time_) / *slowest_non_integrity_resolve;
+      (100 * *integrity_resolve_time_).IntDiv(*slowest_non_integrity_resolve);
 
   // Scale the value of |resolve_time_percent| by dividing by |kPercentScale|.
   // Sample values are bounded between 1 and 20. A recorded sample of 10 means
diff --git a/net/dns/resolve_context.cc b/net/dns/resolve_context.cc
index 3b15cf32..d33504af 100644
--- a/net/dns/resolve_context.cc
+++ b/net/dns/resolve_context.cc
@@ -408,7 +408,7 @@
       // continue in parallel with new attempts made by the transaction. Scale
       // the ratio up by 10 for sub-integer granularity.
       // TODO(crbug.com/1105138): Remove after determining good timeout logic.
-      int timeout_ratio = 10 * rtt / base_timeout;
+      int timeout_ratio = (10 * rtt).IntDiv(base_timeout);
       UMA_HISTOGRAM_COUNTS_1000(
           "Net.DNS.DnsTransaction.SecureValidated.SuccessTimeoutRatio",
           timeout_ratio);
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index 398b0e5..536f8858 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -341,7 +341,7 @@
 
 // If true, consider frame expansion when calculating extra padding bytes to
 // meet minimum plaintext packet size required for header protection.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_extra_padding_bytes, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_extra_padding_bytes, true)
 
 // If true, do not try to close stream again if stream fails to be closed upon
 // connection close.
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc
index 496d1948..9cf15b84c 100644
--- a/net/quic/quic_test_packet_maker.cc
+++ b/net/quic/quic_test_packet_maker.cc
@@ -1263,10 +1263,21 @@
       packet_size += frame_size;
       frames_size += frame_size;
     }
-    // This should be done by calling QuicPacketCreator::MinPlaintextPacketSize.
-    const size_t min_plaintext_size = 7;
-    if (frames_size < min_plaintext_size) {
-      size_t padding_length = min_plaintext_size - frames_size;
+
+    const size_t min_plaintext_packet_size =
+        quic::QuicPacketCreator::MinPlaintextPacketSize(version_);
+    if (frames_size < min_plaintext_packet_size) {
+      const size_t expansion_on_new_frame =
+          frames.empty()
+              ? 0
+              : quic::QuicPacketCreator::ExpansionOnNewFrameWithLastFrame(
+                    frames.back(), version_.transport_version);
+      const size_t padding_length =
+          std::max(1 + expansion_on_new_frame,
+                   min_plaintext_packet_size - frames_size) -
+          expansion_on_new_frame;
+      CHECK_LE(padding_length + packet_size + expansion_on_new_frame,
+               max_plaintext_size);
       frames_copy.push_back(
           quic::QuicFrame(quic::QuicPaddingFrame(padding_length)));
     }
diff --git a/remoting/test/cyclic_frame_generator.cc b/remoting/test/cyclic_frame_generator.cc
index 61324f3..7f12451 100644
--- a/remoting/test/cyclic_frame_generator.cc
+++ b/remoting/test/cyclic_frame_generator.cc
@@ -49,9 +49,9 @@
     webrtc::SharedMemoryFactory* shared_memory_factory) {
   base::TimeTicks now = clock_->NowTicks();
 
-  int frame_id = (now - started_time_) / cursor_blink_period_;
-  int reference_frame =
-      ((now - started_time_) / frame_cycle_period_) % reference_frames_.size();
+  int frame_id = (now - started_time_).IntDiv(cursor_blink_period_);
+  int reference_frame = (now - started_time_).IntDiv(frame_cycle_period_) %
+                        reference_frames_.size();
   bool cursor_state = frame_id % 2;
 
   auto frame = std::make_unique<webrtc::BasicDesktopFrame>(screen_size_);
@@ -88,11 +88,11 @@
 
 CyclicFrameGenerator::ChangeInfoList CyclicFrameGenerator::GetChangeList(
     base::TimeTicks timestamp) {
-  int frame_id = (timestamp - started_time_) / cursor_blink_period_;
+  int frame_id = (timestamp - started_time_).IntDiv(cursor_blink_period_);
   CHECK_GE(frame_id, last_identifier_frame_);
 
   ChangeInfoList result;
-  const int frames_in_cycle = frame_cycle_period_ / cursor_blink_period_;
+  const int frames_in_cycle = frame_cycle_period_.IntDiv(cursor_blink_period_);
   for (int i = last_identifier_frame_ + 1; i <= frame_id; ++i) {
     ChangeType type =
         (i % frames_in_cycle == 0) ? ChangeType::FULL : ChangeType::CURSOR;
diff --git a/services/audio/snooper_node_unittest.cc b/services/audio/snooper_node_unittest.cc
index a07945f..31c6063 100644
--- a/services/audio/snooper_node_unittest.cc
+++ b/services/audio/snooper_node_unittest.cc
@@ -625,7 +625,7 @@
   constexpr double kMaxFrequency = 2000;
   constexpr int kNumToneSteps = 10;
 
-  const int64_t step_number = offset / (kTestDuration / kNumToneSteps);
+  const int64_t step_number = offset.IntDiv(kTestDuration / kNumToneSteps);
   const double t = static_cast<double>(step_number) / kNumToneSteps;
   return kMinFrequency + t * (kMaxFrequency - kMinFrequency);
 }
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index bdf5054..ab633177 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -259,6 +259,7 @@
     "//url/ipc:url_ipc",
     "//url/mojom:url_mojom_gurl",
     "//url/mojom:url_mojom_origin",
+    "//third_party/webrtc_overrides:webrtc_component",
   ]
   deps = [
     "//base",
@@ -267,7 +268,6 @@
     "//net",
     "//services/network/public/mojom:cookies_mojom",
     "//services/network/public/mojom:mojom_shared",
-    "//third_party/webrtc_overrides:webrtc_component",
   ]
   defines = [ "IS_NETWORK_CPP_BASE_IMPL" ]
 }
diff --git a/services/network/throttling/throttling_network_interceptor.cc b/services/network/throttling/throttling_network_interceptor.cc
index 12247ff..4a83c2b 100644
--- a/services/network/throttling/throttling_network_interceptor.cc
+++ b/services/network/throttling/throttling_network_interceptor.cc
@@ -104,7 +104,7 @@
     return last_tick;
   }
 
-  int64_t new_tick = (now - offset_) / tick_length;
+  int64_t new_tick = (now - offset_).IntDiv(tick_length);
   int64_t ticks = new_tick - last_tick;
 
   int64_t length = records->size();
diff --git a/third_party/abseil-cpp/BUILD.gn b/third_party/abseil-cpp/BUILD.gn
index dffe05f3..4241143 100644
--- a/third_party/abseil-cpp/BUILD.gn
+++ b/third_party/abseil-cpp/BUILD.gn
@@ -26,7 +26,7 @@
     public_configs = [ ":absl_component_build" ]
 
     if (is_win) {
-      if (target_cpu == "x64") {
+      if (current_cpu == "x64") {
         if (is_debug) {
           sources = [ "symbols_x64_dbg.def" ]
         } else {
@@ -37,14 +37,14 @@
           }
         }
       }
-      if (target_cpu == "x86") {
+      if (current_cpu == "x86") {
         if (is_debug) {
           sources = [ "symbols_x86_dbg.def" ]
         } else {
           sources = [ "symbols_x86_rel.def" ]
         }
       }
-      if (target_cpu == "arm64") {
+      if (current_cpu == "arm64") {
         if (is_debug) {
           sources = [ "symbols_arm64_dbg.def" ]
         } else {
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 068728f1b..31c84f3 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -6760,22 +6760,6 @@
       GetLayoutBox().PhysicalSelfVisualOverflowRect();
 }
 
-void LayoutBox::MutableForPainting::SetPreviousSizeAndLayoutOverflowRect(
-    const LayoutSize& previous_size,
-    const PhysicalRect& previous_layout_overflow_rect) {
-  GetLayoutBox().previous_size_ = previous_size;
-  if (!previous_layout_overflow_rect.offset.IsZero() ||
-      previous_layout_overflow_rect.size !=
-          PhysicalSizeToBeNoop(previous_size)) {
-    auto& rare_data = GetLayoutBox().EnsureRareData();
-    rare_data.has_previous_content_box_and_overflow_rects_ = true;
-    rare_data.previous_physical_layout_overflow_rect_ =
-        previous_layout_overflow_rect;
-    // Other previous_* fields don't matter because they are used for paint
-    // invalidation and we always do full paint invalidation on reattachment.
-  }
-}
-
 RasterEffectOutset LayoutBox::VisualRectOutsetForRasterEffects() const {
   // If the box has subpixel visual effect outsets, as the visual effect may be
   // painted along the pixel-snapped border box, the pixels on the anti-aliased
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h
index 10a69f21..7acd06c 100644
--- a/third_party/blink/renderer/core/layout/layout_box.h
+++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -1619,13 +1619,6 @@
           false;
     }
 
-    // Called from LayoutShiftTracker when we attach this LayoutBox to a node
-    // for which we saved these values when the node was detached from its
-    // original LayoutBox.
-    void SetPreviousSizeAndLayoutOverflowRect(
-        const LayoutSize& previous_size,
-        const PhysicalRect& previous_layout_overflow_rect);
-
    protected:
     friend class LayoutBox;
     MutableForPainting(const LayoutBox& box)
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 1d99fda..fbb5a7b4 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -177,6 +177,7 @@
   Member<void*> members[1];
   // The following fields are in FragmentData.
   PhysicalOffset paint_offset_;
+  PhysicalRect visual_rect_for_layout_shift_tracking;
   std::unique_ptr<int> rare_data_;
 };
 
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
index bde56304..c0a2f1d 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -31,9 +31,6 @@
 
 using ReattachHook = LayoutShiftTracker::ReattachHook;
 
-using ContainingBlockScope = LayoutShiftTracker::ContainingBlockScope;
-ContainingBlockScope* ContainingBlockScope::top_ = nullptr;
-
 namespace {
 
 ReattachHook& GetReattachHook() {
@@ -45,56 +42,33 @@
 constexpr base::TimeDelta kTimerDelay = base::TimeDelta::FromMilliseconds(500);
 const float kMovementThreshold = 3.0;  // CSS pixels.
 
-// Calculates the physical coordinates of the starting point in the current
-// coordinate space. |paint_offset| is the physical offset of the top-left
-// corner. The starting point can be any of the four corners of the box,
-// depending on the writing mode and text direction. Note that the result is
-// still in physical coordinates, just may be of a different corner.
-// See https://wicg.github.io/layout-instability/#starting-point.
-FloatPoint StartingPoint(const PhysicalOffset& paint_offset,
-                         const LayoutBox& box,
-                         const LayoutSize& size) {
-  PhysicalOffset starting_point = paint_offset;
-  auto writing_direction = box.StyleRef().GetWritingDirection();
-  if (UNLIKELY(writing_direction.IsFlippedBlocks()))
-    starting_point.left += size.Width();
-  if (UNLIKELY(writing_direction.IsRtl())) {
-    if (writing_direction.IsHorizontal())
-      starting_point.left += size.Width();
-    else
-      starting_point.top += size.Height();
-  }
-  return FloatPoint(starting_point);
+FloatPoint LogicalStart(const FloatRect& rect, const LayoutObject& object) {
+  const ComputedStyle* style = object.Style();
+  DCHECK(style);
+  auto logical =
+      PhysicalToLogical<float>(style->GetWritingMode(), style->Direction(),
+                               rect.Y(), rect.MaxX(), rect.MaxY(), rect.X());
+  return FloatPoint(logical.InlineStart(), logical.BlockStart());
 }
 
-// Returns the part a rect logically below a starting point.
-PhysicalRect RectBelowStartingPoint(const PhysicalRect& rect,
-                                    const PhysicalOffset& starting_point,
-                                    WritingDirectionMode writing_direction) {
-  PhysicalRect result = rect;
-  if (writing_direction.IsHorizontal())
-    result.ShiftTopEdgeTo(starting_point.top);
-  else if (writing_direction.IsFlippedBlocks())
-    result.ShiftRightEdgeTo(starting_point.left);
-  else
-    result.ShiftLeftEdgeTo(starting_point.left);
-  return result;
-}
-
-float GetMoveDistance(const FloatPoint& old_starting_point,
-                      const FloatPoint& new_starting_point) {
-  FloatSize location_delta = new_starting_point - old_starting_point;
+float GetMoveDistance(const FloatRect& old_rect,
+                      const FloatRect& new_rect,
+                      const LayoutObject& object) {
+  FloatSize location_delta =
+      LogicalStart(new_rect, object) - LogicalStart(old_rect, object);
   return std::max(fabs(location_delta.Width()), fabs(location_delta.Height()));
 }
 
 bool EqualWithinMovementThreshold(const FloatPoint& a,
                                   const FloatPoint& b,
-                                  float threshold_physical_px) {
+                                  const LayoutObject& object) {
+  float threshold_physical_px =
+      kMovementThreshold * object.StyleRef().EffectiveZoom();
   return fabs(a.X() - b.X()) < threshold_physical_px &&
          fabs(a.Y() - b.Y()) < threshold_physical_px;
 }
 
-bool SmallerThanRegionGranularity(const PhysicalRect& rect) {
+bool SmallerThanRegionGranularity(const FloatRect& rect) {
   // The region uses integer coordinates, so the rects are snapped to
   // pixel boundaries. Ignore rects smaller than half a pixel.
   return rect.Width() < 0.5 || rect.Height() < 0.5;
@@ -136,10 +110,6 @@
 
 LayoutShiftTracker::LayoutShiftTracker(LocalFrameView* frame_view)
     : frame_view_(frame_view),
-      // This eliminates noise from the private Page object created by
-      // SVGImage::DataChanged.
-      is_active_(
-          !frame_view_->GetFrame().GetChromeClient().IsSVGImageChromeClient()),
       score_(0.0),
       weighted_score_(0.0),
       timer_(frame_view->GetFrame().GetTaskRunner(TaskType::kInternalDefault),
@@ -150,138 +120,105 @@
       observed_input_or_scroll_(false),
       most_recent_input_timestamp_initialized_(false) {}
 
-bool LayoutShiftTracker::NeedsToTrack(const LayoutObject& object) const {
-  if (!is_active_)
-    return false;
-
-  // SVG elements don't participate in the normal layout algorithms and are
-  // more likely to be used for animations.
-  if (object.IsSVGChild())
-    return false;
-
-  if (object.IsText())
-    return ContainingBlockScope::top_;
-
-  if (!object.IsBox())
-    return false;
-
-  // Don't report shift of anonymous objects. Will report the children because
-  // we want report real DOM nodes.
-  if (object.IsAnonymous())
-    return true;
-
-  // Ignore layout objects that move (in the coordinate space of the paint
-  // invalidation container) on scroll.
-  // TODO(skobes): Find a way to detect when these objects shift.
-  if (object.IsFixedPositioned() || object.IsStickyPositioned())
-    return false;
-
-  if (object.IsLayoutView())
-    return false;
-
-  if (Element* element = DynamicTo<Element>(object.GetNode())) {
-    if (element->IsSliderThumbElement())
-      return false;
-  }
-
-  return true;
-}
-
 void LayoutShiftTracker::ObjectShifted(
-    const LayoutObject& object,
+    const LayoutObject& source,
     const PropertyTreeStateOrAlias& property_tree_state,
-    const PhysicalRect& old_rect,
-    const PhysicalRect& new_rect,
-    const FloatPoint& old_starting_point,
-    const FloatPoint& new_starting_point) {
-  // The caller should ensure these conditions.
-  DCHECK(!old_rect.IsEmpty());
-  DCHECK(!new_rect.IsEmpty());
+    FloatRect old_rect,
+    FloatRect new_rect) {
+  if (old_rect.IsEmpty() || new_rect.IsEmpty())
+    return;
 
-  float threshold_physical_px =
-      kMovementThreshold * object.StyleRef().EffectiveZoom();
-
-  if (EqualWithinMovementThreshold(old_starting_point, new_starting_point,
-                                   threshold_physical_px))
+  if (EqualWithinMovementThreshold(LogicalStart(old_rect, source),
+                                   LogicalStart(new_rect, source), source))
     return;
 
   if (SmallerThanRegionGranularity(old_rect) &&
       SmallerThanRegionGranularity(new_rect))
     return;
 
+  // Ignore layout objects that move (in the coordinate space of the paint
+  // invalidation container) on scroll.
+  // TODO(skobes): Find a way to detect when these objects shift.
+  if (source.IsFixedPositioned() || source.IsStickyPositioned())
+    return;
+
+  // SVG elements don't participate in the normal layout algorithms and are
+  // more likely to be used for animations.
+  if (source.IsSVG())
+    return;
+
+  if (Element* element = DynamicTo<Element>(source.GetNode())) {
+    if (element->IsSliderThumbElement())
+      return;
+  }
+
   const auto& root_state =
-      object.View()->FirstFragment().LocalBorderBoxProperties();
+      source.View()->FirstFragment().LocalBorderBoxProperties();
   FloatClipRect clip_rect =
       GeometryMapper::LocalToAncestorClipRect(property_tree_state, root_state);
-  clip_rect.Intersect(FloatClipRect(FloatRect(
-      FloatPoint(),
-      FloatSize(
-          frame_view_->GetScrollableArea()->VisibleContentRect().Size()))));
 
   // If the clip region is empty, then the resulting layout shift isn't visible
   // in the viewport so ignore it.
-  if (clip_rect.Rect().IsEmpty())
+  if (!clip_rect.IsInfinite() && clip_rect.Rect().IsEmpty())
     return;
 
-  auto transform = GeometryMapper::SourceToDestinationProjection(
-      property_tree_state.Transform(), root_state.Transform());
-  FloatPoint old_starting_point_in_root =
-      transform.MapPoint(old_starting_point);
-  FloatPoint new_starting_point_in_root =
-      transform.MapPoint(new_starting_point);
+  GeometryMapper::SourceToDestinationRect(property_tree_state.Transform(),
+                                          root_state.Transform(), old_rect);
+  GeometryMapper::SourceToDestinationRect(property_tree_state.Transform(),
+                                          root_state.Transform(), new_rect);
 
-  if (EqualWithinMovementThreshold(old_starting_point_in_root,
-                                   new_starting_point_in_root,
-                                   threshold_physical_px))
+  if (EqualWithinMovementThreshold(old_rect.Location(), new_rect.Location(),
+                                   source)) {
     return;
+  }
 
-  if (EqualWithinMovementThreshold(
-          old_starting_point_in_root + frame_scroll_delta_,
-          new_starting_point_in_root, threshold_physical_px)) {
+  if (EqualWithinMovementThreshold(old_rect.Location() + frame_scroll_delta_,
+                                   new_rect.Location(), source)) {
     // TODO(skobes): Checking frame_scroll_delta_ is an imperfect solution to
     // allowing counterscrolled layout shifts. Ideally, we would map old_rect
     // to viewport coordinates using the previous frame's scroll tree.
     return;
   }
 
-  FloatRect old_rect_in_root(old_rect);
-  transform.MapRect(old_rect_in_root);
-  FloatRect new_rect_in_root(new_rect);
-  transform.MapRect(new_rect_in_root);
+  FloatRect clipped_old_rect(old_rect), clipped_new_rect(new_rect);
+  if (!clip_rect.IsInfinite()) {
+    clipped_old_rect.Intersect(clip_rect.Rect());
+    clipped_new_rect.Intersect(clip_rect.Rect());
+  }
 
-  IntRect visible_old_rect =
-      RoundedIntRect(Intersection(old_rect_in_root, clip_rect.Rect()));
-  IntRect visible_new_rect =
-      RoundedIntRect(Intersection(new_rect_in_root, clip_rect.Rect()));
+  IntRect viewport =
+      IntRect(IntPoint(),
+              frame_view_->GetScrollableArea()->VisibleContentRect().Size());
+
+  IntRect visible_old_rect = RoundedIntRect(clipped_old_rect);
+  visible_old_rect.Intersect(viewport);
+  IntRect visible_new_rect = RoundedIntRect(clipped_new_rect);
+  visible_new_rect.Intersect(viewport);
+
   if (visible_old_rect.IsEmpty() && visible_new_rect.IsEmpty())
     return;
 
   // Compute move distance based on unclipped rects, to accurately determine how
   // much the element moved.
-  float move_distance =
-      GetMoveDistance(old_starting_point_in_root, new_starting_point_in_root);
+  float move_distance = GetMoveDistance(old_rect, new_rect, source);
   frame_max_distance_ = std::max(frame_max_distance_, move_distance);
 
 #if DCHECK_IS_ON()
   LocalFrame& frame = frame_view_->GetFrame();
   if (ShouldLog(frame)) {
     DVLOG(2) << "in " << (frame.IsMainFrame() ? "" : "subframe ")
-             << frame.GetDocument()->Url() << ", " << object << " moved from "
-             << old_rect_in_root << " to " << new_rect_in_root
-             << " (visible from " << visible_old_rect << " to "
-             << visible_new_rect << ")";
-    if (old_starting_point_in_root != old_rect_in_root.Location() ||
-        new_starting_point_in_root != new_rect_in_root.Location()) {
-      DVLOG(2) << " (starting point from " << old_starting_point_in_root
-               << " to " << new_starting_point_in_root << ")";
-    }
+             << frame.GetDocument()->Url().GetString() << ", "
+             << source.DebugName() << " moved from " << old_rect.ToString()
+             << " to " << new_rect.ToString() << " (visible from "
+             << visible_old_rect.ToString() << " to "
+             << visible_new_rect.ToString() << ")";
   }
 #endif
 
   region_.AddRect(visible_old_rect);
   region_.AddRect(visible_new_rect);
 
-  if (Node* node = object.GetNode()) {
+  if (Node* node = source.GetNode()) {
     MaybeRecordAttribution(
         {DOMNodeIds::IdForNode(node), visible_old_rect, visible_new_rect});
   }
@@ -336,60 +273,16 @@
     *smallest = attribution;
 }
 
-void LayoutShiftTracker::NotifyBoxPrePaint(
-    const LayoutBox& box,
+void LayoutShiftTracker::NotifyObjectPrePaint(
+    const LayoutObject& object,
     const PropertyTreeStateOrAlias& property_tree_state,
-    const PhysicalRect& old_rect,
-    const PhysicalRect& new_rect,
-    const PhysicalOffset& old_paint_offset,
-    const PhysicalOffset& new_paint_offset) {
-  DCHECK(NeedsToTrack(box));
-  ObjectShifted(box, property_tree_state, old_rect, new_rect,
-                StartingPoint(old_paint_offset, box, box.PreviousSize()),
-                StartingPoint(new_paint_offset, box, box.Size()));
-}
-
-void LayoutShiftTracker::NotifyTextPrePaint(
-    const LayoutText& text,
-    const PropertyTreeStateOrAlias& property_tree_state,
-    const LogicalOffset& old_starting_point,
-    const LogicalOffset& new_starting_point,
-    const PhysicalOffset& old_paint_offset,
-    const PhysicalOffset& new_paint_offset) {
-  DCHECK(NeedsToTrack(text));
-  auto* block = ContainingBlockScope::top_;
-  DCHECK(block);
-  LayoutUnit distance = std::max(
-      (new_starting_point.inline_offset - old_starting_point.inline_offset)
-          .Abs(),
-      (new_starting_point.block_offset - old_starting_point.block_offset)
-          .Abs());
-  if (distance <= block->max_text_shift_distance_)
+    const PhysicalRect& old_visual_rect,
+    const PhysicalRect& new_visual_rect) {
+  if (!IsActive())
     return;
 
-  block->max_text_shift_distance_ = distance;
-  auto writing_direction = text.StyleRef().GetWritingDirection();
-  PhysicalOffset old_physical_starting_point =
-      old_paint_offset + old_starting_point.ConvertToPhysical(writing_direction,
-                                                              block->old_size_,
-                                                              PhysicalSize());
-  PhysicalOffset new_physical_starting_point =
-      new_paint_offset + new_starting_point.ConvertToPhysical(writing_direction,
-                                                              block->new_size_,
-                                                              PhysicalSize());
-
-  PhysicalRect old_rect = RectBelowStartingPoint(
-      block->old_rect_, old_physical_starting_point, writing_direction);
-  if (old_rect.IsEmpty())
-    return;
-  PhysicalRect new_rect = RectBelowStartingPoint(
-      block->new_rect_, new_physical_starting_point, writing_direction);
-  if (new_rect.IsEmpty())
-    return;
-
-  ObjectShifted(text, property_tree_state, old_rect, new_rect,
-                FloatPoint(old_physical_starting_point),
-                FloatPoint(new_physical_starting_point));
+  ObjectShifted(object, property_tree_state, FloatRect(old_visual_rect),
+                FloatRect(new_visual_rect));
 }
 
 double LayoutShiftTracker::SubframeWeightingFactor() const {
@@ -418,7 +311,7 @@
 }
 
 void LayoutShiftTracker::NotifyPrePaintFinished() {
-  if (!is_active_)
+  if (!IsActive())
     return;
   if (region_.IsEmpty())
     return;
@@ -446,7 +339,7 @@
   LocalFrame& frame = frame_view_->GetFrame();
   if (ShouldLog(frame)) {
     DVLOG(1) << "in " << (frame.IsMainFrame() ? "" : "subframe ")
-             << frame.GetDocument()->Url() << ", viewport was "
+             << frame.GetDocument()->Url().GetString() << ", viewport was "
              << (impact_fraction * 100) << "% impacted with distance fraction "
              << move_distance_factor;
   }
@@ -599,6 +492,14 @@
   UpdateInputTimestamp(base::TimeTicks::Now());
 }
 
+bool LayoutShiftTracker::IsActive() {
+  // This eliminates noise from the private Page object created by
+  // SVGImage::DataChanged.
+  if (frame_view_->GetFrame().GetChromeClient().IsSVGImageChromeClient())
+    return false;
+  return true;
+}
+
 std::unique_ptr<TracedValue> LayoutShiftTracker::PerFrameTraceData(
     double score_delta,
     bool input_detected) const {
@@ -676,7 +577,7 @@
     auto& hook = GetReattachHook();
     hook.scope_ = outer_;
     if (!outer_)
-      hook.geometries_before_detach_.clear();
+      hook.visual_rects_.clear();
   }
 }
 
@@ -685,19 +586,17 @@
   if (!hook.scope_)
     return;
   auto* layout_object = node.GetLayoutObject();
-  if (!layout_object || !layout_object->IsBox())
+  if (!layout_object)
     return;
 
-  auto& map = hook.geometries_before_detach_;
+  auto& map = hook.visual_rects_;
   auto& fragment = layout_object->GetMutableForPainting().FirstFragment();
 
   // Save the visual rect for restoration on future reattachment.
-  const auto& box = ToLayoutBox(*layout_object);
-  PhysicalRect layout_overflow_rect = box.PreviousPhysicalLayoutOverflowRect();
-  if (layout_overflow_rect.IsEmpty())
+  PhysicalRect visual_rect = fragment.VisualRectForLayoutShiftTracking();
+  if (visual_rect.IsEmpty())
     return;
-  map.Set(&node, Geometry{layout_overflow_rect, fragment.PaintOffset(),
-                          box.PreviousSize()});
+  map.Set(&node, visual_rect);
 }
 
 void ReattachHook::NotifyAttach(const Node& node) {
@@ -705,25 +604,20 @@
   if (!hook.scope_)
     return;
   auto* layout_object = node.GetLayoutObject();
-  if (!layout_object || !layout_object->IsBox())
+  if (!layout_object)
     return;
-  auto& map = hook.geometries_before_detach_;
+  auto& map = hook.visual_rects_;
   auto& fragment = layout_object->GetMutableForPainting().FirstFragment();
 
-  // Restore geometries that was saved during detach. Note: this does not
-  // affect paint invalidation; we will fully invalidate the new layout object.
+  // Restore the visual rect that was saved during detach.
   auto iter = map.find(&node);
   if (iter == map.end())
     return;
-  ToLayoutBox(layout_object)
-      ->GetMutableForPainting()
-      .SetPreviousSizeAndLayoutOverflowRect(iter->value.size,
-                                            iter->value.layout_overflow_rect);
-  fragment.SetPaintOffset(iter->value.paint_offset);
+  fragment.SetVisualRectForLayoutShiftTracking(iter->value);
 }
 
 void ReattachHook::Trace(Visitor* visitor) const {
-  visitor->Trace(geometries_before_detach_);
+  visitor->Trace(visual_rects_);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.h b/third_party/blink/renderer/core/layout/layout_shift_tracker.h
index 10d3cc0..e855351 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker.h
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.h
@@ -18,13 +18,12 @@
 
 namespace blink {
 
-class LayoutBox;
 class LayoutObject;
-class LayoutText;
 class LocalFrameView;
 class PropertyTreeStateOrAlias;
 class TracedValue;
 class WebInputEvent;
+struct PhysicalRect;
 
 // Tracks "layout shifts" from layout objects changing their visual location
 // between animation frames. See https://github.com/WICG/layout-instability.
@@ -33,38 +32,26 @@
  public:
   explicit LayoutShiftTracker(LocalFrameView*);
   ~LayoutShiftTracker() = default;
-
-  bool NeedsToTrack(const LayoutObject&) const;
-
-  // |old_rect| and |new_rect| are layout overflow rects if the box has layout
-  // overflow and doesn't clip overflow, or border box rect, in the local
-  // transform space (property_tree_state.Transform()). |old_paint_offset| and
-  // |new_paint_offset| are the offsets of the border box rect in the local
-  // transform space, which are the same as |old_rect.offset| and
-  // |new_rect.offset| respectively if the rects are border box rects.
-  // As we don't save the old property tree state, the caller should adjust
-  // |old_rect| and |old_paint_offset| so that we can calculate the correct old
-  // visual representation and old starting point in the initial containing
-  // block and the viewport with the new property tree state in most cases.
-  void NotifyBoxPrePaint(const LayoutBox& box,
-                         const PropertyTreeStateOrAlias& property_tree_state,
-                         const PhysicalRect& old_rect,
-                         const PhysicalRect& new_rect,
-                         const PhysicalOffset& old_paint_offset,
-                         const PhysicalOffset& new_paint_offset);
-
-  void NotifyTextPrePaint(const LayoutText& text,
-                          const PropertyTreeStateOrAlias& property_tree_state,
-                          const LogicalOffset& old_starting_point,
-                          const LogicalOffset& new_starting_point,
-                          const PhysicalOffset& old_paint_offset,
-                          const PhysicalOffset& new_paint_offset);
-
+  // |old_visual_rect| and |new_visual_rect| are in the local transform space:
+  // |property_tree_state.Transform()|. As we don't save the old property tree
+  // state, the caller should adjust |old_visual_rect| as if the difference
+  // between the old and new additional offsets to the layout shift root[1]
+  // caused the difference between the locations of |old_visual_rect| and
+  // |new_visual_rect|, in addition to that caused by the difference between
+  // the old and new paint offsets in the local transform space, so that we can
+  // calculate the total shift from the layout shift root by comparing locations
+  // of |old_visual_rect| and |new_visual_rect|.
+  // [1] See PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext
+  // ::additional_offset_to_layout_shift_root_delta.
+  void NotifyObjectPrePaint(const LayoutObject& object,
+                            const PropertyTreeStateOrAlias& property_tree_state,
+                            const PhysicalRect& old_visual_rect,
+                            const PhysicalRect& new_visual_rect);
   void NotifyPrePaintFinished();
   void NotifyInput(const WebInputEvent&);
   void NotifyScroll(mojom::blink::ScrollType, ScrollOffset delta);
   void NotifyViewportSizeChanged();
-  bool IsActive() const { return is_active_; }
+  bool IsActive();
   double Score() const { return score_; }
   double WeightedScore() const { return weighted_score_; }
   float OverallMaxDistance() const { return overall_max_distance_; }
@@ -96,51 +83,14 @@
 
    private:
     Scope* scope_ = nullptr;
-    struct Geometry {
-      PhysicalRect layout_overflow_rect;
-      PhysicalOffset paint_offset;
-      LayoutSize size;
-    };
-    HeapHashMap<Member<const Node>, Geometry> geometries_before_detach_;
-  };
-
-  class CORE_EXPORT ContainingBlockScope {
-   public:
-    // |old_size| and |new_size| are the border box sizes.
-    // |old_rect| and |new_rect| have the same definition as in
-    // NotifyBoxPrePaint().
-    explicit ContainingBlockScope(const PhysicalSize& old_size,
-                                  const PhysicalSize& new_size,
-                                  const PhysicalRect& old_rect,
-                                  const PhysicalRect& new_rect)
-        : outer_(top_),
-          old_size_(old_size),
-          new_size_(new_size),
-          old_rect_(old_rect),
-          new_rect_(new_rect) {
-      top_ = this;
-    }
-    ~ContainingBlockScope() { top_ = outer_; }
-
-   private:
-    friend class LayoutShiftTracker;
-    ContainingBlockScope* outer_;
-    static ContainingBlockScope* top_;
-    PhysicalSize old_size_;
-    PhysicalSize new_size_;
-    PhysicalRect old_rect_;
-    PhysicalRect new_rect_;
-    LayoutUnit max_text_shift_distance_;
+    HeapHashMap<Member<const Node>, PhysicalRect> visual_rects_;
   };
 
  private:
   void ObjectShifted(const LayoutObject&,
                      const PropertyTreeStateOrAlias&,
-                     const PhysicalRect& old_rect,
-                     const PhysicalRect& new_rect,
-                     const FloatPoint& old_starting_point,
-                     const FloatPoint& new_starting_point);
-
+                     FloatRect old_rect,
+                     FloatRect new_rect);
   void ReportShift(double score_delta, double weighted_score_delta);
   void TimerFired(TimerBase*) {}
   std::unique_ptr<TracedValue> PerFrameTraceData(double score_delta,
@@ -153,7 +103,6 @@
   void SubmitPerformanceEntry(double score_delta, bool input_detected) const;
 
   Member<LocalFrameView> frame_view_;
-  bool is_active_;
 
   // The document cumulative layout shift (DCLS) score for this LocalFrame,
   // unweighted, with move distance applied.
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index ded42b7..6d286c25 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -84,11 +84,10 @@
 
 struct SameSizeAsLayoutText : public LayoutObject {
   uint32_t bitfields : 12;
-  DOMNodeId node_id;
   float widths[4];
   String text;
   void* pointers[2];
-  PhysicalOffset previous_starting_point;
+  DOMNodeId node_id;
 };
 
 ASSERT_SIZE(LayoutText, SameSizeAsLayoutText);
@@ -1691,25 +1690,6 @@
   return PhysicalOffset();
 }
 
-LogicalOffset LayoutText::LogicalStartingPoint() const {
-  if (IsInLayoutNGInlineFormattingContext()) {
-    NGInlineCursor cursor;
-    cursor.MoveTo(*this);
-    if (!cursor)
-      return LogicalOffset();
-    PhysicalOffset physical_offset = cursor.Current().OffsetInContainerBlock();
-    if (StyleRef().GetWritingDirection().IsHorizontalLtr())
-      return {physical_offset.left, physical_offset.top};
-    return physical_offset.ConvertToLogical(
-        StyleRef().GetWritingDirection(),
-        PhysicalSizeToBeNoop(ContainingBlock()->Size()),
-        cursor.Current().Size());
-  }
-  if (const auto* text_box = FirstTextBox())
-    return {text_box->LogicalLeft(), text_box->LogicalTop()};
-  return LogicalOffset();
-}
-
 bool LayoutText::CanOptimizeSetText() const {
   // If we have only one line of text and "contain: layout size" we can avoid
   // doing a layout and only paint in the SetText() operation.
diff --git a/third_party/blink/renderer/core/layout/layout_text.h b/third_party/blink/renderer/core/layout/layout_text.h
index 989653f..0ebfc63 100644
--- a/third_party/blink/renderer/core/layout/layout_text.h
+++ b/third_party/blink/renderer/core/layout/layout_text.h
@@ -332,24 +332,6 @@
 
   void DetachAbstractInlineTextBoxesIfNeeded();
 
-  // Returns the logical location of the first line box.
-  LogicalOffset LogicalStartingPoint() const;
-
-  // For LayoutShiftTracker. Saves the value of LogicalStartingPoint() value
-  // during the previous paint invalidation.
-  LogicalOffset PreviousLogicalStartingPoint() const {
-    return previous_logical_starting_point_;
-  }
-  // This is const because LayoutObjects are const for paint invalidation.
-  void SetPreviousLogicalStartingPoint(const LogicalOffset& point) const {
-    DCHECK_EQ(GetDocument().Lifecycle().GetState(),
-              DocumentLifecycle::kInPrePaint);
-    previous_logical_starting_point_ = point;
-  }
-  static LogicalOffset UninitializedLogicalStartingPoint() {
-    return {LayoutUnit::Max(), LayoutUnit::Max()};
-  }
-
  protected:
   void WillBeDestroyed() override;
 
@@ -466,9 +448,6 @@
   // Used for LayoutNG with accessibility. True if inline fragments are
   // associated to |NGAbstractInlineTextBox|.
   unsigned has_abstract_inline_text_box_ : 1;
-
-  DOMNodeId node_id_ = kInvalidDOMNodeId;
-
   float min_width_;
   float max_width_;
   float first_line_min_width_;
@@ -476,10 +455,6 @@
 
   String text_;
 
-  // This is mutable for paint invalidation.
-  mutable LogicalOffset previous_logical_starting_point_ =
-      UninitializedLogicalStartingPoint();
-
   union {
     // The line boxes associated with this object.
     // Read the LINE BOXES OWNERSHIP section in the class header comment.
@@ -493,6 +468,7 @@
     // Valid only when IsInLayoutNGInlineFormattingContext().
     wtf_size_t first_fragment_item_index_;
   };
+  DOMNodeId node_id_ = kInvalidDOMNodeId;
 };
 
 inline InlineTextBoxList& LayoutText::MutableTextBoxes() {
diff --git a/third_party/blink/renderer/core/paint/box_border_painter.cc b/third_party/blink/renderer/core/paint/box_border_painter.cc
index ccce719..b4a466a9 100644
--- a/third_party/blink/renderer/core/paint/box_border_painter.cc
+++ b/third_party/blink/renderer/core/paint/box_border_painter.cc
@@ -412,13 +412,13 @@
 void ClipQuad(GraphicsContext& context,
               const FloatPoint quad[],
               bool antialiased) {
-  SkPath path;
+  SkPathBuilder path;
   path.moveTo(FloatPointToSkPoint(quad[0]));
   path.lineTo(FloatPointToSkPoint(quad[1]));
   path.lineTo(FloatPointToSkPoint(quad[2]));
   path.lineTo(FloatPointToSkPoint(quad[3]));
 
-  context.ClipPath(path, antialiased ? kAntiAliased : kNotAntiAliased);
+  context.ClipPath(path.detach(), antialiased ? kAntiAliased : kNotAntiAliased);
 }
 
 }  // anonymous namespace
diff --git a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
index 4207af62..cbd4c0b 100644
--- a/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -400,9 +400,8 @@
       box_.ContentSize() != box_.Size())
     return true;
   if ((BackgroundGeometryDependsOnLayoutOverflowRect() ||
-       BackgroundPaintsOntoScrollingContentsLayer() ||
-       !box_.HasOverflowClip()) &&
-      box_.HasLayoutOverflow())
+       BackgroundPaintsOntoScrollingContentsLayer()) &&
+      box_.LayoutOverflowRect() != box_.BorderBoxRect())
     return true;
 
   return false;
diff --git a/third_party/blink/renderer/core/paint/document_marker_painter.cc b/third_party/blink/renderer/core/paint/document_marker_painter.cc
index 604b26a..fd4cb77 100644
--- a/third_party/blink/renderer/core/paint/document_marker_painter.cc
+++ b/third_party/blink/renderer/core/paint/document_marker_painter.cc
@@ -14,6 +14,7 @@
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
+#include "third_party/skia/include/core/SkPathBuilder.h"
 
 namespace blink {
 
@@ -33,7 +34,7 @@
 
   // Adjust the phase such that f' == 0 is "pixel"-centered
   // (for optimal rasterization at native rez).
-  SkPath path;
+  SkPathBuilder path;
   path.moveTo(kMarkerWidth * -3 / 8, kMarkerHeight * 3 / 4);
   path.cubicTo(kMarkerWidth * -1 / 8, kMarkerHeight * 3 / 4,
                kMarkerWidth * -1 / 8, kMarkerHeight * 1 / 4,
@@ -53,7 +54,7 @@
 
   PaintRecorder recorder;
   recorder.beginRecording(kMarkerWidth, kMarkerHeight);
-  recorder.getRecordingCanvas()->drawPath(path, flags);
+  recorder.getRecordingCanvas()->drawPath(path.detach(), flags);
 
   return recorder.finishRecordingAsPicture();
 }
diff --git a/third_party/blink/renderer/core/paint/fragment_data.h b/third_party/blink/renderer/core/paint/fragment_data.h
index a4fa933..f4a3ab0 100644
--- a/third_party/blink/renderer/core/paint/fragment_data.h
+++ b/third_party/blink/renderer/core/paint/fragment_data.h
@@ -35,6 +35,14 @@
     paint_offset_ = paint_offset;
   }
 
+  // Visual rect in the space of the the local transform space.
+  const PhysicalRect& VisualRectForLayoutShiftTracking() const {
+    return visual_rect_for_layout_shift_tracking_;
+  }
+  void SetVisualRectForLayoutShiftTracking(const PhysicalRect& rect) {
+    visual_rect_for_layout_shift_tracking_ = rect;
+  }
+
   // An id for this object that is unique for the lifetime of the WebView.
   UniqueObjectId UniqueId() const {
     DCHECK(rare_data_);
@@ -242,6 +250,8 @@
   RareData& EnsureRareData();
 
   PhysicalOffset paint_offset_;
+  PhysicalRect visual_rect_for_layout_shift_tracking_;
+
   std::unique_ptr<RareData> rare_data_;
 };
 
diff --git a/third_party/blink/renderer/core/paint/object_painter_base.cc b/third_party/blink/renderer/core/paint/object_painter_base.cc
index bb6a75d..be69765 100644
--- a/third_party/blink/renderer/core/paint/object_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/object_painter_base.cc
@@ -229,7 +229,7 @@
               const FloatPoint quad[],
               const Color& color,
               bool antialias) {
-  SkPath path;
+  SkPathBuilder path;
   path.moveTo(FloatPointToSkPoint(quad[0]));
   path.lineTo(FloatPointToSkPoint(quad[1]));
   path.lineTo(FloatPointToSkPoint(quad[2]));
@@ -238,7 +238,7 @@
   flags.setAntiAlias(antialias);
   flags.setColor(color.Rgb());
 
-  context.DrawPath(path, flags);
+  context.DrawPath(path.detach(), flags);
 }
 
 void DrawDashedOrDottedBoxSide(GraphicsContext& graphics_context,
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc
index bcb4ee56..e92d928 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -149,6 +149,30 @@
   DCHECK(tree_context);
   DCHECK_EQ(tree_context->current.paint_offset, fragment_data.PaintOffset());
 
+  // LayoutShiftTracker doesn't track SVG children. Also the visual rect
+  // calculation below works for non-SVG-child objects only.
+  if (!object.IsSVGChild()) {
+    PhysicalRect new_visual_rect = object.LocalVisualRect();
+    new_visual_rect.Move(fragment_data.PaintOffset());
+    // If the layout shift root has changed, LayoutShiftTracker can't use the
+    // current paint property tree to map the old visual rect.
+    if (!tree_context->current.layout_shift_root_changed) {
+      // Adjust old_visual_rect so that LayoutShiftTracker can see the change of
+      // offset caused by change of transforms below the 2d translation root.
+      PhysicalRect old_visual_rect =
+          fragment_data.VisualRectForLayoutShiftTracking();
+      old_visual_rect.Move(
+          -tree_context->current.additional_offset_to_layout_shift_root_delta);
+      object.GetFrameView()->GetLayoutShiftTracker().NotifyObjectPrePaint(
+          object,
+          PropertyTreeStateOrAlias(*tree_context->current.transform,
+                                   *tree_context->current.clip,
+                                   *tree_context->current_effect),
+          old_visual_rect, new_visual_rect);
+    }
+    fragment_data.SetVisualRectForLayoutShiftTracking(new_visual_rect);
+  }
+
   // For performance, we ignore subpixel movement of composited layers for paint
   // invalidation. This will result in imperfect pixel-snapped painting.
   // See crbug.com/833083 for details.
@@ -158,113 +182,6 @@
     context.old_paint_offset = fragment_data.PaintOffset();
 }
 
-void PaintInvalidator::UpdateForLayoutShiftTracking(
-    const LayoutObject& object,
-    FragmentData& fragment_data,
-    PaintInvalidatorContext& context) {
-  const auto* tree_context = context.tree_builder_context_;
-  DCHECK(tree_context);
-
-  if (!object.ShouldCheckGeometryForPaintInvalidation())
-    return;
-
-  auto& layout_shift_tracker = object.GetFrameView()->GetLayoutShiftTracker();
-  if (!layout_shift_tracker.NeedsToTrack(object))
-    return;
-
-  PropertyTreeStateOrAlias property_tree_state(*tree_context->current.transform,
-                                               *tree_context->current.clip,
-                                               *tree_context->current_effect);
-
-  if (object.IsText()) {
-    const auto& text = ToLayoutText(object);
-    LogicalOffset new_starting_point = text.LogicalStartingPoint();
-    LogicalOffset old_starting_point = text.PreviousLogicalStartingPoint();
-    if (new_starting_point == old_starting_point)
-      return;
-    text.SetPreviousLogicalStartingPoint(new_starting_point);
-    if (old_starting_point == LayoutText::UninitializedLogicalStartingPoint())
-      return;
-    // If the layout shift root has changed, LayoutShiftTracker can't use the
-    // current paint property tree to map the old rect.
-    if (tree_context->current.layout_shift_root_changed)
-      return;
-
-    layout_shift_tracker.NotifyTextPrePaint(
-        text, property_tree_state, old_starting_point, new_starting_point,
-        // Similar to the adjustment of old_paint_offset for LayoutBox.
-        context.old_paint_offset -
-            tree_context->current.additional_offset_to_layout_shift_root_delta,
-        fragment_data.PaintOffset());
-    return;
-  }
-
-  DCHECK(object.IsBox());
-  const auto& box = ToLayoutBox(object);
-
-  PhysicalRect new_rect = box.HasOverflowClip()
-                              ? box.PhysicalBorderBoxRect()
-                              : box.PhysicalLayoutOverflowRect();
-  // If we didn't save the previous physical layout overflow rect, (e.g. if
-  // there was no layout overflow or we clipped overflow and there was no other
-  // reason for saving the value) this is the previous PhysicalBorderBoxRect(),
-  // so it is mostly the correct previous rect for layout shift tracking.
-  PhysicalRect old_rect = box.PreviousPhysicalLayoutOverflowRect();
-
-  bool should_report_layout_shift = [&]() -> bool {
-    // If the layout shift root has changed, LayoutShiftTracker can't use the
-    // current paint property tree to map the old rect.
-    if (tree_context->current.layout_shift_root_changed)
-      return false;
-    if (new_rect.IsEmpty() || old_rect.IsEmpty())
-      return false;
-    // The parent of out-of-flow-positioned object may not be its container.
-    if (object.IsOutOfFlowPositioned())
-      return true;
-    // We don't report shift for anonymous objects but report for the children.
-    if (object.Parent()->IsAnonymous())
-      return true;
-    // Report if the parent is in a different transform space.
-    const auto* parent_context = context.ParentContext();
-    if (!parent_context || !parent_context->tree_builder_context_ ||
-        parent_context->tree_builder_context_->current.transform !=
-            tree_context->current.transform)
-      return true;
-    // Report if this object has local movement (i.e. delta of paint offset is
-    // different from that of the parent).
-    return parent_context->fragment_data->PaintOffset() -
-               parent_context->old_paint_offset !=
-           fragment_data.PaintOffset() - context.old_paint_offset;
-  }();
-
-  if (!should_report_layout_shift && !box.ChildrenInline())
-    return;
-
-  new_rect.Move(fragment_data.PaintOffset());
-  old_rect.Move(context.old_paint_offset);
-  // Adjust old_visual_rect so that LayoutShiftTracker can see the change of
-  // offset caused by change of transforms below the 2d translation root.
-  old_rect.Move(
-      -tree_context->current.additional_offset_to_layout_shift_root_delta);
-
-  if (box.ChildrenInline()) {
-    // For layout shift tracking of contained LayoutTexts.
-    context.containing_block_scope_.emplace(
-        PhysicalSizeToBeNoop(box.PreviousSize()),
-        PhysicalSizeToBeNoop(box.Size()), old_rect, new_rect);
-    if (!should_report_layout_shift)
-      return;
-  }
-
-  // Adjust old_paint_offset similarly.
-  PhysicalOffset old_paint_offset =
-      context.old_paint_offset -
-      tree_context->current.additional_offset_to_layout_shift_root_delta;
-  layout_shift_tracker.NotifyBoxPrePaint(box, property_tree_state, old_rect,
-                                         new_rect, old_paint_offset,
-                                         fragment_data.PaintOffset());
-}
-
 bool PaintInvalidator::InvalidatePaint(
     const LayoutObject& object,
     const NGPrePaintInfo* pre_paint_info,
@@ -309,7 +226,6 @@
       context.old_paint_offset =
           context.tree_builder_context_->old_paint_offset;
       UpdateForPaintOffsetChange(object, fragment_data, context);
-      UpdateForLayoutShiftTracking(object, fragment_data, context);
     } else {
       context.tree_builder_context_ = nullptr;
       context.old_paint_offset = fragment_data.PaintOffset();
@@ -333,7 +249,6 @@
         context.old_paint_offset =
             context.tree_builder_context_->old_paint_offset;
         UpdateForPaintOffsetChange(object, *fragment_data, context);
-        UpdateForLayoutShiftTracking(object, *fragment_data, context);
       } else {
         context.tree_builder_context_ = nullptr;
         context.old_paint_offset = fragment_data->PaintOffset();
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.h b/third_party/blink/renderer/core/paint/paint_invalidator.h
index 889e8b27..3417989c 100644
--- a/third_party/blink/renderer/core/paint/paint_invalidator.h
+++ b/third_party/blink/renderer/core/paint/paint_invalidator.h
@@ -6,7 +6,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATOR_H_
 
 #include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/core/layout/layout_shift_tracker.h"
 #include "third_party/blink/renderer/core/paint/paint_property_tree_builder.h"
 #include "third_party/blink/renderer/platform/geometry/layout_rect.h"
 #include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h"
@@ -104,8 +103,6 @@
  private:
   friend class PaintInvalidator;
 
-  base::Optional<LayoutShiftTracker::ContainingBlockScope>
-      containing_block_scope_;
   const PaintPropertyTreeBuilderFragmentContext* tree_builder_context_ =
       nullptr;
 };
@@ -140,9 +137,6 @@
   ALWAYS_INLINE void UpdateForPaintOffsetChange(const LayoutObject&,
                                                 FragmentData&,
                                                 PaintInvalidatorContext&);
-  ALWAYS_INLINE void UpdateForLayoutShiftTracking(const LayoutObject&,
-                                                  FragmentData&,
-                                                  PaintInvalidatorContext&);
 
   Vector<const LayoutObject*> pending_delayed_paint_invalidations_;
 };
diff --git a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
index fdfba2f..87074d1 100644
--- a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
+++ b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -112,7 +112,7 @@
   paint_flags.setStyle(PaintFlags::kStroke_Style);
   paint_flags.setStrokeWidth(1);
 
-  SkPath line_path;
+  SkPathBuilder line_path;
 
   // Draw a dark line, to ensure contrast against a light background
   line_path.moveTo(points[0].X(), points[0].Y());
@@ -120,17 +120,16 @@
   line_path.moveTo(points[2].X(), points[2].Y());
   line_path.lineTo(points[3].X(), points[3].Y());
   paint_flags.setColor(SkColorSetARGB(153, 0, 0, 0));
-  context.DrawPath(line_path, paint_flags);
+  context.DrawPath(line_path.detach(), paint_flags);
 
   // Draw a light line one pixel below the light line,
   // to ensure contrast against a dark background
-  line_path.rewind();
   line_path.moveTo(points[0].X(), points[0].Y() + 1);
   line_path.lineTo(points[1].X() + (on_left ? -1 : 1), points[1].Y());
   line_path.moveTo(points[2].X(), points[2].Y() + 1);
   line_path.lineTo(points[3].X() + (on_left ? -1 : 1), points[3].Y());
   paint_flags.setColor(SkColorSetARGB(153, 255, 255, 255));
-  context.DrawPath(line_path, paint_flags);
+  context.DrawPath(line_path.detach(), paint_flags);
 }
 
 void ScrollableAreaPainter::PaintOverflowControls(
diff --git a/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc b/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc
index 5079751..35788fa1 100644
--- a/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc
+++ b/third_party/blink/renderer/core/scheduler_integration_tests/throttling_test.cc
@@ -271,7 +271,7 @@
     // Tasks are not throttled beyond the default background throttling behavior
     // nor do they get to run more often.
     Vector<String> expected_ouput(
-        kTimeUntilNextCheck / kDefaultThrottledWakeUpInterval,
+        kTimeUntilNextCheck.IntDiv(kDefaultThrottledWakeUpInterval),
         "called onTimer");
     EXPECT_THAT(ConsoleMessages(), expected_ouput);
   }
diff --git a/third_party/blink/renderer/core/svg/animation/smil_time.h b/third_party/blink/renderer/core/svg/animation/smil_time.h
index 10286c6..fe5497d5 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_time.h
+++ b/third_party/blink/renderer/core/svg/animation/smil_time.h
@@ -108,10 +108,11 @@
   SMILTime operator-() const { return -time_; }
   // Division and /modulo are used primarily for computing interval
   // progress/repeats.
-  int64_t operator/(SMILTime other) const {
+  int64_t operator/(SMILTime other) const = delete;
+  int64_t IntDiv(SMILTime other) const {
     DCHECK(IsFinite());
     DCHECK(other.IsFinite());
-    return time_ / other.time_;
+    return time_.IntDiv(other.time_);
   }
   SMILTime operator%(SMILTime other) const {
     DCHECK(IsFinite());
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
index 4d39e27..d57568a 100644
--- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
+++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
@@ -1034,7 +1034,7 @@
     // use a progress value of 1.0, otherwise we should return a value that is
     // within the interval (< 1.0), so subtract the smallest representable time
     // delta in that case.
-    repeat = last_active_duration / simple_duration;
+    repeat = last_active_duration.IntDiv(simple_duration);
     simple_time = last_active_duration % simple_duration;
     if (simple_time) {
       simple_time = simple_time - SMILTime::Epsilon();
@@ -1043,7 +1043,7 @@
       --repeat;
     }
   } else {
-    repeat = active_time / simple_duration;
+    repeat = active_time.IntDiv(simple_duration);
     simple_time = active_time % simple_duration;
   }
   return {clampTo<float>(simple_time.InternalValueAsDouble() /
diff --git a/third_party/blink/renderer/core/svg/unsafe_svg_attribute_sanitization_test.cc b/third_party/blink/renderer/core/svg/unsafe_svg_attribute_sanitization_test.cc
index e7654b8..68576b45 100644
--- a/third_party/blink/renderer/core/svg/unsafe_svg_attribute_sanitization_test.cc
+++ b/third_party/blink/renderer/core/svg/unsafe_svg_attribute_sanitization_test.cc
@@ -54,11 +54,13 @@
 
 namespace blink {
 
-// Pastes htmlToPaste into the body of pageHolder's document, and
-// returns the new content of the body.
-String ContentAfterPastingHTML(DummyPageHolder* page_holder,
-                               const char* html_to_paste) {
-  LocalFrame& frame = page_holder->GetFrame();
+// Pastes |html_to_paste| into the body of |page_holder|'s document, and
+// verifies the new content of the body is safe and sanitized, and contains
+// |expected_partial_contents|.
+void PasteAndVerifySanitization(const char* html_to_paste,
+                                const char* expected_partial_contents) {
+  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
+  LocalFrame& frame = page_holder.get()->GetFrame();
 
   // Setup a mock clipboard host.
   PageTestBase::MockClipboardHostProvider mock_clipboard_host_provider(
@@ -85,22 +87,10 @@
   test::RunPendingTasks();
   EXPECT_TRUE(frame.GetEditor().ExecuteCommand("Paste"));
 
-  return body->innerHTML();
-}
-
-// Integration tests.
-
-TEST(UnsafeSVGAttributeSanitizationTest, pasteAnchor_javaScriptHrefIsStripped) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
-  static const char kUnsafeContent[] =
-      "<svg xmlns='http://www.w3.org/2000/svg' "
-      "     width='1cm' height='1cm'>"
-      "  <a href='javascript:alert()'></a>"
-      "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("</a>"))
+  // Verify that sanitization during pasting strips JavaScript, but keeps at
+  // least |expected_partial_contents|.
+  String sanitized_content = body->innerHTML();
+  EXPECT_TRUE(sanitized_content.Contains(expected_partial_contents))
       << "We should have pasted *something*; the document is: "
       << sanitized_content.Utf8();
   EXPECT_FALSE(sanitized_content.Contains(":alert()"))
@@ -109,108 +99,74 @@
       << sanitized_content.Utf8();
 }
 
+void PasteAndVerifyBasicSanitization(const char* unsafe_content) {
+  static const char kMinimalExpectedContents[] = "</a>";
+  PasteAndVerifySanitization(unsafe_content, kMinimalExpectedContents);
+}
+
+// Integration tests.
+
+TEST(UnsafeSVGAttributeSanitizationTest, pasteAnchor_javaScriptHrefIsStripped) {
+  static const char kUnsafeContent[] =
+      "<svg xmlns='http://www.w3.org/2000/svg' "
+      "     width='1cm' height='1cm'>"
+      "  <a href='javascript:alert()'></a>"
+      "</svg>";
+  PasteAndVerifyBasicSanitization(kUnsafeContent);
+}
+
 TEST(UnsafeSVGAttributeSanitizationTest,
      pasteAnchor_javaScriptXlinkHrefIsStripped) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
   static const char kUnsafeContent[] =
       "<svg xmlns='http://www.w3.org/2000/svg' "
       "     xmlns:xlink='http://www.w3.org/1999/xlink'"
       "     width='1cm' height='1cm'>"
       "  <a xlink:href='javascript:alert()'></a>"
       "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("</a>"))
-      << "We should have pasted *something*; the document is: "
-      << sanitized_content.Utf8();
-  EXPECT_FALSE(sanitized_content.Contains(":alert()"))
-      << "The JavaScript URL is unsafe and should have been stripped; "
-         "instead: "
-      << sanitized_content.Utf8();
+  PasteAndVerifyBasicSanitization(kUnsafeContent);
 }
 
 TEST(UnsafeSVGAttributeSanitizationTest,
      pasteAnchor_javaScriptHrefIsStripped_caseAndEntityInProtocol) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
   static const char kUnsafeContent[] =
       "<svg xmlns='http://www.w3.org/2000/svg' "
       "     width='1cm' height='1cm'>"
       "  <a href='j&#x41;vascriPT:alert()'></a>"
       "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("</a>"))
-      << "We should have pasted *something*; the document is: "
-      << sanitized_content.Utf8();
-  EXPECT_FALSE(sanitized_content.Contains(":alert()"))
-      << "The JavaScript URL is unsafe and should have been stripped; "
-         "instead: "
-      << sanitized_content.Utf8();
+  PasteAndVerifyBasicSanitization(kUnsafeContent);
 }
 
 TEST(UnsafeSVGAttributeSanitizationTest,
      pasteAnchor_javaScriptXlinkHrefIsStripped_caseAndEntityInProtocol) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
   static const char kUnsafeContent[] =
       "<svg xmlns='http://www.w3.org/2000/svg' "
       "     xmlns:xlink='http://www.w3.org/1999/xlink'"
       "     width='1cm' height='1cm'>"
       "  <a xlink:href='j&#x41;vascriPT:alert()'></a>"
       "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("</a>"))
-      << "We should have pasted *something*; the document is: "
-      << sanitized_content.Utf8();
-  EXPECT_FALSE(sanitized_content.Contains(":alert()"))
-      << "The JavaScript URL is unsafe and should have been stripped; "
-         "instead: "
-      << sanitized_content.Utf8();
+  PasteAndVerifyBasicSanitization(kUnsafeContent);
 }
 
 TEST(UnsafeSVGAttributeSanitizationTest,
      pasteAnchor_javaScriptHrefIsStripped_entityWithoutSemicolonInProtocol) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
   static const char kUnsafeContent[] =
       "<svg xmlns='http://www.w3.org/2000/svg' "
       "     width='1cm' height='1cm'>"
       "  <a href='jav&#x61script:alert()'></a>"
       "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("</a>"))
-      << "We should have pasted *something*; the document is: "
-      << sanitized_content.Utf8();
-  EXPECT_FALSE(sanitized_content.Contains(":alert()"))
-      << "The JavaScript URL is unsafe and should have been stripped; "
-         "instead: "
-      << sanitized_content.Utf8();
+  PasteAndVerifyBasicSanitization(kUnsafeContent);
 }
 
 TEST(
     UnsafeSVGAttributeSanitizationTest,
     pasteAnchor_javaScriptXlinkHrefIsStripped_entityWithoutSemicolonInProtocol) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
   static const char kUnsafeContent[] =
       "<svg xmlns='http://www.w3.org/2000/svg' "
       "     xmlns:xlink='http://www.w3.org/1999/xlink'"
       "     width='1cm' height='1cm'>"
       "  <a xlink:href='jav&#x61script:alert()'></a>"
       "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("</a>"))
-      << "We should have pasted *something*; the document is: "
-      << sanitized_content.Utf8();
-  EXPECT_FALSE(sanitized_content.Contains(":alert()"))
-      << "The JavaScript URL is unsafe and should have been stripped; "
-         "instead: "
-      << sanitized_content.Utf8();
+  PasteAndVerifyBasicSanitization(kUnsafeContent);
 }
 
 // Other sanitization integration tests are web tests that use
@@ -220,7 +176,6 @@
 // web tests: there is nowhere to source the unsafe content from.
 TEST(UnsafeSVGAttributeSanitizationTest,
      pasteAnimatedAnchor_javaScriptHrefIsStripped_caseAndEntityInProtocol) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
   static const char kUnsafeContent[] =
       "<svg xmlns='http://www.w3.org/2000/svg' "
       "     width='1cm' height='1cm'>"
@@ -228,22 +183,14 @@
       "    <animate attributeName='href' values='evil;J&#x61VaSCRIpT:alert()'>"
       "  </a>"
       "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("<a href=\"https://www.goo"))
-      << "We should have pasted *something*; the document is: "
-      << sanitized_content.Utf8();
-  EXPECT_FALSE(sanitized_content.Contains(":alert()"))
-      << "The JavaScript URL is unsafe and should have been stripped; "
-         "instead: "
-      << sanitized_content.Utf8();
+  static const char kExpectedContentAfterSanitization[] =
+      "<a href=\"https://www.goo";
+  PasteAndVerifySanitization(kUnsafeContent, kExpectedContentAfterSanitization);
 }
 
 TEST(
     UnsafeSVGAttributeSanitizationTest,
     pasteAnimatedAnchor_javaScriptXlinkHrefIsStripped_caseAndEntityInProtocol) {
-  auto page_holder = std::make_unique<DummyPageHolder>(IntSize(1, 1));
   static const char kUnsafeContent[] =
       "<svg xmlns='http://www.w3.org/2000/svg' "
       "     xmlns:xlink='http://www.w3.org/1999/xlink'"
@@ -254,16 +201,9 @@
       "values='evil;J&#x61VaSCRIpT:alert()'>"
       "  </a>"
       "</svg>";
-  String sanitized_content =
-      ContentAfterPastingHTML(page_holder.get(), kUnsafeContent);
-
-  EXPECT_TRUE(sanitized_content.Contains("<a xlink:href=\"https://www.goo"))
-      << "We should have pasted *something*; the document is: "
-      << sanitized_content.Utf8();
-  EXPECT_FALSE(sanitized_content.Contains(":alert()"))
-      << "The JavaScript URL is unsafe and should have been stripped; "
-         "instead: "
-      << sanitized_content.Utf8();
+  static const char kExpectedContentAfterSanitization[] =
+      "<a xlink:href=\"https://www.goo";
+  PasteAndVerifySanitization(kUnsafeContent, kExpectedContentAfterSanitization);
 }
 
 // Unit tests
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index e1a56fe..dc75f654 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -3518,9 +3518,20 @@
   }
 
   if (IsWebArea()) {
-    if (layout_object->GetFrame()->View()) {
-      out_bounds_in_container.SetSize(
-          FloatSize(layout_object->GetFrame()->View()->Size()));
+    if (LocalFrameView* view = layout_object->GetFrame()->View()) {
+      out_bounds_in_container.SetSize(FloatSize(view->Size()));
+
+      // If it's a popup, account for the popup window's offset.
+      if (view->GetPage()->GetChromeClient().IsPopup()) {
+        IntRect frame_rect = view->FrameToScreen(view->FrameRect());
+        LocalFrameView* root_view =
+            AXObjectCache().GetDocument().GetFrame()->View();
+        IntRect root_frame_rect =
+            root_view->FrameToScreen(root_view->FrameRect());
+        out_bounds_in_container.SetLocation(
+            FloatPoint(frame_rect.X() - root_frame_rect.X(),
+                       frame_rect.Y() - root_frame_rect.Y()));
+      }
     }
     return;
   }
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 1838816..ba719c0 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -4682,15 +4682,17 @@
   if (!ValidateWebGLProgramOrShader("shaderSource", shader))
     return;
   String string_without_comments = StripComments(string).Result();
-  // TODO(danakj): Make validateShaderSource reject characters > 255 (or utf16
-  // Strings) so we don't need to use StringUTF8Adaptor.
-  if (!ValidateShaderSource(string_without_comments))
-    return;
   shader->SetSource(string);
-  WTF::StringUTF8Adaptor adaptor(string_without_comments);
-  const GLchar* shader_data = adaptor.data();
-  // TODO(danakj): Use base::saturated_cast<GLint>.
-  const GLint shader_length = adaptor.size();
+  if (!string_without_comments.Is8Bit() ||
+      !string_without_comments.ContainsOnlyASCIIOrEmpty()) {
+    SynthesizeGLError(
+        GL_INVALID_VALUE, "shaderSource",
+        "Non ASCII character detected after comments are stripped.");
+    return;
+  }
+  const GLchar* shader_data =
+      reinterpret_cast<const GLchar*>(string_without_comments.Characters8());
+  const GLint shader_length = string_without_comments.length();
   ContextGL()->ShaderSource(ObjectOrZero(shader), 1, &shader_data,
                             &shader_length);
 }
@@ -7207,20 +7209,6 @@
   return false;
 }
 
-bool WebGLRenderingContextBase::ValidateShaderSource(const String& string) {
-  for (wtf_size_t i = 0; i < string.length(); ++i) {
-    // line-continuation character \ is supported in WebGL 2.0.
-    if (IsWebGL2OrHigher() && string[i] == '\\') {
-      continue;
-    }
-    if (!ValidateCharacter(string[i])) {
-      SynthesizeGLError(GL_INVALID_VALUE, "shaderSource", "string not ASCII");
-      return false;
-    }
-  }
-  return true;
-}
-
 bool WebGLRenderingContextBase::ValidateShaderType(const char* function_name,
                                                    GLenum shader_type) {
   switch (shader_type) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
index 6edcd81c..e9c377b 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -1215,12 +1215,6 @@
   // Helper function to check if an identifier starts with reserved prefixes.
   bool IsPrefixReserved(const String& name);
 
-  // Helper function to check if all characters in the shader source belong to
-  // the ASCII subset as defined in GLSL ES 1.0 spec section 3.1 Character Set
-  // for WebGL 1.0 and in GLSL ES 3.00 spec section 3.1 Character Set for WebGL
-  // 2.0.
-  bool ValidateShaderSource(const String&);
-
   virtual bool ValidateShaderType(const char* function_name,
                                   GLenum shader_type);
 
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc
index 90ea268..caa1f8f 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_context.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -1188,11 +1188,11 @@
   } else if (valid_w || valid_h) {
     // we are expected to respect the lineJoin, so we can't just call
     // drawLine -- we have to create a path that doubles back on itself.
-    SkPath path;
+    SkPathBuilder path;
     path.moveTo(r.fLeft, r.fTop);
     path.lineTo(r.fRight, r.fBottom);
     path.close();
-    DrawPath(path, flags);
+    DrawPath(path.detach(), flags);
   }
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
index ea7772a..a392dee9 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
@@ -1358,13 +1358,14 @@
     return;
 
   DrawingRecorder recorder(context, client, type, IntRect(0, 0, 100, 100));
-  SkPath path;
-  path.moveTo(0, 0);
-  path.lineTo(0, 100);
-  path.lineTo(50, 50);
-  path.lineTo(100, 100);
-  path.lineTo(100, 0);
-  path.close();
+  SkPathBuilder builder;
+  builder.moveTo(0, 0);
+  builder.lineTo(0, 100);
+  builder.lineTo(50, 50);
+  builder.lineTo(100, 100);
+  builder.lineTo(100, 0);
+  builder.close();
+  SkPath path = builder.detach();
   PaintFlags flags;
   flags.setAntiAlias(true);
   for (unsigned i = 0; i < count; i++)
diff --git a/third_party/blink/renderer/platform/graphics/path.h b/third_party/blink/renderer/platform/graphics/path.h
index c45d259..0d8e817 100644
--- a/third_party/blink/renderer/platform/graphics/path.h
+++ b/third_party/blink/renderer/platform/graphics/path.h
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 #include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkPathBuilder.h"
 #include "third_party/skia/include/core/SkPathMeasure.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index 12b1cbb..192fbaa 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -732,8 +732,8 @@
   // throttling is disabled by default.
   constexpr int kNumTasks =
       base::TimeDelta::FromSeconds(
-          kIntensiveWakeUpThrottling_GracePeriodSeconds_Default) *
-      2 / kTaskPeriod;
+          kIntensiveWakeUpThrottling_GracePeriodSeconds_Default * 2)
+          .IntDiv(kTaskPeriod);
   // This TaskRunner is throttled.
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimerDelayed);
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 1764a22..3e77fac 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -303,8 +303,7 @@
 crbug.com/874695 fast/events/frame-detached-in-mousedown.html [ Slow ]
 crbug.com/874695 fast/events/pointerevents/pointerevent_touch-adjustment_click_target.html [ Slow ]
 crbug.com/874695 fast/events/popup-blocking-timers4.html [ Slow ]
-crbug.com/874695 fast/forms/color/color-suggestion-picker-one-row-appearance.html [ Slow ]
-crbug.com/874695 fast/forms/color/color-suggestion-picker-two-row-appearance.html [ Slow ]
+crbug.com/874695 fast/forms/color/* [ Slow ]
 crbug.com/874695 fast/forms/number/number-spinbutton-gets-disabled-or-readonly.html [ Slow ]
 crbug.com/874695 fast/forms/select/input-select-after-resize.html [ Slow ]
 crbug.com/874695 fast/history/history-back-twice-with-subframes-assert.html [ Slow ]
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations
index db6e00f..b5cdc64 100644
--- a/third_party/blink/web_tests/WebDriverExpectations
+++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -78,6 +78,19 @@
 crbug.com/1020018 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_sucess_input_non_interactable [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_tripleclick.py>>test_tripleclick_at_coordinates [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/minimize_window/minimize.py>>test_fully_exit_fullscreen [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_duplicated_cookie [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/add.py>>test_add_cookie_with_valid_samesite_flag[None] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_get_named_session_cookie [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_get_named_cookie [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/printcmd.py>>test_html_document [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/idlharness.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/webdriver/tests/idlharness.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/webdriver/tests/idlharness.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/inline-flow-shift-vertical-rl.html b/third_party/blink/web_tests/external/wpt/layout-instability/inline-flow-shift-vertical-rl.html
deleted file mode 100644
index 06bc34c..0000000
--- a/third_party/blink/web_tests/external/wpt/layout-instability/inline-flow-shift-vertical-rl.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html>
-<title>Layout Instability: simple block movement is detected</title>
-<link rel="help" href="https://wicg.github.io/layout-instability/" />
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/util.js"></script>
-<body style="writing-mode: vertical-rl">
-<div style="height: 200px; font-size: 20px; line-height: 25px">
-  1AAAAAAA<br>
-  2AAAAAAA<br>
-  3AAAAAAA<br>
-  <div id="inline-block" style="display: inline-block; width: 50px">4AAAAAAA</div><br>
-  5AAAAAAA<br>
-  6AAAAAAA<br>
-  7AAAAAAA<br>
-</div>
-<script>
-
-promise_test(async () => {
-  const watcher = new ScoreWatcher;
-
-  // Wait for the initial render to complete.
-  await waitForAnimationFrames(2);
-
-  // Modify the position of the div.
-  const inline_block = document.querySelector("#inline-block");
-  inline_block.style.width = '100px';
-
-  // The lines below the inline-block are shifted down by 50px.
-  // The implementation may measure the real width of the shifted text
-  // or use the available width (i.e. width of the containing block).
-  // Also tolerate extra 10% error.
-  const text_width = inline_block.offsetWidth;
-  const expectedScoreMin = computeExpectedScore(text_width * (30 * 3 + 50), 50) * 0.9;
-  const expectedScoreMax = computeExpectedScore(200 * (30 * 3 + 50), 50) * 1.1;
-
-  // Observer fires after the frame is painted.
-  assert_equals(watcher.score, 0);
-  await watcher.promise;
-  assert_between_exclusive(watcher.score, expectedScoreMin, expectedScoreMax);
-}, 'Inline flow movement.');
-
-</script>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/inline-flow-shift.html b/third_party/blink/web_tests/external/wpt/layout-instability/inline-flow-shift.html
deleted file mode 100644
index 39550da..0000000
--- a/third_party/blink/web_tests/external/wpt/layout-instability/inline-flow-shift.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html>
-<title>Layout Instability: simple block movement is detected</title>
-<link rel="help" href="https://wicg.github.io/layout-instability/" />
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/util.js"></script>
-<div style="width: 200px; font-size: 20px; line-height: 25px">
-  1AAAAAAA<br>
-  2AAAAAAA<br>
-  3AAAAAAA<br>
-  <div id="inline-block" style="display: inline-block; height: 50px">4AAAAAAA</div><br>
-  5AAAAAAA<br>
-  6AAAAAAA<br>
-  7AAAAAAA<br>
-</div>
-<script>
-
-promise_test(async () => {
-  const watcher = new ScoreWatcher;
-
-  // Wait for the initial render to complete.
-  await waitForAnimationFrames(2);
-
-  // Modify the position of the div.
-  const inline_block = document.querySelector("#inline-block");
-  inline_block.style.height = '100px';
-
-  // The lines below the inline-block are shifted down by 50px.
-  // The implementation may measure the real width of the shifted text
-  // or use the available width (i.e. width of the containing block).
-  // Also tolerate extra 10% error.
-  const text_width = inline_block.offsetWidth;
-  const expectedScoreMin = computeExpectedScore(text_width * (30 * 3 + 50), 50) * 0.9;
-  const expectedScoreMax = computeExpectedScore(200 * (30 * 3 + 50), 50) * 1.1;
-
-  // Observer fires after the frame is painted.
-  assert_equals(watcher.score, 0);
-  await watcher.promise;
-  assert_between_exclusive(watcher.score, expectedScoreMin, expectedScoreMax);
-}, 'Inline flow movement.');
-
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/layout-instability/outline.html b/third_party/blink/web_tests/external/wpt/layout-instability/outline.html
deleted file mode 100644
index 1fed8e9..0000000
--- a/third_party/blink/web_tests/external/wpt/layout-instability/outline.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<title>Layout Instability: outline doesn't contribute to layout shift</title>
-<link rel="help" href="https://wicg.github.io/layout-instability/" />
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/util.js"></script>
-<div id="target" style="width: 300px; height: 300px"></div>
-<script>
-promise_test(async () => {
-  const watcher = new ScoreWatcher;
-
-  // Wait for the initial render to complete.
-  await waitForAnimationFrames(2);
-
-  // Add outline for target. This should not generate a shift.
-  target.style.outline = "10px solid blue";
-
-  await waitForAnimationFrames(3);
-  assert_equals(watcher.score, 0);
-}, "Outline.");
-</script>
diff --git a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
index ac110a84..0096356f 100644
--- a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
+++ b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
@@ -956,15 +956,7 @@
   auto affected_member_expr_matcher =
       memberExpr(member(fieldDecl(hasExplicitFieldDecl(field_decl_matcher))))
           .bind("affectedMemberExpr");
-  auto affected_implicit_expr_matcher = implicitCastExpr(has(expr(anyOf(
-      // Only single implicitCastExpr is present in case of:
-      // |auto* v = s.ptr_field;|
-      expr(affected_member_expr_matcher),
-      // 2nd nested implicitCastExpr is present in case of:
-      // |const auto* v = s.ptr_field;|
-      expr(implicitCastExpr(has(affected_member_expr_matcher)))))));
-  auto affected_expr_matcher =
-      expr(anyOf(affected_member_expr_matcher, affected_implicit_expr_matcher));
+  auto affected_expr_matcher = ignoringImplicit(affected_member_expr_matcher);
 
   // Places where |.get()| needs to be appended =========
   // Given
@@ -1067,10 +1059,9 @@
   //
   // See also the testcases in tests/gen-in-out-arg-test.cc.
   auto affected_in_out_ref_arg_matcher = callExpr(forEachArgumentWithParam(
-      affected_expr_matcher.bind("expr"),
-      hasExplicitParmVarDecl(
-          hasType(qualType(allOf(referenceType(pointee(pointerType())),
-                                 unless(rValueReferenceType())))))));
+      affected_expr_matcher, hasExplicitParmVarDecl(hasType(qualType(
+                                 allOf(referenceType(pointee(pointerType())),
+                                       unless(rValueReferenceType())))))));
   FilteredExprWriter filtered_in_out_ref_arg_writer(&output_helper,
                                                     "in-out-param-ref");
   match_finder.addMatcher(affected_in_out_ref_arg_matcher,
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
index 7a65a24..4444513 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
@@ -334,3 +334,47 @@
 }
 
 }  // namespace affected_implicit_template_specialization
+
+// The test scenario below is based on an example encountered in
+// //cc/layers/picture_layer_impl_unittest.cc:
+//   auto* shared_quad_state = render_pass->quad_list.begin()->shared_quad_state
+// In this example, the AST looks like this:
+//  `-DeclStmt
+//    `-VarDecl shared_quad_state 'const SharedQuadState *' cinit
+//      `-ExprWithCleanups 'const SharedQuadState *'
+//        `-ImplicitCastExpr 'const SharedQuadState *' <LValueToRValue>
+//          `-MemberExpr 'const SharedQuadState *const' lvalue ->shared...state
+//            `-.....
+// The rewriter needs to ignore the implicit ExprWithCleanups and
+// ImplicitCastExpr nodes in order to find the MemberExpr.  If this is
+// implemented incorrectly, then the rewriter won't append |.get()| to fix the
+// |auto*| initialization.
+namespace more_implicit_ast_nodes_trouble {
+
+template <class BaseElementType>
+struct ListContainer {
+  struct ConstIterator {
+    const BaseElementType* operator->() const { return nullptr; }
+  };
+
+  ConstIterator begin() const { return ConstIterator(); }
+};
+
+class SharedQuadState;
+
+struct DrawQuad {
+  CheckedPtr<const SharedQuadState> shared_quad_state;
+};
+
+struct RenderPass {
+  using QuadList = ListContainer<DrawQuad>;
+  QuadList quad_list;
+};
+
+void foo() {
+  RenderPass* render_pass = nullptr;
+  auto* shared_quad_state =
+      render_pass->quad_list.begin()->shared_quad_state.get();
+}
+
+}  // namespace more_implicit_ast_nodes_trouble
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
index 26f4847..efa8857 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
@@ -333,3 +333,46 @@
 }
 
 }  // namespace affected_implicit_template_specialization
+
+// The test scenario below is based on an example encountered in
+// //cc/layers/picture_layer_impl_unittest.cc:
+//   auto* shared_quad_state = render_pass->quad_list.begin()->shared_quad_state
+// In this example, the AST looks like this:
+//  `-DeclStmt
+//    `-VarDecl shared_quad_state 'const SharedQuadState *' cinit
+//      `-ExprWithCleanups 'const SharedQuadState *'
+//        `-ImplicitCastExpr 'const SharedQuadState *' <LValueToRValue>
+//          `-MemberExpr 'const SharedQuadState *const' lvalue ->shared...state
+//            `-.....
+// The rewriter needs to ignore the implicit ExprWithCleanups and
+// ImplicitCastExpr nodes in order to find the MemberExpr.  If this is
+// implemented incorrectly, then the rewriter won't append |.get()| to fix the
+// |auto*| initialization.
+namespace more_implicit_ast_nodes_trouble {
+
+template <class BaseElementType>
+struct ListContainer {
+  struct ConstIterator {
+    const BaseElementType* operator->() const { return nullptr; }
+  };
+
+  ConstIterator begin() const { return ConstIterator(); }
+};
+
+class SharedQuadState;
+
+struct DrawQuad {
+  const SharedQuadState* shared_quad_state;
+};
+
+struct RenderPass {
+  using QuadList = ListContainer<DrawQuad>;
+  QuadList quad_list;
+};
+
+void foo() {
+  RenderPass* render_pass = nullptr;
+  auto* shared_quad_state = render_pass->quad_list.begin()->shared_quad_state;
+}
+
+}  // namespace more_implicit_ast_nodes_trouble
diff --git a/tools/grit/grit/tool/update_resource_ids/parser.py b/tools/grit/grit/tool/update_resource_ids/parser.py
index 3ef76845..da956bb 100644
--- a/tools/grit/grit/tool/update_resource_ids/parser.py
+++ b/tools/grit/grit/tool/update_resource_ids/parser.py
@@ -99,8 +99,8 @@
       _EatString()
       t = 'S'
     else:
-      raise ValueError(
-          'Unknown char \'%s\' at %s' % (ch, _RenderLineCol(data, lo)))
+      raise ValueError('Unknown char %s at %s' %
+                       (repr(ch), _RenderLineCol(data, lo)))
     yield (t, lo, ctx.pos)
   yield ('E', ctx.pos, ctx.pos)  # End sentinel.
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e7d68cc8..365115d 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -148541,7 +148541,8 @@
   </summary>
 </histogram>
 
-<histogram name="SafeBrowsing.V4Database.Size" units="KB" expires_after="M85">
+<histogram name="SafeBrowsing.V4Database.Size" units="KB"
+    expires_after="2021-07-31">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -148621,9 +148622,8 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4GetHash.CacheHit.Result"
-    enum="SafeBrowsingV4FullHashCacheResult" expires_after="M85">
+    enum="SafeBrowsingV4FullHashCacheResult" expires_after="2021-07-31">
   <owner>vakh@chromium.org</owner>
-  <owner>kcarattini@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>Track cache hits for V4 full hashes.</summary>
 </histogram>
@@ -148660,9 +148660,8 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4GetHash.Network.Time" units="ms"
-    expires_after="M85">
+    expires_after="2021-07-31">
   <owner>vakh@chromium.org</owner>
-  <owner>kcarattini@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     The time that it took to receive a response from the Google SafeBrowsing
@@ -148685,9 +148684,8 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4GetHash.Result"
-    enum="SafeBrowsingV4OperationResult" expires_after="M85">
+    enum="SafeBrowsingV4OperationResult" expires_after="2021-07-31">
   <owner>vakh@chromium.org</owner>
-  <owner>kcarattini@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     Track return status from V4 GetHash attempts. The buckets of this histogram
@@ -179490,58 +179488,6 @@
   </details>
 </histogram>
 
-<histogram name="Tabs.TabSearch.WebUI.InitialTabsRenderTime" units="ms"
-    expires_after="M90">
-  <owner>tluk@chromium.org</owner>
-  <owner>robliao@chromium.org</owner>
-  <summary>
-    Records the time taken to load the Tab Search WebUI and render (at least)
-    the initial list of tabs. This is roughly equivalent to 'time to first
-    meaningful paint' for the Tab Search UI.
-  </summary>
-</histogram>
-
-<histogram name="Tabs.TabSearch.WebUI.LoadCompletedTime" units="ms"
-    expires_after="M90">
-  <owner>tluk@chromium.org</owner>
-  <owner>robliao@chromium.org</owner>
-  <summary>
-    The amount of time between the render frame host StartProvisionalLoad event
-    and the render frame DocumentOnLoadCompleted event for the Tab Search WebUI
-    page.
-  </summary>
-</histogram>
-
-<histogram name="Tabs.TabSearch.WebUI.LoadDocumentTime" units="ms"
-    expires_after="M90">
-  <owner>tluk@chromium.org</owner>
-  <owner>robliao@chromium.org</owner>
-  <summary>
-    The amount of time between the render frame host StartProvisionalLoad and
-    DidFinishDocumentLoad events for the Tab Search WebUI page.
-  </summary>
-</histogram>
-
-<histogram name="Tabs.TabSearch.WindowDisplayedDuration" units="seconds"
-    expires_after="M90">
-  <owner>tluk@chromium.org</owner>
-  <owner>robliao@chromium.org</owner>
-  <summary>
-    Tab Search is a feature that allows users to better search their browsers
-    for their desired tabs. It can be opened and closed. This records the amount
-    of time between when a Tab Search bubble is opened and when it is closed.
-
-    The Tab Search UI is a bubble anchored to an element within a browser window
-    and is closed if the user switches to a tab, presses the escape key or
-    performs an action to return focus to the hosting window. The Tab Search UI
-    bubble will also close if the hosting browser window is closed or crashes.
-
-    Users may leave the bubble open for long periods of time without directly
-    interacting with the UI which could result in a long tail of displayed
-    durations.
-  </summary>
-</histogram>
-
 <histogram name="Tabs.TabsStatsDailyEventInterval"
     enum="DailyEventIntervalType" expires_after="M77">
   <owner>sebmarchand@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 7ff4a15..db35cf5 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "f82ee5e9f8355d966f34ad17b4ae6f370a5646ed",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/22b8657a5558de83e88093a85d302f0d0773bb9f/trace_processor_shell.exe"
+            "hash": "85538d973c3e2f37c43b8eeead2944aa61227bc9",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/fce06b20005cdc2e98d266719088811c65eecf0f/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "7feaca03c2586bab7ffd8274ed4d091fcf5c3ea8",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/39c302bccf3a67b44045c5d99badfd0fdea5a432/trace_processor_shell"
+            "hash": "41e5a50575a0679ce4468f753ee9a2e06568ae7a",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/fce06b20005cdc2e98d266719088811c65eecf0f/trace_processor_shell"
         },
         "linux": {
-            "hash": "00fbbdcb3e995dcb25cfb070731624c0ca02a18f",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/39c302bccf3a67b44045c5d99badfd0fdea5a432/trace_processor_shell"
+            "hash": "f2d163e0cfc524ae3d8d0f4434283a93b87fbb38",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/fce06b20005cdc2e98d266719088811c65eecf0f/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/android/delegated_frame_host_android.h b/ui/android/delegated_frame_host_android.h
index e263edf..b605de511 100644
--- a/ui/android/delegated_frame_host_android.h
+++ b/ui/android/delegated_frame_host_android.h
@@ -55,7 +55,7 @@
     return base::TimeDelta::FromSeconds(5);
   }
   static constexpr int64_t FirstFrameTimeoutFrames() {
-    return FirstFrameTimeout() / viz::BeginFrameArgs::DefaultInterval();
+    return FirstFrameTimeout().IntDiv(viz::BeginFrameArgs::DefaultInterval());
   }
 
   // Wait up to 1 second for a frame of the correct size to be produced. Android
@@ -65,7 +65,7 @@
     return base::TimeDelta::FromSeconds(1);
   }
   static constexpr int64_t ResizeTimeoutFrames() {
-    return ResizeTimeout() / viz::BeginFrameArgs::DefaultInterval();
+    return ResizeTimeout().IntDiv(viz::BeginFrameArgs::DefaultInterval());
   }
 
   // Advances the fallback surface to the first surface after navigation. This
diff --git a/ui/base/l10n/time_format.cc b/ui/base/l10n/time_format.cc
index 21830ab..41f1881 100644
--- a/ui/base/l10n/time_format.cc
+++ b/ui/base/l10n/time_format.cc
@@ -130,13 +130,13 @@
     }
   } else if (delta < kYear) {
     DCHECK(with_month_and_year);
-    const int month = delta / kMonth;
+    const int month = delta.IntDiv(kMonth);
     DCHECK_GE(month, 1);
     DCHECK_LE(month, 12);
     formatter->Format(Formatter::UNIT_MONTH, month, &time_string);
   } else {
     DCHECK(with_month_and_year);
-    const int year = delta / kYear;
+    const int year = delta.IntDiv(kYear);
     formatter->Format(Formatter::UNIT_YEAR, year, &time_string);
   }
 
diff --git a/ui/events/gesture_detection/motion_event_buffer_unittest.cc b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
index 35a1bdc..7dfe70a 100644
--- a/ui/events/gesture_detection/motion_event_buffer_unittest.cc
+++ b/ui/events/gesture_detection/motion_event_buffer_unittest.cc
@@ -170,9 +170,9 @@
         event_time + flush_time_delta - event_time_offset;
     base::TimeTicks max_event_time =
         event_time + base::TimeDelta::FromSecondsD(0.5f);
-    const size_t min_expected_events =
-        static_cast<size_t>((max_event_time - flush_time) /
-                            std::max(event_time_delta, flush_time_delta));
+    const size_t min_expected_events = static_cast<size_t>(
+        (max_event_time - flush_time)
+            .IntDiv(std::max(event_time_delta, flush_time_delta)));
 
     MotionEventBuffer buffer(this, true);
 
diff --git a/ui/gfx/paint_throbber.cc b/ui/gfx/paint_throbber.cc
index 034ac5c3..9da3a1b0 100644
--- a/ui/gfx/paint_throbber.cc
+++ b/ui/gfx/paint_throbber.cc
@@ -71,7 +71,7 @@
   constexpr auto kRevolutionTime = base::TimeDelta::FromMilliseconds(1320);
   int64_t twelve_oclock = 90;
   int64_t finish_angle_cc =
-      twelve_oclock + 360 * elapsed_time / kRevolutionTime;
+      twelve_oclock + (360 * elapsed_time).IntDiv(kRevolutionTime);
   int64_t start_angle_cc = std::max(finish_angle_cc - 180, twelve_oclock);
 
   // Negate the angles to convert to the clockwise numbers Skia expects.
@@ -98,7 +98,7 @@
   // This tween is equivalent to cubic-bezier(0.4, 0.0, 0.2, 1).
   double sweep = kMaxArcSize *
                  Tween::CalculateValue(Tween::FAST_OUT_SLOW_IN, arc_progress);
-  const int64_t sweep_frame = elapsed_time / kArcTime;
+  const int64_t sweep_frame = elapsed_time.IntDiv(kArcTime);
   if (sweep_frame % 2 == 0)
     sweep -= kMaxArcSize;
 
@@ -127,7 +127,7 @@
                            SkColor color,
                            const base::TimeDelta& elapsed_time,
                            base::Optional<SkScalar> stroke_width) {
-  const int64_t start_angle = 270 + 360 * elapsed_time / kRotationTime;
+  const int64_t start_angle = 270 + (360 * elapsed_time).IntDiv(kRotationTime);
   PaintThrobberSpinningWithStartAngle(canvas, bounds, color, elapsed_time,
                                       start_angle, stroke_width);
 }
@@ -179,7 +179,7 @@
       color_utils::AlphaBlend(color, waiting_state->color, color_progress);
 
   const int64_t start_angle =
-      waiting_start_angle + 360 * elapsed_time / kRotationTime;
+      waiting_start_angle + (360 * elapsed_time).IntDiv(kRotationTime);
   const base::TimeDelta effective_elapsed_time =
       elapsed_time + waiting_state->arc_time_offset;
 
diff --git a/ui/message_center/BUILD.gn b/ui/message_center/BUILD.gn
index 4df6e85..187c455 100644
--- a/ui/message_center/BUILD.gn
+++ b/ui/message_center/BUILD.gn
@@ -138,8 +138,6 @@
     sources = [
       "fake_message_center.cc",
       "fake_message_center.h",
-      "lock_screen/fake_lock_screen_controller.cc",
-      "lock_screen/fake_lock_screen_controller.h",
     ]
 
     deps = [
@@ -162,6 +160,8 @@
     }
 
     sources = [
+      "lock_screen/fake_lock_screen_controller.cc",
+      "lock_screen/fake_lock_screen_controller.h",
       "message_center_impl_unittest.cc",
       "notification_list_unittest.cc",
       "public/cpp/notification_delegate_unittest.cc",
diff --git a/ui/message_center/views/relative_time_formatter.cc b/ui/message_center/views/relative_time_formatter.cc
index 14ece7e..36b6c67 100644
--- a/ui/message_center/views/relative_time_formatter.cc
+++ b/ui/message_center/views/relative_time_formatter.cc
@@ -69,7 +69,7 @@
   }
 
   int string_id = past ? format.past : format.future;
-  int count = static_cast<int>(absolute / format.range);
+  int count = static_cast<int>(absolute.IntDiv(format.range));
   TimeDelta delay = past
                         ? format.range * (count + 1)
                         : TimeDelta::FromMilliseconds(1) - format.range * count;
diff --git a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
index bfd99ee3..f4ae4b72 100644
--- a/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
+++ b/ui/webui/resources/cr_components/chromeos/os_cr_components.gni
@@ -6,10 +6,14 @@
 
 cr_components_chromeos_namespace_rewrites = [
   "network_config.MojoInterfaceProvider|MojoInterfaceProvider",
+  "settings.receivedEventFromKeyboard|receivedEventFromKeyboard",
+  "settings.LockScreenProgress|LockScreenProgress",
 ]
 
 cr_components_chromeos_auto_imports = [
   "ui/webui/resources/cr_components/chromeos/network/onc_mojo.html|OncMojo",
   "ui/webui/resources/cr_components/chromeos/network/network_listener_behavior.html|NetworkListenerBehavior",
   "ui/webui/resources/cr_components/chromeos/network/mojo_interface_provider.html|MojoInterfaceProviderImpl,MojoInterfaceProvider",
+  "ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html|recordLockScreenProgress,LockScreenProgress",
+  "ui/webui/resources/html/assert.html|assert,assertNotReached",
 ]
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn b/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
index c897fa1..f2d0c18a 100644
--- a/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../os_cr_components.gni")
 
 js_type_check("closure_compile") {
   deps = [
@@ -13,6 +16,7 @@
 
 js_library("pin_keyboard") {
   deps = [
+    ":lock_screen_constants",
     "//ui/webui/resources/cr_elements/cr_input:cr_input",
     "//ui/webui/resources/js:i18n_behavior",
   ]
@@ -52,7 +56,7 @@
     "//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector.m",
     "//ui/webui/resources/js:cr.m",
   ]
-  extra_deps = [ ":lock_screen_constants_module" ]
+  extra_deps = [ ":modulize" ]
 }
 
 js_library("pin_keyboard.m") {
@@ -81,26 +85,36 @@
 
 group("polymer3_elements") {
   public_deps = [
-    ":lock_screen_constants_module",
+    ":modulize",
+    ":pin_keyboard_icon_module",
     ":pin_keyboard_module",
     ":setup_pin_keyboard_module",
   ]
 }
 
-polymer_modulizer("lock_screen_constants") {
-  js_file = "lock_screen_constants.js"
-  html_file = "lock_screen_constants.html"
-  html_type = "dom-module"
-}
-
 polymer_modulizer("pin_keyboard") {
   js_file = "pin_keyboard.js"
   html_file = "pin_keyboard.html"
   html_type = "dom-module"
+  namespace_rewrites = cr_components_chromeos_namespace_rewrites
+  auto_imports = cr_components_chromeos_auto_imports
 }
 
 polymer_modulizer("setup_pin_keyboard") {
   js_file = "setup_pin_keyboard.js"
   html_file = "setup_pin_keyboard.html"
   html_type = "dom-module"
+  namespace_rewrites = cr_components_chromeos_namespace_rewrites
+  auto_imports = cr_components_chromeos_auto_imports
+}
+
+js_modulizer("modulize") {
+  input_files = [ "lock_screen_constants.js" ]
+  namespace_rewrites = cr_components_chromeos_namespace_rewrites
+}
+
+polymer_modulizer("pin_keyboard_icon") {
+  js_file = "pin_keyboard_icon.m.js"
+  html_file = "pin_keyboard_icon.html"
+  html_type = "iron-iconset"
 }
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
index 1dc6eb3..74d26d2 100644
--- a/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
+++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
@@ -1,7 +1,3 @@
-<!-- TODO(crbug.com/603217): Use i18n instead of string literals. Figure out
-                             what i18n to use for keypad, ie, does 1 ABC make
-                             sense in every scenario? -->
-
 <link rel="import" href="../../../html/polymer.html">
 
 <link rel="import" href="../../../cr_elements/cr_button/cr_button.html">
@@ -267,3 +263,7 @@
   </template>
   <script src="pin_keyboard.js"></script>
 </dom-module>
+
+<!-- TODO(crbug.com/603217): Use i18n instead of string literals. Figure out
+                             what i18n to use for keypad, ie, does 1 ABC make
+                             sense in every scenario? -->
diff --git a/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js b/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js
index 1443e8f..eeebe765 100644
--- a/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js
+++ b/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js
@@ -10,9 +10,6 @@
  *
  */
 
-(function() {
-'use strict';
-
 /**
  * Keep in sync with the string keys provided by settings.
  * @enum {string}
@@ -383,5 +380,3 @@
                        '';
   },
 });
-
-})();
diff --git a/ui/webui/resources/cr_components/cr_components_resources_v3.grdp b/ui/webui/resources/cr_components/cr_components_resources_v3.grdp
index fba7d584..53cedf0 100644
--- a/ui/webui/resources/cr_components/cr_components_resources_v3.grdp
+++ b/ui/webui/resources/cr_components/cr_components_resources_v3.grdp
@@ -42,6 +42,22 @@
            file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/network/network_icons.m.js"
            use_base_dir="false"
            type="BINDATA" />
+    <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_SCREEN_CONSTANTS_M_JS"
+           file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.m.js"
+           use_base_dir="false"
+           type="BINDATA" />
+    <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_SETUP_PIN_KEYBOARD_M_JS"
+           file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.m.js"
+           use_base_dir="false"
+           type="BINDATA" />
+    <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_PIN_KEYBOARD_M_JS"
+           file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.m.js"
+           use_base_dir="false"
+           type="BINDATA" />
+    <include name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_PIN_KEYBOARD_ICON_M_JS"
+           file="${root_gen_dir}/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard_icon.m.js"
+           use_base_dir="false"
+           type="BINDATA" />
   </if>
   <if expr="use_nss_certs">
     <include name="IDR_WEBUI_CA_TRUST_EDIT_DIALOG_JS"